# Command

## Overview

**Command** is a powerful and flexible command-line interface (CLI) base built with TypeScript.
It is built on top of the `commander` library to provide a robust framework for creating and managing commands,
options, and arguments. This application is designed to be highly customizable and extendable,
making it suitable for a wide range of use cases.

## Features

- **Command Management**: Easily create, configure, and manage commands with support for subcommands.
- **Options and Arguments**: Define and handle options and arguments with ease, including support for global options.
- **Help System**: Customizable help documentation for commands, options, and arguments.
- **Colorized Output**: Enhanced terminal output with color support using the `chalk` library.
- **Autocomplete**: Built-in support for command and option autocompletion.
- **Logging**: Integrated logging with `pino` for detailed and configurable logging.
- **Error Handling**: Robust error handling and reporting.
- **Input/Output**: Helpers for reading and printing to the console. Adhering to silent/no-interaction/no-color flags

## Installation

To install **Command**, use the following command:

```sh
npm install @radicjs/command
```

## Usage
Commands should be defined in the wrapper function `run` which is exported by the package.
The resulting function should be exported as the default export of the file.

```typescript
import { run } from '@radicjs/command';

export default run(app =>
    app.program
       .name('foo')
       .description('A test command')
       .action(async function () {
           this.out.t`{green All set!}`
           this.log.debug('All these work out of the box');
       }),
);
```
### Default Global Options
By default, the following global options are available:

- `-h, --help`: Display help for command.
- `--log-level <level>`: Set log level (default: `warn`).
- `-v, --verbose`: Enables verbose output.
- `--debug`: Enable debugging output.
- `--no-interaction`: No interaction.
- `--silent`: Disable output.
- `--no-color`: Disable color output.

### Custom global options
Create a new file `run.ts`, wich will then serve as the wrapper for your commands.

```typescript
import { run as _run, gopts } from '../src';

export const run: typeof _run = (...args) => {
    // either clear all options
    gopts.clearOptions();
    // or remove some options
    gopts.removeOption('help');

    // then add some options. the GlobalOptionsCommand has this helper method to add the global options
    gopts.add('-v, --version','output the version number',false).conflicts('V');


    return _run(...args)
}
```

### Help improvements

```typescript
command.configureHelp({
    // enabled by default. Must be set to true for the options below to take effect
    // when set to true, the help output will be improved.
    // you can also sort / disable sections
    useImprovedHelp: true,

    // default values, lower values are shown first. Set value to false to omit from help
    outputOrder: {
        'Usage'             : 10,
        'CommandDescription': 20,
        'CommandsList'      : 30,
        'ArgumentsList'     : 40,
        'OptionsList'       : 50,
        'GlobalOptionsList' : 60,
    },

    // when using a lot of options, it can be helpful to seperate them by newlines.
    // This is disabled by default
    seperateGlobalOptionsByNewLine: true,
    seperateOptionsByNewLine      : true,
});
```

The improved help looks like this (plus some coloring):
```
-h, --help               display help for command       [default: false]
--log-level <level>      set log level                  [allowed: 'trace'|'debug'|'info'|'warn'|'error'|'fatal'] [default: 'warn']
-v, --verbose            enables verbose output         [default: false]
--debug                  enable debugging output        [default: false] [env: DEBUG]
--no-interaction         no interaction
--silent                 disable output                 [default: false]
--no-color               disable color output           [env: NO_COLOR]
--json                   show json output               [default: true]
```


### Input/Output

- The `Command` package provides a number of helper functions for reading and printing to the console. These helpers are designed to be used in conjunction with the `Command` class to provide a consistent and easy-to-use interface for interacting with the terminal.
- They also adhere to the `silent`, `no-interaction`, and `no-color` flags to provide a consistent user experience across different environments.
- They are accessible through the `in` and `out` property on the `Command` instance and the `Application` object
- The `in` and `out` properties are instances of the `Input` and `Output` classes, respectively, which provide a number of methods for interacting with the terminal.
- The `Input` and `Output` class are macroable, meaning you can add your own methods to them to extend their functionality.


> The input questions are powered by the [`inquirer`](https://github.com/SBoudrias/Inquirer.js.git) library.

**Input Definitions**:

```typescript
command.action(async function () {
    await this.in.checkbox({ message: '' /* ...options */ });
    await this.in.confirm({ message: '' /* ...options */ });
    await this.in.number({ message: '' /* ...options */ });
    await this.in.input({ message: '' /* ...options */ });
    await this.in.editor({ message: '' /* ...options */ });
    await this.in.search({ message: '' /* ...options */ });
    await this.in.password({ message: '' /* ...options */ });
    await this.in.expand({ message: '' /* ...options */ });
    await this.in.select({ message: '' /* ...options */ });
    await this.in.rawlist({ message: '' /* ...options */ });
});
```

**Macroable**:
Both the `Input` and `Output` classes are macroable, meaning you can add your own methods to them to extend their functionality.

```typescript
this.in.macro('myMethod', function (arg1, arg2) {
    // your custom method here
});

this.in.myMethod('arg1', 'arg2');
```

**Augmenting**: You can also augment the `Input` and `Output` classes with additional methods.

```typescript
import { Input } from '@radicjs/command';

declare module '@radicjs/command' {
    interface Input {
        myMethod(arg1: string, arg2: string): Promise<string>;
    }
}
```

### Tab completion

@todo write docs

## Examples
Can be found in the [example directory](../example/foo.ts) for more examples.



## Contributing

Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) for more information.

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

