eyeprolog 1.6.22 → 1.6.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/repl.js +41 -21
- package/test/regression/cases-regression.mjs +13 -2
package/package.json
CHANGED
package/src/repl.js
CHANGED
|
@@ -146,7 +146,18 @@ class LineReader {
|
|
|
146
146
|
async read(prompt) {
|
|
147
147
|
this.currentPrompt = prompt;
|
|
148
148
|
this.readline.setPrompt(prompt);
|
|
149
|
-
|
|
149
|
+
// On a terminal, let readline render the prompt rather than writing it
|
|
150
|
+
// here. setPrompt tells readline how wide the prompt is, but only
|
|
151
|
+
// prompt() makes readline the thing that drew it; writing the same
|
|
152
|
+
// characters directly leaves readline redrawing the line from a column it
|
|
153
|
+
// does not believe the prompt occupies. The cursor can then travel back
|
|
154
|
+
// over the prompt, and a refresh can paint the line where the prompt
|
|
155
|
+
// already is.
|
|
156
|
+
//
|
|
157
|
+
// Without a terminal there is no line editor to own the prompt, and it
|
|
158
|
+
// still has to reach the transcript, so there it is written directly.
|
|
159
|
+
if (this.terminal) this.readline.prompt();
|
|
160
|
+
else this.output.write(prompt);
|
|
150
161
|
const result = await this.nextLine();
|
|
151
162
|
return result.done ? null : result.value;
|
|
152
163
|
}
|
|
@@ -171,26 +182,35 @@ class LineReader {
|
|
|
171
182
|
this.input.setRawMode(true);
|
|
172
183
|
this.input.resume();
|
|
173
184
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
// Raw mode has to be given back even when the wait below fails. In raw
|
|
186
|
+
// mode the terminal does no echo, performs no newline translation, and
|
|
187
|
+
// delivers Ctrl-C as a byte rather than a signal, so a session that
|
|
188
|
+
// escapes this block still in raw mode looks frozen while in fact still
|
|
189
|
+
// reading: nothing echoes, Enter returns the carriage without feeding a
|
|
190
|
+
// line, and there is no interrupt left to break out with.
|
|
191
|
+
let control;
|
|
192
|
+
try {
|
|
193
|
+
control = await new Promise((resolve, reject) => {
|
|
194
|
+
const cleanup = () => {
|
|
195
|
+
this.input.off('data', onData);
|
|
196
|
+
this.input.off('error', onError);
|
|
197
|
+
};
|
|
198
|
+
const onData = (data) => {
|
|
199
|
+
cleanup();
|
|
200
|
+
const text = String(data);
|
|
201
|
+
resolve(text === '\x04' ? null : text[0] ?? null);
|
|
202
|
+
};
|
|
203
|
+
const onError = (error) => {
|
|
204
|
+
cleanup();
|
|
205
|
+
reject(error);
|
|
206
|
+
};
|
|
207
|
+
this.input.once('data', onData);
|
|
208
|
+
this.input.once('error', onError);
|
|
209
|
+
});
|
|
210
|
+
} finally {
|
|
211
|
+
if (this.input.isRaw) this.input.setRawMode(false);
|
|
212
|
+
if (!this.readline) this.open();
|
|
213
|
+
}
|
|
194
214
|
return control;
|
|
195
215
|
}
|
|
196
216
|
|
|
@@ -3832,7 +3832,12 @@ c4 ?- call((!;1)).
|
|
|
3832
3832
|
assertEqual(result.status, 0, 'exit status');
|
|
3833
3833
|
assertIncludes(result.stdout, 'X = foo, Y = bar.', 'conjunction reads');
|
|
3834
3834
|
assertIncludes(result.stdout, 'Z = end_of_file.', 'Ctrl-D read result');
|
|
3835
|
-
|
|
3835
|
+
// On a terminal readline owns the prompt, so it redraws the line with
|
|
3836
|
+
// cursor-positioning escapes between the prompt and the echoed query.
|
|
3837
|
+
// This assertion is about the top level resuming, not about which
|
|
3838
|
+
// control sequences the line editor uses to place the cursor.
|
|
3839
|
+
const plain = result.stdout.replaceAll(/\u001b\[[0-9;]*[A-Za-z]/g, '');
|
|
3840
|
+
assertIncludes(plain, '?- true.', 'top level resumes after Ctrl-D');
|
|
3836
3841
|
assertIncludes(result.stdout, ' true.', 'post-EOF query executes');
|
|
3837
3842
|
},
|
|
3838
3843
|
},
|
|
@@ -3892,7 +3897,13 @@ c4 ?- call((!;1)).
|
|
|
3892
3897
|
]);
|
|
3893
3898
|
assertEqual(result.error?.code, undefined, 'terminal interrupt timeout');
|
|
3894
3899
|
assertEqual(result.status, 130, 'SIGINT exit status');
|
|
3895
|
-
|
|
3900
|
+
// Readline owns the prompt on a terminal and places the cursor with
|
|
3901
|
+
// escapes; the echo is what matters here, not how it was drawn.
|
|
3902
|
+
assertIncludes(
|
|
3903
|
+
result.stdout.replaceAll(/\u001b\[[0-9;]*[A-Za-z]/g, ''),
|
|
3904
|
+
'?- put_code(82), put_code(69), put_code(65), put_code(68), put_code(89), repeat, fail.',
|
|
3905
|
+
'terminal query echo',
|
|
3906
|
+
);
|
|
3896
3907
|
assertIncludes(result.stdout, 'READY', 'query entered computation');
|
|
3897
3908
|
},
|
|
3898
3909
|
},
|