1 | 'use strict';
|
---|
2 | /**
|
---|
3 | * `editor` type prompt
|
---|
4 | */
|
---|
5 |
|
---|
6 | const chalk = require('chalk');
|
---|
7 | const { editAsync } = require('external-editor');
|
---|
8 | const Base = require('./base');
|
---|
9 | const observe = require('../utils/events');
|
---|
10 | const { 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 | const events = observe(this.rl);
|
---|
26 | this.lineSubscription = events.line.subscribe(this.startExternalEditor.bind(this));
|
---|
27 |
|
---|
28 | // Trigger Validation when editor closes
|
---|
29 | const 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 | let bottomContent = '';
|
---|
50 | let 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;
|
---|