Giter Club home page Giter Club logo

react-bash's Introduction

<Terminal />

[NO LONGER MAINTAINED] ReactBash is a configurable / extendable bash terminal component. It provides an easy way of adding a terminal to your application. The terminal has a few built in base commands, and allows a simple means of extending the understandable commands. It boasts things like autocomplete on tab, previous command navigation, and a test suite you can trust. It is easy to install and get started.

npm install --save react-bash

Try out the DEMO

Props

prop description
extensions An object of bash command extensions
history An array of initial history items
structure An object representing the file system
theme A string representing which theme to use (Terminal.Themes.LIGHT, Terminal.Themes.DARK)
styles An object overriding the theme styles passed to each section
prefix The string used to prefix commands in history: defaults to hacker@default

Currently supported commands and args

command args/flags description
help lists all available commands
clear clears history
ls path lists all file and dirs at path or cwd
cat path/file prints out the contents of a file
mkdir path/dir makes a new dir at path
cd path change directory to relative path
pwd prints out the cwd
echo any prints out all args with env variables
printenv prints out env variables
whoami prints out current user's username

Extending the command list

The extension prop is an easy way to extend the bash commands that can be parsed from the terminal input. In essence, each command is a state reducer returning a new terminal state. This provides a lot of flexibility. Each command has access to the structure, history, and cwd, and expects the object returned to be applied in setState of the React component. Note that each extension should keep the state immutable, otherwise the component will not update. If we were to extend the commands with and existing command like 'clear, here's how we could do it.

import Terminal from 'react-bash';

export const clear = {
    exec: ({ structure, history, cwd }, command) => {
        return { structure, cwd, history: [] };
    },
};

const extensions = { clear };
<Terminal extensions={extensions} />

Each command is given the state and a parsed command object. The command object provides the name, input, args, and flags corresponding to the input. Some commands can use optional or required arguments. There are three types of args: anonymous args, named args (--), and flag args (-). To see how ReactBash parses the input.

For the input foo some/path -baz --hello world, ReactBash would parse the input as:

{
  command = 'foo'
  input: 'foo some/path -baz --hello world',
  args: {
    0: 'some/path',
    hello: 'world',
  },
  flags: { b: true, a: true, z: true },
}

History

The history prop and state arrays are lists of items that will be displayed as history items in the terminal. Essentially, anything that gets 'printed' out onto the terminal is a history item. The prefix prop is available to alter the bash user info that prepends commands in the history. If you'd like to add a welcome message to the initial state of the terminal, it's as easy as passing in a prop.

const history = [{ value: 'Welcome to the terminal!' }];
<Terminal history={history}  />

Structure

The structure object is a representation of the "file system" found within the terminal. It is what is used to navigate into/out of directories, display file contents, and suggesting autocompletions. Each key in the dict is either a directory or a file. If the object has a content field then it is assumed to be a file. This simplified the interface and makes it easier to get started. Here's an example of what a structure might look like.

const structure = {
    src: {
        file1: { content: 'This is the text content for <file1> of <src>' },
        file2: { content: 'This is the text content for <file2> of <src>' },
        childDir1: {
            file: { content: 'This is the text content for <file> of <src/childDir1>' },
        },
        childDir2: {
        }
    },
    '.hiddenDir': {
    },
    '.hiddenFile': { content: 'This is a hidden file' },
    file: { content: 'This is the text content for <file> of the root directory' },
};

Scripts

script description
npm start run the demo on localhost:3000
npm run test run the test suite
npm run lint run the linter

Patrons

Be the second to contribute! ✌⊂(✰‿✰)つ✌

Some ideas for contributions:

  • Add grep command that walks/searches the structure
  • Add multiline support / text formatting for cat

License

MIT

react-bash's People

Contributors

aghoneim92 avatar akleiner2 avatar derekargueta avatar derekstavis avatar frontmaker avatar zackargyle 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

react-bash's Issues

Support react-native

It would be best if you can continue this project and make it available for react-native :)

add new command ?

hi
is it possible to add bash command like npm or python ?
thanks

Ctrl + click problems

ctrl + L click jumps to URL line instead of clearing the terminal.
After that, every click on 'L' (without ctrl) does a clear and every 'C' clears the line.

Can't override default commands

First of all thanks for the great library, it's exactly what I was looking for!

I have an issue with overriding existing commands, I tried for example to override the help, but my custom function is never called. It works perfectly well with new commands.

Here there's a snippet of my code.

const help = {
  exec: (state) => {
    console.log('Help', state)
  }
}

const navigate = {
  exec: (state, { args }) => {
    const location = get(args, '0')
    history.push('/')
  }
}

const extension = { navigate, help }

<Terminal extensions={extensions} />

I'm using React 16.3.0, so maybe it might depends on that

Quotes

hacker@default ~ $echo "foo"
"foo"

Base commands should be overridable

It is currently impossible to override the base commands, although it might be desirable for a user to change the behaviour of a given command. One possible use case might be to link a structure modifying command to an actual request to an external API:

import * as builtin from 'react-bash/commands';

const mkdir = {
    exec: (state, { args }) => {
        someExternalAPI.execute('mkdir', args);
        return builtin.mkdir(state, args);
    },
};

const extensions = { mkdir };
<Terminal extensions={extensions} />

I think it should suffice to replace src/bash.js:9 with the following:

this.commands = Object.assign({}, BaseCommands, extensions);

How to create async command?

I would like to be able to execute commands asynchronously.

For example:

const extensions = {
  asyncCommand1: {
    exec: (state, command) => {
      return Promise.resolve(state)
    }
  }
}

How can i do it?

How to I get my command?

Hi,
Help me to get whatever things I am typing on a terminal.
In the below I type 'cd list' and I want to console value. How to get value?
Screenshot from 2020-02-14 11-00-27

access history from main app

Hi there - As I understand, each time something is typed/returned, it appends to the history array and state.

Is there a way to access history on an ongoing basis?

I'd like to do something like:

  1. user cat's some file
  2. file prints UUID
  3. if history.find UUID then trigger some action.. maybe show a button

Similarly if, history gets beyond some count, maybe i auto trigger help.

Is this possible?

Autocomplete should work with a single letter when unique

In the example below, I have the public directory, the only directory that starts with a p. But when I try cd p + tab, it doesn't autocomplete. It works if I add a u, but since it's the only item starting with a p the autocomplete should work anyways.

image

Unhandled promise rejection after importing

I used yarn to install the package: yarn add react-bash
I'm trying to include it on a page. As soon as I add the import statement import Terminal from "react-bash";` I get the following in the console:

Unhandled promise rejection 
TypeError: _react.PropTypes is undefined
Stack trace:
./node_modules/react-bash/lib/component.js@http://0.0.0.0:8000/commons.js:40810:6
__webpack_require__@http://0.0.0.0:8000/commons.js:556:12
fn@http://0.0.0.0:8000/commons.js:87:20
./node_modules/react-bash/lib/index.js@http://0.0.0.0:8000/commons.js:40889:19
__webpack_require__@http://0.0.0.0:8000/commons.js:556:12
fn@http://0.0.0.0:8000/commons.js:87:20
./src/pages/index.js@http://0.0.0.0:8000/commons.js:2876:19
__webpack_require__@http://0.0.0.0:8000/commons.js:556:12
fn@http://0.0.0.0:8000/commons.js:87:20
./.cache/sync-requires.js@http://0.0.0.0:8000/commons.js:2323:52
__webpack_require__@http://0.0.0.0:8000/commons.js:556:12
fn@http://0.0.0.0:8000/commons.js:87:20
./.cache/root.js@http://0.0.0.0:8000/commons.js:2026:22
__webpack_require__@http://0.0.0.0:8000/commons.js:556:12
fn@http://0.0.0.0:8000/commons.js:87:20
./.cache/app.js/<@http://0.0.0.0:8000/commons.js:912:15
run@http://0.0.0.0:8000/commons.js:6019:23
notify/<@http://0.0.0.0:8000/commons.js:6032:31
flush@http://0.0.0.0:8000/commons.js:5506:10

Removing the import statement fixes the issue.

Modify history outside extensions

I want to modify the history like this :

export default class ShellManager extends Component {
  constructor(props) {
    super(props);
    this.extensions = {
      clear: {
        exec: ({structure, history, cwd}, command) => {
          return {structure, cwd, history: []}
        }
      },

      somethingAsync: {
        exec: ({structure, history, cwd}, command) => {
          console.log(command.input);
          this.props.socket.emit("toto", "toto")
          return {structure, cwd, history}
        }
      }
    }
  }

 socket.on('returnData', (someData) {
    "historyofterminal" = historyofterminal.concat({value: someData});  <=====  HERE
 }

  render() {
    return(
      <Terminal  extensions={this.extensions} prefix={"tozzo"}/>
    );
  }
}

Regex support

Ability to execute commands on the filesystem using a regular expression to specify files.
image
image

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.