UNPKG

bnash

Version:

A command-line editor for bash or compatible shells, aiming to provide great UX and productivity

154 lines (120 loc) 7.39 kB
# Writing plugins To write a custom `nash` plugin, the follwing steps are required: 1. Create a standard node.js module and place it in `~/.nash`. 2. Make that module export a `start` function. In there, place any initialization code, such as registering keyboard shortcut handlers, a custom prompt, line decorator, etc. 3. Edit `~/.nash/nashrc.js` and add the plugin name as a relative path at the end of the exported `plugins` array. When `nash` starts, it requires `~/.nash/nashrc.js` and looks into its exported `plugins` property, which contains an array of plugin paths. It then iterates that array, requiring each plugin and executing its `start` function, if present. ## Sample plugins When `nash` is first executed, it creates the `~/.nash` directory and places several example plugins in there: - `custom-keys.js`: registers 4 additional keyboard shortcuts. - `git-commit-len.js`: registers a line decorator that warns when a git commit text is longer than 50 characters. - `agnoster-prompt.js`: registers a custom prompt function. This plugin is disabled by default. Those plugins are relatively simple, and illustrate `nash` extension points and API. More details about what each plugin does and how do they make use of the extension API can be found in their source code. If you are writing a custom plugin, the best way to learn how to write `nash` plugins is to first look at the sample plugins in `~/.nash`. If more details are required, directly look at the source code of the default plugins inside the `src/plugins` directory of the source distribution of `nash`. ## Extension API ### Keyboard bindings #### `function bindKey(knames, code, desc)` Binds a given key or key combination to a function, which will be invoked by the editor when the key is pressed. **Parameters**: - `knames`: (String or String[]) - The key name. If an array is given, the binding is applied to multiple keys. To learn about the name of a key combination, (e.g. `ctrl-t` or `f3`), type `ctrl-k` at the `nash` prompt, then the requested key combination, and the key name will be displayed, along with the registered handlers, if any. - `code`: (Function) - The function to invoke when the key is pressed. - `desc` (String) desc - A description of what the binding does. When the end user types the bound key and the function provided in the `code` parameter is invoked, it receives an object parameter with the current editor line, split in the `left` and `right` properties with the cursor in the middle. The binding function can either be synchronous or asynchronous: - If synchronous, it must return an object with a `left` and `right` string properties, which will be used to update the editor line. The prompt is not redisplayed for synchronous functions, unless the returned object also contains the `showPrompt` property set to `true`. - If asynchronous, it must return a promise that will resolve when the bound function has finished running. The resolved object will contain the new line `left` and `right` properties. The prompt will be redisplayed upon the promise completion, unless the resolved line object also contains the `showPrompt` property set to `false`. Asynchronous bindings may need to handle keyboard input. Keyboard events can be obtained by calling the `onKeyPressed` function of the `editor` module and passing a listener function. The listener will be automatically discarded after the promise resolves. #### `function unbindKey(kname, fname)` Unbinds a previously bound key handler. **Parameters**: - `kname`: (String) - The key name, as passed in the `bindKey` function. - `fname`: (String) - The name of the function to unbind. #### `function getKeyBindings(kname)` Returns an array with all the bindings registered via the `bindKey` function. **Parameters**: - `kname`: (String) - The key name, as passed in the `bindKey` function. Each element in the array is an object with two properties that match the second and third parameters of the `bindKey` function: - `code`: the handler function - `desc`: the description #### `function getKeyBindingByFunction(fname)` Returns the binding object (with the `code` and `desc` properties) for the function with the given name. **Parameters**: - `fname`: (String) - The name of the function passed in the `bindKey` function. ### Line decoration #### `function registerLineDecorator(decorator)` Registers a *line decorator* function. **Parameters**: - `decorator`: (Function) - The decorator function When the user is typing some text at the command prompt, `nash` invokes all registered line decorator functions, so they can add color or text as required. For example: - The syntax highlight plugin decorates the command line by giving different colors to each part of the line depending on its purpose: command, file, option, quoted string, environment variable, redirection to file, etc. - The suggestions plugin adds gray text at the end of the line, if there is a line in the history that starts with the current text. - The sample `git-commit-len.js` plugin checks for a `git commit -m "..."` command and validates that the length of the message is not longer than a given limit, highlighting the extra length otherwise. When invoked, the registered decorator function receives the following parameters: - `plainLine`: the current command line, without any decoration. As multiple decorators can modify the command line, this text can be used to inspect the command line without the interference of other decorators. - `decoratedLine`: the command line, after being potentially decorated by other registered decorators. This parameter should be used to add any custom decoration, so the effect of all decorators is accumulated. The decorator function must return the resulting decorated line, i.e. with colors and/or additional text, ready to be displayed. For adding color to text, `nash` provides the `colors` module, which relies on the `chalk` package. Decorators are invoked in the order they are registered, which corresponds with the order in which the plugins are listed in the `plugins` array of `~/.nash/nashrc.js`. If a given decorator needs to execute before others, the exported plugins array can be rearranged accordingly. ### Command prompt #### `function setPrompt(promptFunction)` Sets the function that will be invoked for building the prompt string. **Parameters**: - `promptFunction`: (Function) - The function that will be invoked whenever the prompt needs to be displayed. This function should return a string, which will be presented to the user when typing a command. The prompt function receives a single object parameter with relevant information about the environment, which can be optionally used by the prompt function in order to build the prompt string. The object properties are the following: - **cwd**: the current working directory - **username**: the current user name - **hostname**: the host name - **fqdn**: the fully qualified domain name of the host - **retCode**: the return code of the most recent command - **isRemote**: true if `nash` is acting on a remote connection