[
  {
    "path": ".gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Prakhar Srivastav\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# React Term\n\nA couple of days back, I got an email from Columbia (the university that I'm stated to join) informing me that my new email ID and other student IT services were ready. Hosting my own webpage on a university's domain had long been a wish of mine, so as soon as I learnt about having some server space on the university's server I got excited wanted to put something interesting. Since I already have a boring [about me](http://prakhar.me/about) page, I went with something different and built a simple terminal emulator in [React](http://facebook.github.io/react/)!\n\n![img](shot.png)\n\nDemo - http://columbia.edu/~ps2894\n\n### Run\n```\n$ npm install\n$ npm run dist\n```\n\n### Dev\n```\n$ npm install\n$ npm run watch\n```\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Prakhar Srivastav</title>\n    <link rel=\"stylesheet\" href=\"http://getskeleton.com/dist/css/normalize.css\">\n    <link rel=\"stylesheet\" href=\"http://getskeleton.com/dist/css/skeleton.css\">\n    <link href='http://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>\n    <style>\n      body {\n        margin: 100px 0;\n        font-family: 'Inconsolata', monospace;\n        font-size: 14px;\n        color: #dfe1e8;\n        background: #343d46;\n      }\n      #app, div.input-area {\n        height: 100%;\n      }\n      div#main {\n          max-width: 560px;\n          background: #2b303b;\n          border-radius: 5px;\n          height: 400px;\n          -webkit-box-shadow: 0px 0px 13px 0px rgba(50, 50, 50, 0.59);\n          -moz-box-shadow:    0px 0px 13px 0px rgba(50, 50, 50, 0.59);\n          box-shadow:         0px 0px 13px 0px rgba(50, 50, 50, 0.59);\n          overflow: hidden;\n      }\n      .holder {\n          overflow: auto;\n      }\n      .prompt {\n        color: #d28445;\n      }\n      input[type=text], input[type=text]:focus {\n        border: none;\n        padding: 0; \n        margin: 0;\n        height: 22px;\n        background: #2b303b;\n        color: #ebcb8b;\n        width: 80%;\n      }\n      p { \n        margin-bottom: 0;\n        line-height: 21px;\n      }\n      #bar {\n        height: 30px;\n        max-width: 560px;\n        background: black;\n        border-radius: 5px;\n      }\n      #content {\n        padding: 20px;\n        height: 100%;\n      }\n    </style>\n</head>\n<body>\n      <div id=\"bar\" class='container'>\n        <svg height=\"20\" width=\"100\">\n          <circle cx=\"24\" cy=\"14\" r=\"5\" fill=\"#bf616a\" />\n          <circle cx=\"44\" cy=\"14\" r=\"5\" fill=\"#ebcb8b\" />\n          <circle cx=\"64\" cy=\"14\" r=\"5\" fill=\"#a3be8c\" />\n        </svg>\n      </div>\n    <div class=\"container\" id=\"main\">\n      <div class=\"holder\">\n        <div id=\"content\">\n          <div id=\"app\"></div>\n        </div>\n      </div>\n    </div>\n    <script type=\"text/javascript\" src=\"build/main.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-term\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"main\": \"reactcart.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"watch\": \"watchify -t reactify ./src/app.js -o ./build/main.min.js -v\",\n    \"dist\": \"npm run remove-dist && npm run build-standalone\",\n    \"remove-dist\": \"rm build/*.js\",\n    \"build-standalone\": \"NODE_ENV=production browserify -t reactify ./src/app.js | uglifyjs -mc > build/main.min.js\"\n  },\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"babelify\": \"^5.0.4\",\n    \"browserify\": \"^9.0.3\",\n    \"react\": \"^0.13.1\",\n    \"reactify\": \"^1.1.0\",\n    \"uglify-js\": \"^2.4.20\",\n    \"underscore\": \"^1.8.3\",\n    \"watchify\": \"^3.1.0\"\n  }\n}\n"
  },
  {
    "path": "src/app.js",
    "content": "var React = require('react');\n\nvar App = React.createClass({\n  getInitialState: function() {\n      return {\n        commands: {},\n        history: [],\n        prompt: '$ '\n      }\n  },\n  clearHistory: function() {\n      this.setState({ history: [] });\n  },\n  registerCommands: function() {\n    this.setState({\n      commands: {\n        'clear' : this.clearHistory,\n        'ls'    : this.listFiles,\n        'intro' : this.showWelcomeMsg,\n        'help'  : this.showHelp,\n        'cat'   : this.catFile,\n        'source': this.openLink('https://github.com/prakhar1989/react-term/blob/master/src/app.js'),\n        'github': this.openLink('http://github.com/prakhar1989'),\n        'blog'  : this.openLink('http://prakhar.me'),\n        'resume': this.openLink('https://github.com/prakhar1989/cv/blob/master/Resume.pdf')\n      }\n    });\n  },\n  listFiles: function() {\n      this.addHistory(\"README.md\");\n  },\n  showWelcomeMsg: function() {\n      this.addHistory(\"Hello, I'm Prakhar Srivastav, a graduate student in the Computer Science department (Machine Learning track).\");\n      this.addHistory(\"Type `help` to see what all commands are available\");\n  },\n  catFile: function(arg) {\n      if (arg === \"README.md\") {\n          this.addHistory('### REACT TERM');\n          this.addHistory(\"A couple of days back, I got an email from Columbia (the university that I'm stated to join) informing me that my new email ID and other student IT services were ready. Hosting my own webpage on a university's domain had long been a wish of mine, so as soon as I learnt about having some server space on the university's server I got excited wanted to put something interesting. Since I already have \" +\n                          \"a boring about me page, I went \" +\n                          \"with something different and built a simple terminal emulator in React!\");\n          this.addHistory(\"type `source` to view the source code\");\n      } else {\n          this.addHistory(\"cat: \" +  arg + \": No such file or directory\");\n      }\n  },\n  openLink: function(link) {\n      return function() {\n        window.open(link, '_blank');\n      }\n  },\n  showHelp: function() {\n      this.addHistory(\"help - this help text\");\n      this.addHistory(\"github - view my github profile\");\n      this.addHistory(\"source - browse the code for this page\");\n      this.addHistory(\"intro - print intro message\");\n      this.addHistory(\"blog - read some stuff that I've written\");\n      this.addHistory(\"clear - clear screen\");\n      this.addHistory(\"cat - print contents of a file\");\n      this.addHistory(\"ls - list files\");\n      this.addHistory(\"resume - view my resume\");\n  },\n  componentDidMount: function() {\n      var term = this.refs.term.getDOMNode();\n\n      this.registerCommands();\n      this.showWelcomeMsg();\n      term.focus();\n  },\n  componentDidUpdate: function() {\n      var el = React.findDOMNode(this);\n      //var container = document.getElementsByClassName('container')[0];\n      var container = document.getElementById(\"main\");\n      container.scrollTop = el.scrollHeight;\n  },\n  handleInput: function(e) {\n      if (e.key === \"Enter\") {\n          var input_text = this.refs.term.getDOMNode().value;\n          var input_array = input_text.split(' ');\n          var input = input_array[0];\n          var arg = input_array[1];\n          var command = this.state.commands[input];\n\n          this.addHistory(this.state.prompt + \" \" + input_text);\n\n          if (command === undefined) {\n              this.addHistory(\"sh: command not found: \" + input);\n          } else {\n              command(arg);\n          }\n          this.clearInput();\n      }\n  },\n  clearInput: function() {\n      this.refs.term.getDOMNode().value = \"\";\n  },\n  addHistory: function(output) {\n    var history = this.state.history;\n    history.push(output)\n    this.setState({\n      'history': history\n    });\n  },\n  handleClick: function() {\n    var term = this.refs.term.getDOMNode();\n    term.focus();\n  },\n  render: function() {\n      var output = this.state.history.map(function(op, i) {\n          return <p key={i}>{op}</p>\n      });\n      return (\n        <div className='input-area' onClick={this.handleClick}>\n          {output}\n          <p>\n            <span className=\"prompt\">{this.state.prompt}</span> \n            <input type=\"text\" onKeyPress={this.handleInput} ref=\"term\" />\n          </p>\n        </div>\n      )\n  }\n});\n\n// render it dawg!\nvar AppComponent = React.createFactory(App);\nReact.render(AppComponent(), document.getElementById('app'));\n"
  }
]