/terminal-in-react

👨‍💻 A tiny component that renders a terminal

Primary LanguageJavaScript

Terminal in React

version size size

A component that renders a terminal

Table of contents

Install

npm install terminal-in-react --save

or if you use yarn

yarn add terminal-in-react

Usage

import React, { Component } from 'react';
import Terminal from 'terminal-in-react';
import 'terminal-in-react/lib/css/index.css';

class App extends Component {
  showMsg = () => 'Hello World'

  render() {
    return (
      <div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }}>
        <Terminal
          color='green'
          backgroundColor='black'
          barColor='black'
          style={{ fontWeight: "bold", fontSize: "1em" }}
          commands={{
            'open-google': () => window.open('https://www.google.com/', '_blank'),
            showmsg: this.showMsg,
            popup: () => alert('Terminal in React')
          }}
          descriptions={{
            'open-google': 'opens google.com',
            showmsg: 'shows a message',
            alert: 'alert', popup: 'alert'
          }}
          msg='You can write anything here. Example - Hello! My name is Foo and I like Bar.'
        />
      </div>
    );
  }
}

Include the CSS

Ensure that terminal-in-react/lib/css/index.css is loaded

Be careful when copying this example because it uses window object ('open-google': () => window.open("https://www.google.com/", "_blank"),) which is only available on the client-side and it will give you an error if you're doing server side rendering.

Working

Adding commands

To add your own command, use prop commands which accepts an object. This objects then maps command name -> command function.

Let's take an example. You want to open a website with a command open-google

<Terminal commands={{ 'open-google': () => window.open("https://www.google.com/", "_blank")}} />

Adding description of your command

Add a description of your command using prop description.

<Terminal descriptions={{ 'open-google': 'opens google' }} />

Console logging

You can have the terminal watch console.log/info function and print out. It does so by default.

<Terminal watchConsoleLogging />

Command passthrough

You can have the terminal pass out the cmd that was input

<Terminal commandPassThrough={cmd => `-PassedThrough:${cmd}: command not found`} />

Async handling of commands

you can also handle the result with a callback

<Terminal
  commandPassThrough={(cmd, print) => {
    // do something async
    print(`-PassedThrough:${cmd}: command not found`);
  }}
/>

Minimise, maximise and close the window

Hide the default options

<Terminal descriptions={{ color: false, show: false, clear: false }} />

This will hide the option color, show and clear.

Advanced commands

You can give your commands options and get them back parsed to the method. Using this method will also give your command a build in help output. With the option -h or --help.

<Terminal
  commands={{
    color: {
      method: (args, print, runCommand) => {
        print(`The color is ${args._[0] || args.color}`);
      },
      options: [
        {
          name: 'color',
          description: 'The color the output should be',
          defaultValue: 'white',
        },
      ],
    },
  }}
/>

The command API has three parameters arguments, print, and runCommand.

  • arguments will be an array of the input split on spaces or and object with parameters meeting the options given as well as a _ option with any strings given after the options.
  • print is a method to write a new line to the terminals output. Any string returned as a result of a command will also be printed.
  • runCommand is a method to call other commands it takes a string and will attempt to run the command given

Let's take an another example -

<Terminal
  commands={{
    'type-text': (args, print, runCommand) => {
      const text = args.slice(1).join(' ');
      print('');
      for (let i = 0; i < text.length; i += 1) {
        setTimeout(() => {
          runCommand(`edit-line ${text.slice(0, i + 1)}`);
        }, 100 * i);
      }
    }
  }}
/>

Using plugins 🔥

We have also developed a plugin system for the <Terminal /> component which helps you develop custom plugins. Here is one example of plugin which creates a fake file system called terminal-in-react-pseudo-file-system-plugin.

Instantiating the plugin

import PseudoFileSystem from 'terminal-in-react-pseudo-file-system-plugin'

<Terminal
  plugins={[
    new PseudoFileSystem(),
  ]}
/>

Awesome! Right? Let us know if you make something interesting 😃

More features

Tab autocomplete

Multiline input

via shift + enter

Check history of your commands

using arrow down and up keys

Keyboard shortcuts

You can define keyboard shortcuts. They have to be grouped by os. The three available are win, darwin, and linux. You can group multiple os by a , for example if the shortcut was for all platforms win,darwin,linux would be fine as a key

<Terminal
  shortcuts={{
    'darwin,win,linux': {
      'ctrl + a': 'echo whoo',
    },
  }}
/>

But you might want to specific

<Terminal
  shortcuts={{
    'win': {
      'ctrl + a': 'echo hi windows',
    },
    'darwin': {
      'cmd + a': 'echo hi mac'
    },
    'linux': {
      'ctrl + a': 'echo hi linux'
    }
  }}
/>

You can mix and match

<Terminal
  shortcuts={{
    'win,linux': {
      'ctrl + b': 'echo we are special',
    },
    'win': {
      'ctrl + a': 'echo hi windows',
    },
    'darwin': {
      'cmd + a': 'echo hi mac'
    },
    'linux': {
      'ctrl + a': 'echo hi linux'
    }
  }}
/>

The value of the shortcut should be a command to run.

Customization

Use

  • prop color to change the color of the text.
  • prop backgroundColor to change the background.
  • prop barColor to change the color of bar.
  • prop prompt to change the prompt (>) color.

Follow me on Twitter @NTulswani for new updates and progress 😄

API

Props Type Default
color string 'green'
backgroundColor string 'black'
prompt string 'green'
barColor string 'black'
description object {}
commands object { clear: this.clearScreen(), help: this.showHelp(), show: this.showMsg() }
msg string -
watchConsoleLogging bool false
commandPassThrough function null
promptSymbol string >
plugins array [ { name: '', load: new Plugin(), commands: {} descriptions: {} } ]

Built-in commands

  • clear - Clears the screen
  • help - List all the commands
  • show - Shows a msg if any
  • echo - Display the input message
  • edit-line - Edits the last line or a given line using the -l argument

Where to use ?

  • Embed it as a toy on your website
  • For showcasing
  • Explain any of your project using this terminal component
  • or just play with it

You want a X feature

Sure! Check our todolist or create an issue and I will look into it.

Contributing

Contributing Guide

Troubleshooting

Getting build errors when using create-react-app

Style issues when maximizing

  • Set the style to height: 100vh on parent element.