Update .bashrc
[dotfiles/.git] / prompts / editor.js
1 'use strict';
2 /**
3  * `editor` type prompt
4  */
5
6 var chalk = require('chalk');
7 var editAsync = require('external-editor').editAsync;
8 var Base = require('./base');
9 var observe = require('../utils/events');
10 var { Subject } = require('rxjs');
11
12 class EditorPrompt extends Base {
13   /**
14    * Start the Inquiry session
15    * @param  {Function} cb      Callback when prompt is done
16    * @return {this}
17    */
18
19   _run(cb) {
20     this.done = cb;
21
22     this.editorResult = new Subject();
23
24     // Open Editor on "line" (Enter Key)
25     var events = observe(this.rl);
26     this.lineSubscription = events.line.subscribe(this.startExternalEditor.bind(this));
27
28     // Trigger Validation when editor closes
29     var validation = this.handleSubmitEvents(this.editorResult);
30     validation.success.forEach(this.onEnd.bind(this));
31     validation.error.forEach(this.onError.bind(this));
32
33     // Prevents default from being printed on screen (can look weird with multiple lines)
34     this.currentText = this.opt.default;
35     this.opt.default = null;
36
37     // Init
38     this.render();
39
40     return this;
41   }
42
43   /**
44    * Render the prompt to screen
45    * @return {EditorPrompt} self
46    */
47
48   render(error) {
49     var bottomContent = '';
50     var message = this.getQuestion();
51
52     if (this.status === 'answered') {
53       message += chalk.dim('Received');
54     } else {
55       message += chalk.dim('Press <enter> to launch your preferred editor.');
56     }
57
58     if (error) {
59       bottomContent = chalk.red('>> ') + error;
60     }
61
62     this.screen.render(message, bottomContent);
63   }
64
65   /**
66    * Launch $EDITOR on user press enter
67    */
68
69   startExternalEditor() {
70     // Pause Readline to prevent stdin and stdout from being modified while the editor is showing
71     this.rl.pause();
72     editAsync(this.currentText, this.endExternalEditor.bind(this));
73   }
74
75   endExternalEditor(error, result) {
76     this.rl.resume();
77     if (error) {
78       this.editorResult.error(error);
79     } else {
80       this.editorResult.next(result);
81     }
82   }
83
84   onEnd(state) {
85     this.editorResult.unsubscribe();
86     this.lineSubscription.unsubscribe();
87     this.answer = state.value;
88     this.status = 'answered';
89     // Re-render prompt
90     this.render();
91     this.screen.done();
92     this.done(this.answer);
93   }
94
95   onError(state) {
96     this.render(state.isValid);
97   }
98 }
99
100 module.exports = EditorPrompt;