text.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. const color = require('kleur');
  2. const Prompt = require('./prompt');
  3. const { cursor } = require('sisteransi');
  4. const { style, clear } = require('../util');
  5. /**
  6. * TextPrompt Base Element
  7. * @param {Object} opts Options
  8. * @param {String} opts.message Message
  9. * @param {String} [opts.style='default'] Render style
  10. * @param {String} [opts.initial] Default value
  11. */
  12. class TextPrompt extends Prompt {
  13. constructor(opts={}) {
  14. super(opts);
  15. this.transform = style.render(opts.style);
  16. this.scale = this.transform.scale;
  17. this.msg = opts.message;
  18. this.initial = opts.initial || '';
  19. this.value = '';
  20. this.cursor = Number(!!this.initial);
  21. this.clear = clear('');
  22. this.render();
  23. }
  24. set value(v) {
  25. if (!v && this.initial) {
  26. this.placeholder = true;
  27. this.rendered = color.gray(this.transform.render(this.initial));
  28. } else {
  29. this.placeholder = false;
  30. this.rendered = this.transform.render(v);
  31. }
  32. this._value = v;
  33. this.fire();
  34. }
  35. get value() {
  36. return this._value;
  37. }
  38. reset() {
  39. this.value = '';
  40. this.fire();
  41. this.render();
  42. }
  43. abort() {
  44. this.value = this.value || this.initial;
  45. this.done = this.aborted = true;
  46. this.fire();
  47. this.render();
  48. this.out.write('\n');
  49. this.close();
  50. }
  51. submit() {
  52. this.value = this.value || this.initial;
  53. this.done = true;
  54. this.aborted = false;
  55. this.fire();
  56. this.render();
  57. this.out.write('\n');
  58. this.close();
  59. }
  60. next() {
  61. if (!this.placeholder) return this.bell();
  62. this.value = this.initial;
  63. this.cursor = this.rendered.length;
  64. this.fire();
  65. this.render();
  66. }
  67. moveCursor(n) {
  68. if (this.placeholder) return;
  69. this.cursor = this.cursor+n;
  70. }
  71. _(c, key) {
  72. let s1 = this.value.slice(0, this.cursor);
  73. let s2 = this.value.slice(this.cursor);
  74. this.moveCursor(1);
  75. this.value = `${s1}${c}${s2}`;
  76. if (this.placeholder) this.cursor = 0;
  77. this.render();
  78. }
  79. delete() {
  80. if (this.value.length === 0) return this.bell();
  81. let s1 = this.value.slice(0, this.cursor-1);
  82. let s2 = this.value.slice(this.cursor);
  83. this.value = `${s1}${s2}`;
  84. this.moveCursor(-1);
  85. this.render();
  86. }
  87. first() {
  88. this.cursor = 0;
  89. this.render();
  90. }
  91. last() {
  92. this.cursor = this.value.length;
  93. this.render();
  94. }
  95. left() {
  96. if (this.cursor <= 0 || this.placeholder) return this.bell();
  97. this.moveCursor(-1);
  98. this.render();
  99. }
  100. right() {
  101. if (this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();
  102. this.moveCursor(1);
  103. this.render();
  104. }
  105. render() {
  106. const prompt = [
  107. style.symbol(this.done, this.aborted),
  108. color.bold(this.msg),
  109. style.delimiter(this.done),
  110. this.rendered
  111. ].join(' ');
  112. this.out.write(this.clear + prompt);
  113. this.out.write(cursor.move(this.placeholder ?
  114. -this.initial.length*this.scale :
  115. -this.rendered.length + this.cursor*this.scale
  116. ));
  117. this.clear = clear(prompt);
  118. }
  119. }
  120. module.exports = TextPrompt;