🐚 Coquille
Coquille is React component that renders a terminal on the browser with some built-in features.
Algolia web CLI is built on top of Coquille! See more here.
✨ Features
- Command parsing (with usage of double quotes
"
and single quotes '
for values)
- Suggestions for commands, sub commands, arguments, flag names, flag values (single or comma separated)
- Terminal shortcuts
CTRL+L
: clear terminal
CTRL+U
: erase current line
CTRL+A
: place cursor to the beginning of the line
- Automatic errors based on commands structure (wrong flag or argument) is run
- Click on previous command to copy to clipboard
💻 Installation
To add the library to your project, run
pnpm/yarn add @algolia/coquille
or
npm install @algolia/coquille
😌 Quickstart
import Coquille, { Commands } from '@algolia/coquille';
const commands: Commands = {
ls: {
shortDesc: 'List mocked files and folders',
args: { nbArgs: 0 },
run: () => (
<ul>
{['readme.txt', 'index.js', 'coquille.ts'].map((fileName) => (
<li key={fileName}>{fileName}</li>
))}
</ul>
),
},
};
const MyTerminal = () => (
<Coquille
className="my-coquille-class"
promptPrefix={<span className="my-prefix-class">{'$ >'}</span>}
commands={commands}
runOnStart={runOnStart}
/>
);
To define a command with typed flags:
import { Command, FlagValues, RunCommand } from './types';
interface Flags extends FlagValues {
l: boolean;
}
const run: RunCommand<Flags> = async ({ flags }) => {
if (flags && flags.l) {
}
return <ul>...</ul>;
};
const ls: Command<Flags> = {
shortDesc: 'ls – list directory contents',
args: { nbArgs: 0 },
flags: {
l: {
type: 'boolean',
shortDesc:
'List files in the long format, as described in the The Long Format subsection below',
},
},
run,
};
export default ls as Command;
📖 Documentation
Guide
Props interface
interface CoquilleProps {
commands: Commands;
promptPrefix?: ReactNode;
runOnStart?: RunCommand;
onCommandRun?: (rawCommand: string, parsedCommand?: ParsedCommand) => void;
}
Commands definition
The shell uses a commands
object props to parse, define and run commands in the Terminal:
type Commands = {
[name: string]: Command;
};
type Command<F extends FlagValues = FlagValues> = {
shortDesc?: string;
help?: HelpFunction;
run?: RunCommand<F>;
args?: {
nbArgs: number;
suggestions?: Suggestion[];
};
flags?: Flags;
_?: Commands;
};
type Suggestion = {
name: string;
alias?: string;
description?: string;
};
type FlagType = string | number | boolean;
type FlagValues = {
[name: string]: FlagType | FlagType[];
};
type Flags = {
[flagName: string]: Flag;
};
type Flag = {
shortDesc: string;
type: 'string' | 'number' | 'boolean';
multiple?: boolean;
shorthand?: string;
suggestions?: Suggestion[];
};
type ParsedCommand<F extends FlagValues = FlagValues> = {
command: string[];
args?: string[];
flags?: F;
};
type RunCommand<F extends FlagValues = FlagValues> = (
command: ParsedCommand<F>,
shell: {
input: RefObject<HTMLInputElement>; // ref of the input
inputValue: string; // input value of the current command
setInputValue: (value: string) => void; // set input value
history: string[]; // history of previous commands
}
) => Promise<ReactNode> | ReactNode;
export type HelpFunction = (args: {
shortDesc?: string;
subcommands?: Commands;
flags?: Flags;
}) => ReactNode;
Helpers
Functions
runCommandInTerminal
: run the specified command in the terminal programmatically. Useful to create button that runs a command (in a help command output for example).
RunCommandInTerminal = (args: {
command: string;
input: React.RefObject<HTMLInputElement>;
setInputValue: (value: string) => void;
}) => void;
dispatchKeyboardEventInTerminal
: dispatch the specified keyboard event in the terminal programmatically. Useful to simulate user action (in an interactive demo for example).
DispatchKeyboardEventInTerminal = (args: {
event: { type: string; eventInitDict?: KeyboardEventInit };
input: React.RefObject<HTMLInputElement>;
}) => void;
Components
<Help />
: renders the help standard output of a command.
Example:
<Help
shortDesc={...}
subcommands={...}
flags={...}
usage="algolia <command> <subcommand> [flags]"
examples={[
`$ algolia search MY_INDEX --query "foo"`,
`$ algolia profile list`,
`$ algolia indices list`,
]}
learnMore={
<>
<p>
{`Use 'algolia <command> <subcommand> --help' for more information about a command.`}
</p>
<p>
Read the documentation at{" "}
<Link href="https://algolia.com/doc/tools/cli">
https://algolia.com/doc/tools/cli
</Link>
</p>
</>
}
/>
🛟 Support
Found a bug? Open a new issue and help us to improve the code!