Git Product home page Git Product logo

terminal-in-react's Introduction

Terminal in React

Downloads Downloads NPM Version Dependencies Dev Dependencies License 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

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 ๐Ÿ”ฅ

Plugin Documentation.

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

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 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

Contributing Guide

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.

Sponsor

terminal-in-react's People

Contributors

bhageena avatar cvarisco avatar fmedinac avatar haroenv avatar jcgertig avatar nitin42 avatar shenburak avatar vcarmignac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terminal-in-react's Issues

Why can't I use the styled-components over the <Terminal />?

I use the styled-components over the Terminal like this:
image
image

But the style that originally belonged to the Termianl is gone, it looks like this:
image

I didn't konw what was going on in the first place, thinking I didn't load the style of Terminal. But when I got rid of the styled-components, the Terminal was suddenly normal.
image
image

So who can tell me why? And I found that they both had the same class name.
image

It made me very confused.
Help me, please.

Allow Enter key on commandPassThrough

The Enter key does not register with a commandPassThrough handler.
I need access to the second and third args - (cmd, printLine, runCommand) - in certain situations when I push the Enter key.

Using websockets to pass data?

I understand that I can use command passthrough but that is reliant on a transactional system. If i have a websocket open and i am sending data to a room, and listening for data on a room I am not sure how to push the data I am listening for to the terminal.

I need some way to bind a listener to a prop within Terminal that will, when receives data, push more lines to the terminal, this may be completely independent of any command, and may happen without user input.

As of right now I cannot figure out a way to do this, any help?

Way to get onChange of terminal?

I am scratching my head on this one, I don't want to get the full command on enter, I instead want to bind to every change that occurs when typing in the terminal (we use a fully simulated pty backend, so we must send a character at a time).

It is not clear if this is possible in the current release, am I missing something?

Custom tab completion

It would be really nice for plugins to be able to hook into tab completion to provide custom completion.
e.g. the pseudo-filesystem plugin could auto-complete file paths.

support debug %coloring%

Way to support or prevent visionmedia's debug's %c in console output.
Also, report: enabled terminal-in-react broke debug log's coloring in Chromium Developer Tools

Issues : Line BackgroundColor + HandleShortcut + ReadOnly Terminal

Hi, maybe I 'm a noob but have some trouble customising the backgroundColor.

I. Line Background Color ( terminal on the right )
In the gif examble all previous log of the terminal are green on a black blackbackground :
me, on windows , there is a white background on the previous logs historic such as this following pic
terminal issue 1
which is , on the navigator console easily targatable : corresponding to the class pre but I cannot override its behavior from my code, only on the navigator .

II. HandleShortcuts win linux darwin :
Did I well understood ? adding these shortcuts option, If I do ctrl + a for instance the terminal should print : echo whoo ?

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

if that so I also need help in here :/ cause it doesn't work for me.

III. is it also possible to have access to an option readonly for the terminal ? render it not editable but just read what code will be given ( ex the editor on the left side ? )

Until now I couldn't find. :/ if I could have any hint , it could be so nice. Thank you very much

contribute style guide needed

Hi @nitin42 !

Cool component ๐Ÿ™‚
Could you provide a contribute guide (how set up the dev env, how to write js, ecc...) ? Because it would be great contribute to your component.

After that, I will create a PR with a new feature (it is a surprise ๐ŸŒฎ )

Prevent Terminal from Scrolling

If you want to prevent the terminal from scrolling. Then the following is a quick hack:
Open /node_modules/terminal-in-react/lib/js/components/Content/index.js inside your node modules. Then find &&_this.inputWrapper.scrollIntoView(!1) and delete it. Rebuild your react web application and it should no longer scroll.

I believe there should be an option that allows the user to control whether the terminal scrolls or not.

Hide some of the built-in commands

can we choose to hide some commands that we wouldn't use in the terminal?
For example, I don't want to show 'echo' or 'edit-line'. Can we pass the prop as false, in case we don't want certain commands?

Support for positional parameters in commands

I am trying to configure the terminal to show documentation for commands without requiring them to be named parameters in execution of the command. I know that I can get the positional parameter value in the argument array, but I'd like for my users to have some documentation of how to use them. Is this possible?

how to change the terminal input value based on a button action

Hi @nitin42, I need to change the terminal input value based on the button action from my component. As of now i am using printToActive of the terminal ref which actually prints the command. But for my case, i just want to show the value in terminal based on the button action, then the user can edit it.

Is there any way to achieve this?

More examples

We need to add more examples covering async handling of commands, advance commands and command pass through!

change colors of text in print()?

hey!

Is there a way to change the color of a text printed with the method print() in a defined command?

I have the prompt set to prompt="#fff" but there are some cases, where i would like to overwrite this, to whatever else color.

is it possible in any way? :)

Thank you,

Server Side Rendering: window is not defined error

Hey guys, this component is really cool!

Are there any plans to make this component work with SSR?

I am guessing this error is alluding to the server not having a window size

ReferenceError: window is not defined

Prevent terminal input from being autofocused

If you want to prevent the terminal from being autofocused on load. Then the following is a quick hack:
Open /node_modules/terminal-in-react/lib/js/components/Content/index.js inside your node modules. Then find _this.focusInput(); and delete it. Rebuild your react web application and it should no longer autofocus.

I believe there should be an option that allows the user to control whether the terminal input is autofocused on start.

issue with dependanices

Hi,
I'm getting an error when trying to use the module.
I have the most basic usage straight from the docs.
I installed via yarn (version 1.3.2)

can you please assist ?
thanks

  render() {
    return <Terminal
      color='green'
      backgroundColor='black'
      barColor='black'
      style={{fontWeight: "bold", fontSize: "1em"}}
      commands={{
      }}
      descriptions={{
      }}
      msg='You can write anything here. Example - Hello! My name is Foo and I like Bar.'
    />
  }
"dependencies": {
    "autosuggest-highlight": "^3.1.1",
    "brace": "^0.10.0",
    "classnames": "^2.2.5",
    "lodash": "^4.17.4",
    "material-ui": "^1.0.0-beta.22",
    "material-ui-icons": "^1.0.0-beta.17",
    "prop-types": "^15.6.0",
    "react": "^16.0.0",
    "react-ace": "^5.4.0",
    "react-autosuggest": "^9.3.2",
    "react-dom": "^16.0.0",
    "react-router-dom": "^4.2.2",
    "react-sortable-hoc": "^0.6.8",
    "react-tap-event-plugin": "^3.0.2",
    "terminal-in-react": "3.5.0"
  },

image

about tab

I think we should change the matching rule

I input 'echo xxx' then I press the Tab. we will find 'xxx' cleared.so I think it's unfriendly.

And I think the terminal will have more cue in the future, like: we can see some cue when press Tab after we input 'cd' in iTerm.

Color changes once commands get executed.

All the commands turn to green once they get executed. Like this:

terminal
I've even tried setting my color prop to black but no use.

<Terminal
    color='black'
    backgroundColor='white'
    prompt="black"
/>

I've then tried creating a new property named historyColor which holds the color value of previous commands and added it to the React component.

// src/js/components/Terminal
const theme = {
      ...
      historyColor: this.props.historyColor
    };

// src/js/components
export const TerminalPropTypes = {
      ...
      historyColor: PropTypes.string,
}
export const TerminalDefaultProps = {
        historyColor: 'black',
}

// src/js/components/Content/styled-elements.js
const outputLineStyle = `
      ...
      color: ${props => props.theme.historyColor};
`;

It still doesn't work.

But what caught me was, outputLineStyle.color(CSS) was the variable that was holding the color value. Modifying the value changes the color.
So removing that label makes the container to use Terminal.color prop as it's value.
So, Is it a bug(and must be removed) or Is there a way to modify the color of previous commands?

Typescript definitions

Hi! I was hoping to use this for my typescript project, but I saw that you don't have a types definition ( npm install @types/terminal-in-react ). It would be awesome if you did!

Thanks.

Add Flow types

For type inference and tracking the data! We should add support for Flow.

can't override scrollbars

I'm not able to override the overflow.
Even trying inline and class doesn't seem to work.

image

What I found was the third div from the terminal div was holding the overflow values.
image

image
All the styling which I give to Terminal component goes to the 2nd component. While the 3rd is Untouchable.

<Terminal
      color='black'
      style={{ 
          fontWeight: "bold", fontSize: "1em",
          overflow: 'hidden'
      }}
/>

Is there any way to override stylings right from the Terminal component?

How can I add a prompt command instead of running a command?

Hi I wanted to ask if there is a feature where running one command will prompt another one.
For example:
//running the command 'address' prompt another command but does run it until you press enter
'>address
'>enter address one: somwhere st
'>enter city: somecity
'>enter state: someState
....

thanks

Automatically scroll to the bottom

If I get to the bottom of the terminal, the screen will stay where it is, instead of going to where the cursor would be.

Is there a way to automatically send it to the bottom after each command?

command from state

It's possible to update commands property from state?

I have :

 <Terminal
          color='lime'
          backgroundColor='black'
          commands={this.state.commands}
          barColor='black'
          style={{ fontWeight: "bold", fontSize: "1em" }}
        />

But when i fetch command from remote, terminal won't update!

thank you!

Is there a way to replace getNote?

This is a fabulous component.I find if Terminal is not shown,this default action is getNote,so is there a way to replace getNote, maybe pass through props?Actually,what I want is a visible props to handle Terminal visibility manually.

Uglify issue with camelcase dependency

When using this package with an app bootstrapped with create-react-app the build fails, because camelcase will not use ES5 in their package. Their argument is that they target node and it should be no issue there.

Since the package's target is cleary the front end would you consider switching to another camelcase library? Maybe the lodash one.

The error:

Failed to minify the code from this file:
./node_modules/terminal-in-react/node_modules/camelcase/index.js:4
Read more here: http://bit.ly/2tRViJ9

Love the project,

Cheers

Got a Element type is invalid error.

Hello! Thank you for your great project.

I try to create a terminal with the demo code posted on README.md, and I got an error with the following:

screen shot 2018-01-24 at 3 27 12 pm

Thank you for your help.

edit-line command return multiple lines instead of one

Hello, thanks for this awesome component ๐Ÿ™‚

I tried to implement the type-text from advanced commands examples which use the edit-line built in command that is supposed to edit the last line.

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)
    }
  },
}}

But instead of getting the last line updating, it return a new line at each iteration.

> type-text hello
 
h
he
hel
hell
hello

Any idea of what could cause this? ๐Ÿค”

Paste support

It would be cool to be able to use paste (via right-click/Paste /whatever) as in normal bash.

Reasoning, use case:
There can be many use cases for that.
Example:
I am using your awesome component as UI for remote terminal to IOT devices (it is much nicer to do it directly in the web page, rather then finding out devices IP, switching to actual Terminal etc.). I use passthrough feature for that.

So I often need to paste things from manuals. Typing them by hand is kind of tedious.

Thank you!

Easier way to run commands from external component

I was wondering if there is an easier way to run commands from an external component?

Currently I have a button that provides the user the option to clear the terminal without having to type in the command. The code I am using to perform this is:

    this.instance.runCommand(this.instance.getChildContext().instances[0].instance, 'clear');

I think something more along the lines of:

    this.instance.runCommand('clear');

or

    this.instance.runCommand('clear', this.instance.currentTab);

where this.instance is a ref to the <Terminal /> instance.

Support multiple header values on same key

Hi,

I would like to implement a plugin for 'curl' command.
Curl takes -H option and one can use it in a multiple way, e.g: curl -H key1=value1 -H key2=value2.
Right now I see only the last value is given in the args, any idea on how to implement that?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.