npm package: @j-o-r/cli
Description: This project provides a command line interface (CLI) for creating interactive dialogs
Author: Jorrit Duin
Latest version: 2.1.5

# Interactive CLI Framework

A CLI framework with mode-based input handling, command processing, and terminal control for building interactive command-line applications.

## Features

- **Mode-based terminal output** (user, log, system, error, assistant, etc.)
- **Command parsing and execution** with built-in system commands
- **Interactive questions and selections** (yes/no, multiple choice)
- **Custom key mappings** for keyboard shortcuts
- **Spinner controls** and terminal manipulation
- **Event-driven architecture** with graceful error handling

## Installation

```javascript
import cli from '@j-o-r/cli';
```

## Quick Start

```javascript
// Set up input handler (required)
cli.inputHandler = async (input) => {
  cli.focus('assistant');
  cli.write(`echo ${input}`);
  cli.focus(); // Back to user input
};

// Optional: Custom exit handler
cli.exitHandler = async (code) => {
  console.log('Cleaning up...');
  process.exit(code);
};

// Start the CLI
cli.focus('log');
cli.write('Welcome! Type something...');
cli.focus(); // Switch to user input mode
```

## Core API

### Input/Output

```javascript
// Write output (only when not in user mode)
cli.write('Hello world');
cli.write('No newline', false);

// Different output modes
cli.focus('log');       // Log output
cli.focus('error');     // Error output  
cli.focus('assistant'); // Assistant output
cli.focus('user');      // User input mode
```

### Interactive Questions

```javascript
// Simple question
const name = await cli.question('What is your name? ');

// Yes/no question
const confirmed = await cli.yesNo('Are you sure? ');

// Multiple choice selection
const choice = await cli.select('Choose option:', [
  'Option 1',
  'Option 2', 
  'Option 3'
]);
```

### Key Mappings

```javascript
cli.registerKeyMappings([
  { 
    name: 'd', ctrl: true, meta: false, shift: false, 
    handler: async () => process.exit(0) // Ctrl+D to exit
  },
  { 
    name: 'r', ctrl: true, meta: false, shift: false, 
    handler: async () => cli.clear() // Ctrl+R to clear
  }
]);
```

### Utility Functions

```javascript
// Terminal control
cli.clear();           // Clear screen
cli.startSpinner();    // Show loading spinner
cli.stopSpinner();     // Hide spinner

// Logging
cli.log('Debug info'); // Log
cli.error('Error!');   // Error output
```

### Custom Roles

```javascript
// Create custom output modes
cli.setRole('debug', '[DEBUG] ', 'brightGreen');
cli.focus('debug');
cli.write('Debug message');
```

## Built-in Commands

The framework includes built-in system commands that can be used in user input:

- `>edit<` - Open the default editor (vim, nano, helix). Fine tune the user input.
- `My text >paste< here` - Clipboard operations, paste clipboard and opens an editor  
- `>#!bash cat ./README.md<` - Execute a bash command and opens an editor 

## Mode System

The CLI operates in different modes that control input/output behavior:

- **`user`** - Accepts user input, processes commands
- **`log`** - For logging output
- **`system`** - System messages
- **`error`** - Error output
- **`assistant`** - Assistant responses
- **`util`** - Utility prompts (questions, selections)

## Error Handling

The framework provides robust error handling:

- Graceful shutdown on signals (SIGINT, SIGTERM, etc.)
- Uncaught exception handling
- 5-second timeout for cleanup operations
- Custom exit handlers

## Example Application

```javascript
#!/usr/bin/env node
import cli from '@j-o-r/cli';

// Register shortcuts
cli.registerKeyMappings([
  { name: 'd', ctrl: true, meta: false, shift: false, 
    handler: async () => process.exit(0) }
]);

// Handle user input
cli.inputHandler = async (input) => {
  if (!input) return;
  
  cli.focus('log');
  cli.write(`You typed: ${input}`);
  
  const name = await cli.question('What is your name? ');
  const happy = await cli.yesNo(`${name}, are you happy? `);
  
  cli.focus('assistant');
  cli.write(happy ? 'Great to hear!' : 'Hope things get better!');
  
  cli.focus(); // Back to user input
};

// Start the application
cli.focus('log');
cli.write('Welcome to the example app!');
cli.focus();
```

## API Reference

| Method | Description |
|--------|-------------|
| `inputHandler(input)` | Handle user input (must override) |
| `exitHandler(code)` | Handle application exit |
| `focus(role)` | Switch to specific mode |
| `write(content, newline)` | Write to console |
| `question(prompt)` | Ask question, return answer |
| `yesNo(prompt)` | Ask yes/no, return boolean |
| `select(prompt, choices)` | Multiple choice selection |
| `registerKeyMappings(keys)` | Register keyboard shortcuts |
| `setRole(name, prompt, color)` | Create custom role |
| `clear()` | Clear terminal screen |
| `log(message)` | Log with formatting |
| `error(err)` | Display error |
| `stop()` | Graceful shutdown |

## License

MIT