npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@paoloinfante/terminal-emulator

v0.3.0

Published

A nodeJs browser library for emulating a terminal, with command and argument parsing, and definition of schemes with callbacks.

Downloads

4

Readme

Terminal Emulator

A nodeJs browser library for emulating a terminal, with command and argument parsing, and definition of schemes with callbacks.

Guide

To build your terminal-like interface for web or nodejs based applications, you start from the TerminalEmulator class.

You create an instance of it and set it up with the necessary parameters.

Another important player is the OutputStream class. You have to create your own subclass implementing two methods:

  • abstract write(message: string): void;
  • abstract clear(): void;

The implementation of these methods depends upon whether you're using an HTML div element, a plain string, a console for output, etc.

After you istantiated the class you provide command schemes to it.

A command scheme can be created through the CommandSchemeBuilder helper class, and by providing a combination of command, parameter types and a callback, you define a scheme.

You then add it through the .command(...) method to the terminal emulator instance.

After you defined your schemes with your callbacks, you then call the .parse(string) method on the emulator, and it will tokenize the command line, parse the tokens and assign them to the appropriate category (command name, positional argument, flag argument, value argument). It will then check the schemes and when a match is found it will call the callback defined into the scheme, which is defined like so:

(command: string, args: ArgumentList, outputStream: OutputStream) => Promise<boolean>

The callback returns a promise to support async operations. This is needed when a command executes an HTTP request, or file I/O, to correctly signal the end of the operation to the caller. For instance, it is needed when you want to disable the terminal input while the command is executing.

An example

This is an example OutputStream subclass that prints to the debug console.

class ConsoleOutputStream extends OutputStream {
    constructor() {
        super(''); // No end of line character as console.log prints a newline by default
    }
    write(message: string): void {
        console.log(message);
    }
    clear(): void {
        console.clear();
    }
}

You then istantiate the TerminalEmulator class and set it up with the OutputStream istance.

const stream = new ConsoleOutputStream();
const emulator = new TerminalEmulator(stream, new DefaultLocalization());

The localization parameter object consists of the strings to support localization of the error messages shown to the user.

Now you can start adding schemes to the emulator instance.

const callback = async (
    command: string,
    args: ArgumentList,
    outputStream: OutputStream
) => {
    const name = args.getArgument('name', ValueArgument<string>)?.value;
    outputStream.writeLine(`Hello, ${name}`);

    return true;
};

emulator.command(
    new CommandSchemeBuilder('hello')
        .withValueArgument('name')
        .callback(callback)
        .build()
);

You then parse your terminal input.

const cmdLine = 'hello --name John';
emulator.parse(cmdLine);

Output:

> hello --name John
  Hello, John

Argument types

The supported argument types are:

  • Positional arguments

    Positional arguments don't require a flag indicating the parameter name, you just place them next to the command like this:

    command arg1 arg2 arg3 ...

    new CommandSchemeBuilder('hello').withPositionalArgument();
  • Flag arguments

    Flag arguments are like a switch. When added to the command, the application knows that something has to be done. Example:

    command --arg

    new CommandSchemeBuilder('hello').withFlagArgument('arg');
  • Value arguments

    Value arguments are key/value type arguments. They're essentially a flag argument followed by a positional argument. Equivalent to options passed to the application, they specify how something has to be done, like in this example:

    bake --food bread --temperature high

    new CommandSchemeBuilder('hello').withValueArgument('food');

Help message

An help message is displayed every time a command is invoked with the --help flag argument. If more schemes sharing the same command are added, make sure you add the help message, through the .withHelpMessage(message) function on the builder class, to only one of the entries. Otherwise only the first entry with the help message will be displayed.

The help text will also be displayed when the command is invoked with wrong arguments.