eyeprolog 1.6.22 → 1.6.23

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/repl.js +29 -20
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.6.22",
6
+ "version": "1.6.23",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/repl.js CHANGED
@@ -171,26 +171,35 @@ class LineReader {
171
171
  this.input.setRawMode(true);
172
172
  this.input.resume();
173
173
 
174
- const control = await new Promise((resolve, reject) => {
175
- const cleanup = () => {
176
- this.input.off('data', onData);
177
- this.input.off('error', onError);
178
- };
179
- const onData = (data) => {
180
- cleanup();
181
- const text = String(data);
182
- resolve(text === '\x04' ? null : text[0] ?? null);
183
- };
184
- const onError = (error) => {
185
- cleanup();
186
- reject(error);
187
- };
188
- this.input.once('data', onData);
189
- this.input.once('error', onError);
190
- });
191
-
192
- this.input.setRawMode(false);
193
- this.open();
174
+ // Raw mode has to be given back even when the wait below fails. In raw
175
+ // mode the terminal does no echo, performs no newline translation, and
176
+ // delivers Ctrl-C as a byte rather than a signal, so a session that
177
+ // escapes this block still in raw mode looks frozen while in fact still
178
+ // reading: nothing echoes, Enter returns the carriage without feeding a
179
+ // line, and there is no interrupt left to break out with.
180
+ let control;
181
+ try {
182
+ control = await new Promise((resolve, reject) => {
183
+ const cleanup = () => {
184
+ this.input.off('data', onData);
185
+ this.input.off('error', onError);
186
+ };
187
+ const onData = (data) => {
188
+ cleanup();
189
+ const text = String(data);
190
+ resolve(text === '\x04' ? null : text[0] ?? null);
191
+ };
192
+ const onError = (error) => {
193
+ cleanup();
194
+ reject(error);
195
+ };
196
+ this.input.once('data', onData);
197
+ this.input.once('error', onError);
198
+ });
199
+ } finally {
200
+ if (this.input.isRaw) this.input.setRawMode(false);
201
+ if (!this.readline) this.open();
202
+ }
194
203
  return control;
195
204
  }
196
205