From eb7460de0797bcf0d4af817625024957700dc029 Mon Sep 17 00:00:00 2001 From: Zack Argyle Date: Wed, 8 Jun 2016 16:51:52 -0700 Subject: [PATCH] Add 'node' command --- demo/index.js | 1 + src/bash.js | 8 ++++++++ src/commands.js | 44 +++++++++++++++++++++++++------------------- src/component.js | 16 ++++++++++++---- src/const.js | 4 ++++ src/styles.js | 2 +- src/util.js | 25 +++++++++++++++++++++++++ tests/commands.js | 39 +++++++++++++++++++++++++++++++++++++-- 8 files changed, 113 insertions(+), 26 deletions(-) diff --git a/demo/index.js b/demo/index.js index cb450e8..60104e2 100644 --- a/demo/index.js +++ b/demo/index.js @@ -31,6 +31,7 @@ const structure = { file2: { content: 'The is the content for file2 in the directory.' }, file3: { content: 'The is the content for file3 in the directory.' }, }, + 'alert.js': { content: 'alert("Hello world")' }, 'README.md': { content: '✌⊂(✰‿✰)つ✌ Thanks for checking out the tool! There is a lot that you can do with react-bash and I\'m excited to see all of the fun commands and projects build on top of it!' }, }; diff --git a/src/bash.js b/src/bash.js index f835683..2dbc441 100644 --- a/src/bash.js +++ b/src/bash.js @@ -30,6 +30,14 @@ export default class Bash { } } + executeShell(input, state) { + return Object.assign({}, state, { + history: state.history.concat({ + value: Util.evaluate(input), + }), + }); + } + parseInput(input) { const tokens = input.trim().split(/ +/); const command = tokens.shift(); diff --git a/src/commands.js b/src/commands.js index dfb4ac2..2cf38cf 100644 --- a/src/commands.js +++ b/src/commands.js @@ -1,7 +1,7 @@ import * as Util from './util'; -import { Errors } from './const'; +import { Errors, Shells } from './const'; -const helpCommands = ['clear', 'ls', 'cat', 'mkdir', 'cd', 'pwd']; +const helpCommands = ['clear', 'ls', 'cat', 'mkdir', 'cd', 'pwd', 'node']; export const help = { exec: ({ history, structure, cwd }) => { @@ -49,22 +49,30 @@ export const cat = { exec: (state, args) => { const { history, structure, cwd } = state; const path = args[0]; - const relativePath = path.split('/'); - const fileName = relativePath.pop(); - const fullPath = Util.extractPath(relativePath.join('/'), cwd); - const { err, dir } = Util.getDirectoryByPath(structure, fullPath); - if (err) { - return Util.reportError(state, err, path); - } else if (!dir[fileName]) { - return Util.reportError(state, Errors.NO_SUCH_FILE, path); - } else if (!dir[fileName].hasOwnProperty('content')) { - return Util.reportError(state, Errors.IS_A_DIRECTORY, path); - } else { + return Util.getFile(path, state, file => { return { cwd, structure, history: history.concat({ - value: dir[fileName].content, + value: file.content, }), }; + }); + }, +}; + +export const node = { + exec: (state, args) => { + const { history, structure, cwd } = state; + const path = args[0]; + if (path) { + return Util.getFile(path, state, file => { + return { cwd, structure, + history: history.concat({ + value: Util.evaluate(file.content), + }), + }; + }); + } else { + return { cwd, structure, history, shell: Shells.NODE }; } }, }; @@ -108,13 +116,11 @@ export const cd = { }; export const pwd = { - exec: (state) => { - const { history, structure, cwd } = state; - const directory = `/${cwd}`; - + exec: ({ history, structure, cwd }) => { + const value = `/${cwd}`; return { cwd, structure, - history: history.concat({ value: directory }), + history: history.concat({ value }), }; }, }; diff --git a/src/component.js b/src/component.js index 97e1fc6..a3bd354 100644 --- a/src/component.js +++ b/src/component.js @@ -95,6 +95,9 @@ export default class Terminal extends Component { } else if (evt.which === C_CHAR_CODE) { if (this.ctrlPressed) { this.refs.input.value = ''; + if (this.state.shell) { + this.setState({ shell: null }); + } } } else if (evt.which === UP_CHAR_CODE) { if (this.Bash.hasPrevCommand()) { @@ -116,8 +119,11 @@ export default class Terminal extends Component { // Execute command const input = evt.target[0].value; - const newState = this.Bash.execute(input, this.state); - this.setState(newState); + if (this.state.shell) { + this.setState(this.Bash.executeShell(input, this.state)); + } else { + this.setState(this.Bash.execute(input, this.state)); + } this.refs.input.value = ''; } @@ -132,7 +138,7 @@ export default class Terminal extends Component { render() { const { prefix, theme } = this.props; - const { history, cwd } = this.state; + const { history, cwd, shell } = this.state; const style = Styles[theme] || Styles.light; return (
@@ -144,7 +150,9 @@ export default class Terminal extends Component {
this.refs.input.focus()}> {history.map(this.renderHistoryItem(style))}
this.handleSubmit(evt)} style={style.form}> - {`${prefix} ~${cwd} $`} + {shell ? {'>'} : ( + {`${prefix} ~${cwd} $`} + )} { let bash; @@ -147,6 +148,40 @@ describe('bash commands', () => { }); + describe('node', () => { + + it('should exist', () => { + chai.assert.isFunction(bash.commands.node.exec); + }); + + it('should set `shell` state variable to Shells.NODE', () => { + const state = stateFactory(); + const { shell } = bash.commands.node.exec(state, {}); + chai.assert.strictEqual(shell, Shells.NODE); + }); + + it('should eval a file\'s contents', () => { + const state = stateFactory(); + const expected = state.structure.file1.content; + const stub = sinon.stub(global, 'eval').returns(expected); + const { history } = bash.commands.node.exec(state, { 0: 'file1' }); + chai.assert.strictEqual(history.length, 1); + chai.assert.strictEqual(history[0].value, `"${expected}"`); + stub.restore(); + }); + + it('should eval a file\'s contents from path', () => { + const state = stateFactory(); + const expected = state.structure.dir1.dir1File.content; + const stub = sinon.stub(global, 'eval').returns(expected); + const { history } = bash.commands.node.exec(state, { 0: 'dir1/dir1File' }); + chai.assert.strictEqual(history.length, 1); + chai.assert.strictEqual(history[0].value, `"${expected}"`); + stub.restore(); + }); + + }); + describe('mkdir', () => { it('should exist', () => { @@ -229,7 +264,7 @@ describe('bash commands', () => { }); - describe('cd', () => { + describe('pwd', () => { it('should exist', () => { chai.assert.isFunction(bash.commands.pwd.exec); });