scripter-x 1.0.35 → 1.0.38
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/ui/fullscreen.js +7 -1
- package/src/update.js +42 -32
package/package.json
CHANGED
package/src/ui/fullscreen.js
CHANGED
|
@@ -37,6 +37,9 @@ export function FullScreen({ children }) {
|
|
|
37
37
|
// We register restore on exit + the kill signals so it runs no matter how we leave.
|
|
38
38
|
export function enterAltScreen() {
|
|
39
39
|
process.stdout.write('\x1b[?1049h'); // switch to alternate buffer
|
|
40
|
+
process.stdout.write('\x1b[r'); // reset scroll region to full screen (in case a prior
|
|
41
|
+
// session — e.g. an update-restart — left DECSTBM set,
|
|
42
|
+
// which would push our output to the bottom of the screen)
|
|
40
43
|
process.stdout.write('\x1b[2J\x1b[H'); // clear + home
|
|
41
44
|
process.stdout.write('\x1b[?25l'); // hide cursor (we draw our own ▏)
|
|
42
45
|
let restored = false;
|
|
@@ -44,7 +47,10 @@ export function enterAltScreen() {
|
|
|
44
47
|
if (restored) return;
|
|
45
48
|
restored = true;
|
|
46
49
|
try {
|
|
47
|
-
process.stdout.write('\x1b[?1000l\x1b[?1003l\x1b[?1006l'); // disable ALL mouse modes
|
|
50
|
+
process.stdout.write('\x1b[?1000l\x1b[?1003l\x1b[?1006l\x1b[?1015l'); // disable ALL mouse modes
|
|
51
|
+
process.stdout.write('\x1b[?2004l'); // disable bracketed-paste
|
|
52
|
+
process.stdout.write('\x1b[r'); // reset scroll region (so typed text isn't stuck at the bottom)
|
|
53
|
+
process.stdout.write('\x1b[?7h'); // restore line wrap
|
|
48
54
|
process.stdout.write('\x1b[?25h'); // show cursor
|
|
49
55
|
process.stdout.write('\x1b[?1049l'); // back to normal buffer (history intact)
|
|
50
56
|
} catch { /* */ }
|
package/src/update.js
CHANGED
|
@@ -95,10 +95,18 @@ function npmCliPath() {
|
|
|
95
95
|
function resetTerminal() {
|
|
96
96
|
try {
|
|
97
97
|
if (process.stdout.isTTY) {
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
process.stdout.write(
|
|
98
|
+
// Order matters. We must undo EVERY terminal mode the ink/fullscreen UI set, not just
|
|
99
|
+
// mouse + alt-screen — a leftover scroll region (DECSTBM) or bracketed-paste mode makes
|
|
100
|
+
// typed characters land at the bottom of the screen instead of at the prompt.
|
|
101
|
+
const w = (s) => process.stdout.write(s);
|
|
102
|
+
w('\x1b[?1000l\x1b[?1003l\x1b[?1006l\x1b[?1015l'); // disable ALL mouse modes
|
|
103
|
+
w('\x1b[?2004l'); // disable bracketed-paste mode
|
|
104
|
+
w('\x1b[r'); // reset scroll region (DECSTBM) to the full screen ← the bottom-text fix
|
|
105
|
+
w('\x1b[?7h'); // re-enable line wrap (autowrap)
|
|
106
|
+
w('\x1b[0m'); // reset SGR (colors/attrs)
|
|
107
|
+
w('\x1b[?1049l'); // leave alt-screen → normal buffer (history intact)
|
|
108
|
+
w('\x1b[?25h'); // show cursor
|
|
109
|
+
w('\x1b[!p'); // DECSTR: soft terminal reset (restores sane default modes)
|
|
102
110
|
}
|
|
103
111
|
} catch { /* */ }
|
|
104
112
|
try {
|
|
@@ -113,53 +121,55 @@ function resetTerminal() {
|
|
|
113
121
|
} catch { /* */ }
|
|
114
122
|
}
|
|
115
123
|
|
|
116
|
-
// Re-exec the CLI so the just-installed version takes over
|
|
117
|
-
//
|
|
118
|
-
// already torn down the ink/alt-screen UI before calling this.
|
|
124
|
+
// Re-exec the CLI so the just-installed version takes over, keeping the SAME controlling
|
|
125
|
+
// terminal so input goes to the new process — not back to the shell.
|
|
119
126
|
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
127
|
+
// THE BUG this fixes: the old code spawned the child with `detached:true` + `child.unref()`,
|
|
128
|
+
// which puts the child in its OWN session and RELINQUISHES the controlling TTY. The child
|
|
129
|
+
// then can't be the foreground job, so the user's shell (zsh) stays in the foreground and
|
|
130
|
+
// echoes every keystroke at the bottom of the screen, while the orphaned child renders the
|
|
131
|
+
// banner in the background. That's exactly the "typing shows at the bottom" symptom.
|
|
123
132
|
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
133
|
+
// Correct pattern for a TTY hand-off: spawn the child ATTACHED (not detached, no unref) with
|
|
134
|
+
// inherited stdio, and keep THIS process alive as its parent until it exits, then mirror its
|
|
135
|
+
// exit code. The child is a normal foreground job sharing our controlling terminal, so it
|
|
136
|
+
// owns stdin and raw mode works. We reset the terminal first so it boots onto a clean screen.
|
|
128
137
|
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
138
|
+
// We re-run the CURRENT entry file with node (`process.argv[1]`): after `npm install -g`, the
|
|
139
|
+
// global bin symlink points at the new version, so this loads the updated code; if that entry
|
|
140
|
+
// path is missing we fall back to the `scripterx` bin on PATH.
|
|
141
|
+
//
|
|
142
|
+
// NOTE: on success this never returns (it waits, then process.exit mirrors the child). Returns
|
|
143
|
+
// false only if BOTH spawn attempts throw synchronously.
|
|
131
144
|
export function restartCli({ binName = 'scripterx' } = {}) {
|
|
132
|
-
// Re-run with the SAME args the user launched with (drop node + the script path), so
|
|
133
|
-
// `scripterx` → interactive shell, `scripterx zepto` → zepto, etc.
|
|
134
145
|
const argv = process.argv.slice(2);
|
|
135
146
|
const entry = process.argv[1];
|
|
136
147
|
|
|
137
|
-
// Clean the terminal BEFORE spawning so the child
|
|
148
|
+
// Clean the terminal BEFORE spawning so the child boots onto a clean, cooked screen.
|
|
138
149
|
resetTerminal();
|
|
139
150
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
};
|
|
151
|
+
// ATTACHED spawn: child shares our controlling TTY and becomes the foreground job. We keep
|
|
152
|
+
// running as its parent and exit with its code when it finishes — so the shell prompt only
|
|
153
|
+
// returns after the (new) CLI actually quits.
|
|
154
|
+
const trySpawn = (cmd, args) => spawn(cmd, args, { stdio: 'inherit', shell: false });
|
|
145
155
|
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
const supervise = (child) => {
|
|
157
|
+
child.on('exit', (code, signal) => {
|
|
158
|
+
if (signal) { try { process.kill(process.pid, signal); } catch { process.exit(1); } }
|
|
159
|
+
else process.exit(code == null ? 0 : code);
|
|
160
|
+
});
|
|
150
161
|
};
|
|
151
162
|
|
|
152
163
|
try {
|
|
153
164
|
const primary = trySpawn(process.execPath, [entry, ...argv]);
|
|
154
165
|
primary.on('error', () => {
|
|
155
|
-
try { trySpawn(binName, argv); } catch {
|
|
166
|
+
try { supervise(trySpawn(binName, argv)); } catch { process.exit(1); }
|
|
156
167
|
});
|
|
157
|
-
|
|
168
|
+
supervise(primary);
|
|
158
169
|
return true;
|
|
159
170
|
} catch {
|
|
160
171
|
try {
|
|
161
|
-
trySpawn(binName, argv);
|
|
162
|
-
exitSoon();
|
|
172
|
+
supervise(trySpawn(binName, argv));
|
|
163
173
|
return true;
|
|
164
174
|
} catch {
|
|
165
175
|
return false;
|