CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-terminal-kit

Comprehensive Node.js terminal library with 256 colors, interactive components, and advanced graphics capabilities

Pending
Overview
Eval results
Files

interactive-input.mddocs/

Interactive Input

Terminal Kit provides comprehensive input capabilities including text fields, menus, file selection, and interactive prompts with full keyboard and mouse support.

Text Input

Input Field

terminal.inputField(options: InputFieldOptions, callback: (error: Error | null, input: string) => void): void;

Create an interactive text input field with history, auto-completion, and validation.

interface InputFieldOptions {
  history?: string[];
  autoComplete?: string[] | Function;
  autoCompleteMenu?: boolean;
  autoCompleteHint?: boolean;
  default?: string;
  placeholder?: string;
  maxLength?: number;
  minLength?: number;
  echo?: boolean;
  echoChar?: string;
  cancelable?: boolean;
  style?: object;
  hintStyle?: object;
  maxAutocomplete?: number;
  keyBindings?: object;
  tokenHook?: Function;
  tokenResetHook?: Function;
  tokenRegExp?: RegExp;
}
const term = require('terminal-kit').terminal;

// Basic input field
term.cyan('Enter your name: ');
term.inputField((error, input) => {
  term.green('\nHello %s!\n', input);
});

// Advanced input with history and auto-completion
const cities = ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'];
term.magenta('Enter a city: ');
term.inputField({
  history: ['New York', 'San Francisco'],
  autoComplete: cities,
  autoCompleteMenu: true,
  maxLength: 50
}, (error, input) => {
  term.green('\nYou selected: %s\n', input);
});

Yes/No Prompts

terminal.yesOrNo(options: YesOrNoOptions, callback: (error: Error | null, result: boolean) => void): void;

Create yes/no confirmation prompts.

interface YesOrNoOptions {
  yes?: string[];
  no?: string[];
  echoYes?: string;
  echoNo?: string;
  default?: boolean;
}
term.cyan('Do you want to continue? [Y/n] ');
term.yesOrNo({ yes: ['y', 'Y'], no: ['n', 'N'] }, (error, result) => {
  if (result) {
    term.green('\nContinuing...\n');
  } else {
    term.red('\nAborted.\n');
  }
});

File Operations

File Input

terminal.fileInput(options: FileInputOptions, callback: (error: Error | null, input: string) => void): void;

Interactive file/directory selection with tab completion.

interface FileInputOptions {
  baseDir?: string;
  autoComplete?: boolean;
  default?: string;
  cancelable?: boolean;
  style?: object;
}
term.cyan('Select a file: ');
term.fileInput({ baseDir: process.cwd() }, (error, input) => {
  if (input) {
    term.green('\nSelected file: %s\n', input);
  }
});

Menu Systems

Single Line Menu

terminal.singleLineMenu(items: string[], options: SingleLineMenuOptions, callback: (error: Error | null, response: MenuResponse) => void): void;

Horizontal menu selection.

interface SingleLineMenuOptions {
  y?: number;
  separator?: string;
  nextPageHint?: string;
  previousPageHint?: string;
  style?: object;
  selectedStyle?: object;
  submittedStyle?: object;
  leftPadding?: string;
  rightPadding?: string;
  keyBindings?: object;
  cancelable?: boolean;
  exitOnUnexpectedKey?: boolean;
}

interface MenuResponse {
  selectedIndex: number;
  selectedText: string;
  x: number;
  y: number;
  canceled: boolean;
  unexpectedKey?: string;
}
const options = ['New', 'Open', 'Save', 'Exit'];
term.singleLineMenu(options, (error, response) => {
  term('\nYou selected: %s\n', response.selectedText);
});

Single Column Menu

terminal.singleColumnMenu(items: string[], options: SingleColumnMenuOptions, callback: (error: Error | null, response: MenuResponse) => void): void;

Vertical menu selection.

interface SingleColumnMenuOptions {
  y?: number;
  style?: object;
  selectedStyle?: object;
  submittedStyle?: object;
  leftPadding?: string;
  selectedLeftPadding?: string;
  rightPadding?: string;
  selectedRightPadding?: string;
  itemMaxWidth?: number;
  keyBindings?: object;
  cancelable?: boolean;
  exitOnUnexpectedKey?: boolean;
  continueOnSubmit?: boolean;
  selectedIndex?: number;
}
const menuItems = [
  'Create new project',
  'Open existing project', 
  'Recent projects',
  'Settings',
  'Exit'
];

term.singleColumnMenu(menuItems, {
  selectedStyle: term.inverse
}, (error, response) => {
  term('\nSelected: %s (index: %d)\n', response.selectedText, response.selectedIndex);
});

Grid Menu

terminal.gridMenu(items: string[], options: GridMenuOptions, callback: (error: Error | null, response: MenuResponse) => void): void;

Grid-based menu layout for multiple columns.

interface GridMenuOptions {
  width?: number;
  x?: number;
  y?: number;
  leftPadding?: string;
  rightPadding?: string;
  itemMaxWidth?: number;
  keyBindings?: object;
  cancelable?: boolean;
  exitOnUnexpectedKey?: boolean;
  style?: object;
  selectedStyle?: object;
  submittedStyle?: object;
}
const colors = [
  'red', 'green', 'blue', 'yellow',
  'cyan', 'magenta', 'white', 'black',
  'brightRed', 'brightGreen', 'brightBlue', 'brightYellow'
];

term.gridMenu(colors, {
  width: 4,
  selectedStyle: term.inverse
}, (error, response) => {
  term('\nSelected color: %s\n', response.selectedText);
});

Progress Indicators

Progress Bar

terminal.progressBar(options: ProgressBarOptions): ProgressBarController;

Create animated progress bars.

interface ProgressBarOptions {
  width?: number;
  percent?: boolean;
  eta?: boolean;
  items?: boolean;
  title?: string;
  barStyle?: object;
  barBracketStyle?: object;
  percentStyle?: object;
  etaStyle?: object;
  itemStyle?: object;
  titleStyle?: object;
  itemSize?: number;
  barChar?: string;
  barHeadChar?: string;
  maxRefreshTime?: number;
  minRefreshTime?: number;
  inline?: boolean;
  syncMode?: boolean;
}

interface ProgressBarController {
  update(updateObject: ProgressBarUpdate): void;
  startItem(name: string): void;
  itemDone(name: string): void;
  stop(): void;
}

interface ProgressBarUpdate {
  progress?: number;
  title?: string;
  eta?: number;
  item?: string;
}
const progressBar = term.progressBar({
  width: 80,
  title: 'Downloading files...',
  eta: true,
  percent: true
});

let progress = 0;
const timer = setInterval(() => {
  progress += 0.1;
  progressBar.update({ progress });
  
  if (progress >= 1) {
    clearInterval(timer);
    progressBar.stop();
    term('\nDownload complete!\n');
  }
}, 100);

Slow Typing Animation

terminal.slowTyping(text: string, options: SlowTypingOptions, callback?: () => void): void;

Animate text typing effect.

interface SlowTypingOptions {
  style?: object;
  delay?: number;
  flashStyle?: object;
  flashDelay?: number;
}
term.slowTyping('Hello, this text will appear slowly...', {
  delay: 100,
  flashStyle: term.brightWhite
}, () => {
  term('\nAnimation complete!\n');
});

Spinner Animation

terminal.spinner(options: SpinnerOptions): AnimatedText;

Create animated spinners for loading indicators.

interface SpinnerOptions {
  animation?: string;
  x?: number;
  y?: number;
  style?: object;
}
// Simple line spinner
const spinner = term.spinner();

// Specific animation type
const colorSpinner = term.spinner('unboxing-color');

// Custom positioned spinner
const positionedSpinner = term.spinner({
  animation: 'dotSpinner',
  x: 10,
  y: 5,
  style: { color: 'cyan' }
});

// Control spinner
setTimeout(() => spinner.animate(false), 3000); // Stop after 3 seconds

Event Handling

Keyboard Events

Terminal Kit provides comprehensive keyboard event handling when input is grabbed.

terminal.grabInput(options?: GrabInputOptions): void;

interface GrabInputOptions {
  mouse?: boolean | string;
  focus?: boolean;
}
term.grabInput({ mouse: 'button' });

term.on('key', (name, matches, data) => {
  term('Key pressed: %s\n', name);
  
  // Handle specific keys
  switch (name) {
    case 'CTRL_C':
      term.releaseInput();
      process.exit();
      break;
    case 'ENTER':
      term.green('Enter pressed!\n');
      break;
    case 'UP':
      term.up(1);
      break;
    case 'DOWN':
      term.down(1);
      break;
  }
});

Mouse Events

term.grabInput({ mouse: 'button' });

term.on('mouse', (name, data) => {
  switch (name) {
    case 'MOUSE_LEFT_BUTTON_PRESSED':
      term.moveTo(data.x, data.y).red('●');
      break;
    case 'MOUSE_RIGHT_BUTTON_PRESSED':
      term.moveTo(data.x, data.y).blue('●');
      break;
    case 'MOUSE_WHEEL_UP':
      term.scrollUp(3);
      break;
    case 'MOUSE_WHEEL_DOWN':
      term.scrollDown(3);
      break;
  }
});

Auto-completion

Custom Auto-completion

autoComplete(inputString: string, possibilities: string[], returnAlternatives?: boolean): string | string[];

Standalone auto-completion function.

const termkit = require('terminal-kit');

const commands = ['help', 'exit', 'clear', 'history', 'settings'];
const input = 'he';
const completion = termkit.autoComplete(input, commands);

console.log(completion); // 'help'

// Get all alternatives
const alternatives = termkit.autoComplete(input, commands, true);
console.log(alternatives); // ['help']

Usage Examples

Interactive CLI Application

const term = require('terminal-kit').terminal;

function showMainMenu() {
  term.clear();
  term.magenta.bold('=== CLI Application ===\n\n');
  
  const options = [
    'Create new item',
    'List items',
    'Search items',
    'Settings',
    'Exit'
  ];
  
  term.singleColumnMenu(options, (error, response) => {
    term('\n');
    
    switch (response.selectedIndex) {
      case 0:
        createItem();
        break;
      case 1:
        listItems();
        break;
      case 2:
        searchItems();
        break;
      case 3:
        showSettings();
        break;
      case 4:
        term.red('Goodbye!\n');
        process.exit();
        break;
    }
  });
}

function createItem() {
  term.cyan('Enter item name: ');
  term.inputField((error, input) => {
    if (input) {
      term.green('\nCreated item: %s\n', input);
    }
    
    term.cyan('\nPress any key to continue...');
    term.grabInput();
    term.once('key', () => {
      term.releaseInput();
      showMainMenu();
    });
  });
}

// Start the application
showMainMenu();

Multi-step Form

const term = require('terminal-kit').terminal;

function collectUserInfo() {
  const user = {};
  
  // Step 1: Name
  term.cyan('Enter your name: ');
  term.inputField({ maxLength: 50 }, (error, name) => {
    user.name = name;
    
    // Step 2: Email
    term.cyan('\nEnter your email: ');
    term.inputField({ maxLength: 100 }, (error, email) => {
      user.email = email;
      
      // Step 3: Confirmation
      term.cyan('\nIs this information correct?\n');
      term.white('Name: %s\n', user.name);
      term.white('Email: %s\n', user.email);
      term.cyan('Confirm? [Y/n] ');
      
      term.yesOrNo({ default: true }, (error, confirmed) => {
        if (confirmed) {
          term.green('\nUser information saved!\n');
        } else {
          term.yellow('\nOperation cancelled.\n');
        }
      });
    });
  });
}

collectUserInfo();

Install with Tessl CLI

npx tessl i tessl/npm-terminal-kit

docs

buffers-graphics.md

colors-styling.md

document-model.md

index.md

interactive-input.md

terminal-control.md

tile.json