Terminal in React
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
This package also depends on react
so make sure you've already installed it.
Usage
import React, { Component } from 'react';
import Terminal from 'terminal-in-react';
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>
);
}
}
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
<Terminal
closedTitle='OOPS! You closed the window.'
closedMessage='Click on the icon to reopen.'
/>
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';
const FileSystemPlugin = pseudoFileSystem();
<Terminal
plugins={[
FileSystemPlugin,
]}
/>
or if the plugin requires config
import NodeEvalPlugin from 'terminal-in-react-node-eval-plugin';
import pseudoFileSystemPlugin from 'terminal-in-react-pseudo-file-system-plugin';
const FileSystemPlugin = pseudoFileSystemPlugin();
...
<Terminal
plugins={[
FileSystemPlugin,
{
class: NodeEvalPlugin,
config: {
filesystem: FileSystemPlugin.displayName
}
}
]}
/>
...
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
<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.
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.
<Terminal
actionHandlers={{
handleClose: (toggleClose) => {
// do something on close
toggleClose();
},
handleMaximise: (toggleMaximise) => {
// do something on maximise
toggleMaximise();
}
}}
/>
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
Props | Type | Default |
---|---|---|
color | string | 'green' |
outputColor | string | props.color |
backgroundColor | string | 'black' |
prompt | string | 'green' |
barColor | string | 'black' |
description | object | {} |
commands | object | { clear, help, show, } |
msg | string | - |
closedTitle | string | OOPS! You closed the window. |
closedMessage | string | Click on the icon to reopen. |
watchConsoleLogging | bool | false |
commandPassThrough | function | null |
promptSymbol | string | > |
plugins | array | [ { name: '', load: new Plugin(), commands: {} descriptions: {} } ] |
startState | string ['open', 'maximised', 'minimised', 'closed'] | 'open' |
showActions | bool | true |
hideTopBar | bool | false |
allowTabs | bool | true |
actionHandlers | object | - |
Built-in commands
clear
- Clears the screenhelp
- List all the commandsshow
- Shows a msg if anyecho
- Display the input messageedit-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
. Read more about this here.
Style issues when maximizing
Set the style to height: 100vh
on parent element.