[
  {
    "path": ".gitignore",
    "content": "npm-debug.log\n*sw.*\nnode_modules\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014-2019 Paolo Fragomeni & David Mark Clements\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": "# SYNOPSIS\nA sync prompt for node. very simple. no C++ bindings and no bash scripts.\n\nWorks on Linux, OS X and Windows.\n\n# BASIC MODE\n```js\n\nvar prompt = require('prompt-sync')();\n//\n// get input from the user.\n//\nvar n = prompt('How many more times? ');\n```\n# WITH HISTORY\n\nHistory is an optional extra, to use simply install the history plugin. \n\n```sh\nnpm install --save prompt-sync-history\n```\n\n```js\nvar prompt = require('prompt-sync')({\n  history: require('prompt-sync-history')() //open history file\n});\n//get some user input\nvar input = prompt()\nprompt.history.save() //save history back to file\n```\n\nSee the [prompt-sync-history](http://npm.im/prompt-sync-history) module\nfor options, or fork it for customized behaviour. \n\n# API\n\n## `require('prompt-sync')(config) => prompt` \n\nReturns an instance of the `prompt` function.\nTakes `config` option with the following possible properties\n\n`sigint`: Default is `false`. A ^C may be pressed during the input process to abort the text entry. If sigint it `false`, prompt returns `null`. If sigint is `true` the ^C will be handled in the traditional way: as a SIGINT signal causing process to exit with code 130.\n\n`eot`: Default is `false`. A ^D pressed as the first character of an input line causes prompt-sync to echo `exit` and exit the process with code 0.\n\n`autocomplete`: A completer function that will be called when user enters TAB to allow for autocomplete. It takes a string as an argument an returns an array of strings that are possible matches for completion. An empty array is returned if there are no matches.\n\n`history`: Takes an object that supplies a \"history interface\", see [prompt-sync-history](http://npm.im/prompt-sync-history) for an example.\n\n## `prompt(ask, value, opts)`\n\n`ask` is the label of the prompt, `value` is the default value\nin absence of a response. \n\nThe `opts` argument can also be in the first or second parameter position.\n\nOpts can have the following properties\n\n`echo`: Default is `'*'`. If set the password will be masked with the specified character. For hidden input, set echo to `''` (or use `prompt.hide`).\n\n`autocomplete`: Overrides the instance `autocomplete` function to allow for custom \nautocompletion of a particular prompt.\n\n`value`: Same as the `value` parameter, the default value for the prompt. If `opts`\nis in the third position, this property will *not* overwrite the `value` parameter.\n\n`ask`: Sames as the `value` parameter. The prompt label. If `opts` is not in the first position, the `ask` parameter will *not* be overridden by this property.\n\n## `prompt.hide(ask)`\n\nConvenience method for creating a standard hidden password prompt, \nthis is the same as `prompt(ask, {echo: ''})`\n\n\n# LINE EDITING\nLine editing is enabled in the non-hidden mode. (use up/down arrows for history and backspace and left/right arrows for editing)\n\nHistory is not set when using hidden mode.\n\n# EXAMPLES\n\n```js\n  //basic:\n  console.log(require('prompt-sync')()('tell me something about yourself: '))\n\n  var prompt = require('prompt-sync')({\n    history: require('prompt-sync-history')(),\n    autocomplete: complete(['hello1234', 'he', 'hello', 'hello12', 'hello123456']),\n    sigint: false\n  });\n\n  var value = 'frank';\n  var name = prompt('enter name: ', value);\n  console.log('enter echo * password');\n  var pw = prompt({echo: '*'});\n  var pwb = prompt('enter hidden password (or don\\'t): ', {echo: '', value: '*pwb default*'})\n  var pwc = prompt.hide('enter another hidden password: ')\n  var autocompleteTest = prompt('custom autocomplete: ', {\n    autocomplete: complete(['bye1234', 'by', 'bye12', 'bye123456'])\n  });\n\n  prompt.history.save();\n\n  console.log('\\nName: %s\\nPassword *: %s\\nHidden password: %s\\nAnother Hidden password: %s', name, pw, pwb, pwc);\n  console.log('autocomplete2: ', autocompleteTest);\n\n  function complete(commands) {\n    return function (str) {\n      var i;\n      var ret = [];\n      for (i=0; i< commands.length; i++) {\n        if (commands[i].indexOf(str) == 0)\n          ret.push(commands[i]);\n      }\n      return ret;\n    };\n  };\n```\n"
  },
  {
    "path": "index.js",
    "content": "'use strict'\n\nvar fs = require('fs');\nvar stripAnsi = require('strip-ansi');\nvar term = 13; // carriage return\n\n/**\n * create -- sync function for reading user input from stdin\n * @param   {Object} config {\n *   sigint: {Boolean} exit on ^C\n *   autocomplete: {StringArray} function({String})\n *   history: {String} a history control object (see `prompt-sync-history`)\n * }\n * @returns {Function} prompt function\n */\n\n // for ANSI escape codes reference see https://en.wikipedia.org/wiki/ANSI_escape_code\n\nfunction create(config) {\n\n  config = config || {};\n  var sigint = config.sigint;\n  var eot = config.eot;\n  var autocomplete = config.autocomplete =\n    config.autocomplete || function(){return []};\n  var history = config.history;\n  prompt.history = history || {save: function(){}};\n  prompt.hide = function (ask) { return prompt(ask, {echo: ''}) };\n\n  return prompt;\n\n\n  /**\n   * prompt -- sync function for reading user input from stdin\n   *  @param {String} ask opening question/statement to prompt for\n   *  @param {String} value initial value for the prompt\n   *  @param   {Object} opts {\n   *   echo: set to a character to be echoed, default is '*'. Use '' for no echo\n   *   value: {String} initial value for the prompt\n   *   ask: {String} opening question/statement to prompt for, does not override ask param\n   *   autocomplete: {StringArray} function({String})\n   * }\n   *\n   * @returns {string} Returns the string input or (if sigint === false)\n   *                   null if user terminates with a ^C\n   */\n\n\n  function prompt(ask, value, opts) {\n    var insert = 0, savedinsert = 0, res, i, savedstr;\n    opts = opts || {};\n\n    if (Object(ask) === ask) {\n      opts = ask;\n      ask = opts.ask;\n    } else if (Object(value) === value) {\n      opts = value;\n      value = opts.value;\n    }\n    ask = ask || '';\n    var echo = opts.echo;\n    var masked = 'echo' in opts;\n    autocomplete = opts.autocomplete || autocomplete;\n\n    var fd = (process.platform === 'win32') ?\n      process.stdin.fd :\n      fs.openSync('/dev/tty', 'rs');\n\n    var wasRaw = process.stdin.isRaw;\n    if (!wasRaw) { process.stdin.setRawMode && process.stdin.setRawMode(true); }\n\n    var buf = Buffer.alloc(3);\n    var str = '', character, read;\n\n    savedstr = '';\n\n    if (ask) {\n      process.stdout.write(ask);\n    }\n\n    var cycle = 0;\n    var prevComplete;\n\n    while (true) {\n      read = fs.readSync(fd, buf, 0, 3);\n      if (read > 1) { // received a control sequence\n        switch(buf.toString()) {\n          case '\\u001b[A':  //up arrow\n            if (masked) break;\n            if (!history) break;\n            if (history.atStart()) break;\n\n            if (history.atEnd()) {\n              savedstr = str;\n              savedinsert = insert;\n            }\n            str = history.prev();\n            insert = str.length;\n            process.stdout.write('\\u001b[2K\\u001b[0G' + ask + str);\n            break;\n          case '\\u001b[B':  //down arrow\n            if (masked) break;\n            if (!history) break;\n            if (history.pastEnd()) break;\n\n            if (history.atPenultimate()) {\n              str = savedstr;\n              insert = savedinsert;\n              history.next();\n            } else {\n              str = history.next();\n              insert = str.length;\n            }\n            process.stdout.write('\\u001b[2K\\u001b[0G'+ ask + str + '\\u001b['+(insert+ask.length+1)+'G');\n            break;\n          case '\\u001b[D': //left arrow\n            if (masked) break;\n            var before = insert;\n            insert = (--insert < 0) ? 0 : insert;\n            if (before - insert)\n              process.stdout.write('\\u001b[1D');\n            break;\n          case '\\u001b[C': //right arrow\n            if (masked) break;\n            insert = (++insert > str.length) ? str.length : insert;\n            process.stdout.write('\\u001b[' + (insert+ask.length+1) + 'G');\n            break;\n          default:\n            if (buf.toString()) {\n              str = str + buf.toString();\n              str = str.replace(/\\0/g, '');\n              insert = str.length;\n              promptPrint(masked, ask, echo, str, insert);\n              process.stdout.write('\\u001b[' + (insert+ask.length+1) + 'G');\n              buf = Buffer.alloc(3);\n            }\n        }\n        continue; // any other 3 character sequence is ignored\n      }\n\n      // if it is not a control character seq, assume only one character is read\n      character = buf[read-1];\n\n      // catch a ^C and return null\n      if (character == 3){\n        process.stdout.write('^C\\n');\n        fs.closeSync(fd);\n\n        if (sigint) process.exit(130);\n\n        process.stdin.setRawMode && process.stdin.setRawMode(wasRaw);\n\n        return null;\n      }\n\n      // catch a ^D and exit\n      if (character == 4) {\n        if (str.length == 0 && eot) {\n          process.stdout.write('exit\\n');\n          process.exit(0);\n        }\n      }\n\n      // catch the terminating character\n      if (character == term) {\n        fs.closeSync(fd);\n        if (!history) break;\n        if (!masked && str.length) history.push(str);\n        history.reset();\n        break;\n      }\n\n      // catch a TAB and implement autocomplete\n      if (character == 9) { // TAB\n        res = autocomplete(str);\n\n        if (str == res[0]) {\n          res = autocomplete('');\n        } else {\n          prevComplete = res.length;\n        }\n\n        if (res.length == 0) {\n          process.stdout.write('\\t');\n          continue;\n        }\n\n        var item = res[cycle++] || res[cycle = 0, cycle++];\n\n        if (item) {\n          process.stdout.write('\\r\\u001b[K' + ask + item);\n          str = item;\n          insert = item.length;\n        }\n      }\n\n      if (character == 127 || (process.platform == 'win32' && character == 8)) { //backspace\n        if (!insert) continue;\n        str = str.slice(0, insert-1) + str.slice(insert);\n        insert--;\n        process.stdout.write('\\u001b[2D');\n      } else {\n        if ((character < 32 ) || (character > 126))\n            continue;\n        str = str.slice(0, insert) + String.fromCharCode(character) + str.slice(insert);\n        insert++;\n      };\n\n      promptPrint(masked, ask, echo, str, insert);\n\n    }\n\n    process.stdout.write('\\n')\n\n    process.stdin.setRawMode && process.stdin.setRawMode(wasRaw);\n\n    return str || value || '';\n  };\n\n\n  function promptPrint(masked, ask, echo, str, insert) {\n    if (masked) {\n        process.stdout.write('\\u001b[2K\\u001b[0G' + ask + Array(str.length+1).join(echo));\n    } else {\n      process.stdout.write('\\u001b[s');\n      if (insert == str.length) {\n          process.stdout.write('\\u001b[2K\\u001b[0G'+ ask + str);\n      } else {\n        if (ask) {\n          process.stdout.write('\\u001b[2K\\u001b[0G'+ ask + str);\n        } else {\n          process.stdout.write('\\u001b[2K\\u001b[0G'+ str + '\\u001b[' + (str.length - insert) + 'D');\n        }\n      }\n\n      // Reposition the cursor to the right of the insertion point\n      var askLength = stripAnsi(ask).length;\n      process.stdout.write(`\\u001b[${askLength+1+(echo==''? 0:insert)}G`);\n    }\n  }\n};\n\nmodule.exports = create;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"prompt-sync\",\n  \"version\": \"4.2.0\",\n  \"description\": \"a synchronous prompt for node.js\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"node test\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/heapwolf/prompt-sync.git\"\n  },\n  \"keywords\": [\n    \"prompt\",\n    \"sync\",\n    \"blocking\",\n    \"readline\",\n    \"input\",\n    \"getline\",\n    \"repl\",\n    \"history\"\n  ],\n  \"contributors\": [\n    {\n      \"name\": \"Paolo Fragomeni\",\n      \"email\": \"paolo@async.ly\"\n    },\n    {\n      \"name\": \"David Mark Clements\",\n      \"email\": \"david.clements@nearform.com\"\n    }\n  ],\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"prompt-sync-history\": \"^1.0.1\"\n  },\n  \"dependencies\": {\n    \"strip-ansi\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "test.js",
    "content": "//basic:\nconsole.log(require('./')()('tell me something about yourself: '))\n\n// ANSI escape codes colored text test\nrequire('./')()('\\u001B[31mcolored text: \\u001B[39m');\n\nvar prompt = require('./')({\n  history: require('prompt-sync-history')(),\n  autocomplete: complete(['hello1234', 'he', 'hello', 'hello12', 'hello123456']),\n  sigint: false\n});\n\nvar value = 'frank';\nvar name = prompt('enter name: ', value);\nconsole.log('enter echo * password');\nvar pw = prompt({echo: '*'});\nvar pwb = prompt('enter hidden password (or don\\'t): ', {echo: '', value: '*pwb default*'})\nvar pwc = prompt.hide('enter another hidden password: ')\nvar autocompleteTest = prompt('custom autocomplete: ', {\n  autocomplete: complete(['bye1234', 'by', 'bye12', 'bye123456'])\n});\n\nprompt.history.save();\n\nconsole.log('\\nName: %s\\nPassword *: %s\\nHidden password: %s\\nAnother Hidden password: %s', name, pw, pwb, pwc);\nconsole.log('autocomplete2: ', autocompleteTest);\n\nfunction complete(commands) {\n  return function (str) {\n    var i;\n    var ret = [];\n    for (i=0; i< commands.length; i++) {\n      if (commands[i].indexOf(str) == 0)\n        ret.push(commands[i]);\n    }\n    return ret;\n  };\n};\n"
  }
]