Terminal in React

A component that renders a terminal

README

Terminal in React [![Downloads][npm-dm]][package-url] [![Downloads][npm-dt]][package-url] [![NPM Version][npm-v]][package-url] [![Dependencies][deps]][package-url] [![Dev Dependencies][dev-deps]][package-url] [![License][license]][package-url]

size
size


A component that renders a terminal


Table of contents















Install


  1. ```
  2. npm install terminal-in-react --save
  3. ```
or if you use yarn

  1. ```
  2. yarn add terminal-in-react
  3. ```

This package also depends on react so make sure you've already installed it.

Usage


  1. ``` js
  2. import React, { Component } from 'react';
  3. import Terminal from 'terminal-in-react';

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

  6.   render() {
  7.     return (
  8.       <div
  9.         style={{
  10.           display: "flex",
  11.           justifyContent: "center",
  12.           alignItems: "center",
  13.           height: "100vh"
  14.         }}
  15.       >
  16.         <Terminal
  17.           color='green'
  18.           backgroundColor='black'
  19.           barColor='black'
  20.           style={{ fontWeight: "bold", fontSize: "1em" }}
  21.           commands={{
  22.             'open-google': () => window.open('https://www.google.com/', '_blank'),
  23.             showmsg: this.showMsg,
  24.             popup: () => alert('Terminal in React')
  25.           }}
  26.           descriptions={{
  27.             'open-google': 'opens google.com',
  28.             showmsg: 'shows a message',
  29.             alert: 'alert', popup: 'alert'
  30.           }}
  31.           msg='You can write anything here. Example - Hello! My name is Foo and I like Bar.'
  32.         />
  33.       </div>
  34.     );
  35.   }
  36. }
  37. ```

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

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

Adding description of your command 💁🏼‍♂️


Add a description of your command using prop description.

  1. ``` js
  2. <Terminal descriptions={{ 'open-google': 'opens google' }} />
  3. ```

Console logging


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

  1. ``` js
  2. <Terminal watchConsoleLogging />
  3. ```


Command passthrough


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

  1. ``` js
  2. <Terminal commandPassThrough={cmd => `-PassedThrough:${cmd}: command not found`} />
  3. ```

Async handling of commands 😎

you can also handle the result with a callback
  1. ``` js
  2. <Terminal
  3.   commandPassThrough={(cmd, print) => {
  4.     // do something async
  5.     print(`-PassedThrough:${cmd}: command not found`);
  6.   }}
  7. />
  8. ```

Minimise, maximise and close the window


  1. ``` js
  2. <Terminal
  3.   closedTitle='OOPS! You closed the window.'
  4.   closedMessage='Click on the icon to reopen.'
  5. />
  6. ```


Hide the default options


  1. ``` js
  2. <Terminal descriptions={{ color: false, show: false, clear: false }} />
  3. ```

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.

  1. ``` js
  2. <Terminal
  3.   commands={{
  4.     color: {
  5.       method: (args, print, runCommand) => {
  6.         print(`The color is ${args._[0] || args.color}`);
  7.       },
  8.       options: [
  9.         {
  10.           name: 'color',
  11.           description: 'The color the output should be',
  12.           defaultValue: 'white',
  13.         },
  14.       ],
  15.     },
  16.   }}
  17. />
  18. ```


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 -

  1. ``` js
  2. <Terminal
  3.   commands={{
  4.     'type-text': (args, print, runCommand) => {
  5.       const text = args.slice(1).join(' ');
  6.       print('');
  7.       for (let i = 0; i < text.length; i += 1) {
  8.         setTimeout(() => {
  9.           runCommand(`edit-line ${text.slice(0, i + 1)}`);
  10.         }, 100 * i);
  11.       }
  12.     }
  13.   }}
  14. />

  15. ```


Using plugins 🔥



We have also developed a plugin system for the `` 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](https://github.com/jcgertig/terminal-in-react-pseudo-file-system-plugin).

Instantiating the plugin


  1. ``` js
  2. import pseudoFileSystem from 'terminal-in-react-pseudo-file-system-plugin';
  3. const FileSystemPlugin = pseudoFileSystem();

  4. <Terminal
  5.   plugins={[
  6.     FileSystemPlugin,
  7.   ]}
  8. />
  9. ```

or if the plugin requires config

  1. ``` js
  2. import NodeEvalPlugin from 'terminal-in-react-node-eval-plugin';
  3. import pseudoFileSystemPlugin from 'terminal-in-react-pseudo-file-system-plugin';
  4. const FileSystemPlugin = pseudoFileSystemPlugin();

  5. ...
  6. <Terminal
  7.   plugins={[
  8.     FileSystemPlugin,
  9.     {
  10.       class: NodeEvalPlugin,
  11.       config: {
  12.         filesystem: FileSystemPlugin.displayName
  13.       }
  14.     }
  15.   ]}
  16. />
  17. ...
  18. ```


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

Plugin List


- terminal-in-react-pseudo-file-system-plugin : A client-side only filesystem
- terminal-in-react-node-eval-plugin : used with a filesystem to evaluate js code
- terminal-in-react-vi-plugin : used with a filesystem to edit the contents of files more easily

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

  1. ``` js
  2. <Terminal
  3.   shortcuts={{
  4.     'darwin,win,linux': {
  5.       'ctrl + a': 'echo whoo',
  6.     },
  7.   }}
  8. />
  9. ```

But you might want to specific

  1. ``` js
  2. <Terminal
  3.   shortcuts={{
  4.     'win': {
  5.       'ctrl + a': 'echo hi windows',
  6.     },
  7.     'darwin': {
  8.       'cmd + a': 'echo hi mac'
  9.     },
  10.     'linux': {
  11.       'ctrl + a': 'echo hi linux'
  12.     }
  13.   }}
  14. />
  15. ```

You can mix and match

  1. ``` js
  2. <Terminal
  3.   shortcuts={{
  4.     'win,linux': {
  5.       'ctrl + b': 'echo we are special',
  6.     },
  7.     'win': {
  8.       'ctrl + a': 'echo hi windows',
  9.     },
  10.     'darwin': {
  11.       'cmd + a': 'echo hi mac'
  12.     },
  13.     'linux': {
  14.       'ctrl + a': 'echo hi linux'
  15.     }
  16.   }}
  17. />
  18. ```

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

Override the top bar buttons actionHandlers


Use the prop actionHandlers.

The object allows for 3 methods handleClose, handleMaximise, handleMinimise;

Each one is a function and will pass in the default method as the first param.
Any method not passed in will use the default.

  1. ``` js
  2. <Terminal
  3.   actionHandlers={{
  4.     handleClose: (toggleClose) => {
  5.       // do something on close
  6.       toggleClose();
  7.     },
  8.     handleMaximise: (toggleMaximise) => {
  9.       // do something on maximise
  10.       toggleMaximise();
  11.     }
  12.   }}
  13. />
  14. ```

Customization


Use

prop color to change the color of the text.
prop outputColor to change the color of the output text defaults to color prop.
prop backgroundColor to change the background.
prop barColor to change the color of bar.
prop prompt to change the prompt (>) color.
prop showActions to change if the three circles are shown.
prop hideTopBar to hide the top bar altogether.
prop allowTabs to allow multiple tabs.

API


component props

PropsTypeDefault
-------------|:-------------:|
**color**string'green'
**outputColor**stringprops.color
**backgroundColor**string'black'
**prompt**string'green'
**barColor**string'black'
**description**object{}
**commands**object{
**msg**string-
**closedTitle**stringOOPS!
**closedMessage**stringClick
**watchConsoleLogging**boolfalse
**commandPassThrough**functionnull
**promptSymbol**string>
**plugins**array[
**startState**string'open'
**showActions**booltrue
**hideTopBar**boolfalse
**allowTabs**booltrue
**actionHandlers**object-

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 projects using this terminal component
or just play with it

You want a X feature


Sure! Check our todolist or create an issue.

Contributing



Troubleshooting


**Build errors when using with `create-react-app`**

Eject from create-react-app and use a custom webpack configuration with [babili-webpack-plugin](https://github.com/webpack-contrib/babili-webpack-plugin). Read more about this here.

Style issues when maximizing

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

[npm-dm]: https://img.shields.io/npm/dm/terminal-in-react.svg
[npm-dt]: https://img.shields.io/npm/dt/terminal-in-react.svg
[npm-v]: https://img.shields.io/npm/v/terminal-in-react.svg
[deps]: https://img.shields.io/david/nitin42/terminal-in-react.svg
[dev-deps]: https://img.shields.io/david/dev/nitin42/terminal-in-react.svg
[license]: https://img.shields.io/npm/l/terminal-in-react.svg
[package-url]: https://npmjs.com/package/terminal-in-react

Sponsor