index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. 'use strict';
  2. var read = require('read');
  3. var promptly = module.exports;
  4. function prompt(message, opts, fn) {
  5. // Setup read's options
  6. var readOpts = {
  7. prompt: message,
  8. input: opts.input || process.stdin,
  9. output: opts.output || process.stdout,
  10. silent: opts.silent,
  11. replace: opts.replace || ''
  12. };
  13. // Use readline question
  14. read(readOpts, function (err, data) {
  15. // Ignore the error attribute
  16. // It is set on SIGINT or if timeout reached (we are not using timeout)
  17. if (err) {
  18. return;
  19. }
  20. // Trim?
  21. if (opts.trim) {
  22. data = data.trim();
  23. }
  24. // Mandatory?
  25. if (opts['default'] == null && !data) {
  26. return promptly.prompt(message, opts, fn);
  27. } else {
  28. data = data || opts['default'];
  29. }
  30. // Validator verification
  31. if (opts.validator) {
  32. if (!Array.isArray(opts.validator)) {
  33. opts.validator = [opts.validator];
  34. }
  35. var x;
  36. var length = opts.validator.length;
  37. for (x = 0; x < length; x += 1) {
  38. try {
  39. data = opts.validator[x](data);
  40. } catch (e) {
  41. // Retry automatically if the retry option is enabled
  42. if (opts.retry) {
  43. if (e.message) {
  44. readOpts.output.write(e.message + '\n');
  45. }
  46. return promptly.prompt(message, opts, fn);
  47. }
  48. e.retry = promptly.prompt.bind(promptly, message, opts, fn);
  49. return fn(e);
  50. }
  51. }
  52. }
  53. // Everything ok
  54. fn(null, data);
  55. });
  56. }
  57. promptly.prompt = function (message, opts, fn) {
  58. // Arguments parsing
  59. if (typeof opts === 'function') {
  60. fn = opts;
  61. opts = {};
  62. } else if (!opts) {
  63. opts = {};
  64. }
  65. if (opts.trim === undefined) {
  66. opts.trim = true;
  67. }
  68. if (opts.retry === undefined) {
  69. opts.retry = true;
  70. }
  71. if (fn) {
  72. return prompt(message, opts, fn);
  73. }
  74. return new Promise(function (resolve, reject) {
  75. prompt(message, opts, function (err, result) {
  76. if (err) {
  77. return reject(err);
  78. }
  79. resolve(result);
  80. });
  81. });
  82. };
  83. promptly.password = function (message, opts, fn) {
  84. // Arguments parsing
  85. if (typeof opts === 'function') {
  86. fn = opts;
  87. opts = {};
  88. } else {
  89. opts = opts || {};
  90. }
  91. // Set default options
  92. if (opts.silent === undefined) {
  93. opts.silent = true;
  94. }
  95. if (opts.trim === undefined) {
  96. opts.trim = false;
  97. }
  98. if (opts['default'] === undefined) {
  99. opts['default'] = '';
  100. }
  101. // Use prompt()
  102. return promptly.prompt(message, opts, fn);
  103. };
  104. promptly.confirm = function (message, opts, fn) {
  105. // Arguments parsing
  106. if (typeof opts === 'function') {
  107. fn = opts;
  108. opts = {};
  109. } else if (!opts) {
  110. opts = {};
  111. }
  112. opts.validator = opts.validator || [];
  113. if (!Array.isArray(opts.validator)) {
  114. opts.validator = [opts.validator];
  115. }
  116. // Push the validator that will coerse boolean values
  117. var validator = function (value) {
  118. if (typeof value === 'string') {
  119. value = value.toLowerCase();
  120. }
  121. switch (value) {
  122. case 'y':
  123. case 'yes':
  124. case '1':
  125. case true:
  126. return true;
  127. case 'n':
  128. case 'no':
  129. case '0':
  130. case false:
  131. return false;
  132. }
  133. throw new Error();
  134. };
  135. opts.validator.push(validator);
  136. // Use choose() with true, false
  137. return promptly.choose(message, [true, false], opts, fn);
  138. };
  139. promptly.choose = function (message, choices, opts, fn) {
  140. // Arguments parsing
  141. if (typeof opts === 'function') {
  142. fn = opts;
  143. opts = {};
  144. } else if (!opts) {
  145. opts = {};
  146. }
  147. opts.validator = opts.validator || [];
  148. if (!Array.isArray(opts.validator)) {
  149. opts.validator = [opts.validator];
  150. }
  151. // Push the choice validator
  152. var nrChoices = choices.length;
  153. var validator = function (value) {
  154. var x;
  155. for (x = 0; x < nrChoices; x++) {
  156. if (choices[x] == value) {
  157. return choices[x];
  158. }
  159. }
  160. throw new Error('Invalid choice: ' + value);
  161. };
  162. opts.validator.push(validator);
  163. // Use prompt()
  164. return promptly.prompt(message, opts, fn);
  165. };