@phenx-inc/ctlsurf 0.16.0 → 0.16.1
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/out/headless/index.mjs +1 -1
- package/out/headless/index.mjs.map +1 -1
- package/out/renderer/assets/{cssMode-Xx1-SozN.js → cssMode-DwHD6JSn.js} +3 -3
- package/out/renderer/assets/{freemarker2-DM49yPw1.js → freemarker2-Na9-bXYw.js} +1 -1
- package/out/renderer/assets/{handlebars-DJJBblpV.js → handlebars-D7gzKLS8.js} +1 -1
- package/out/renderer/assets/{html-DnMnJOxw.js → html-DDK7xN27.js} +1 -1
- package/out/renderer/assets/{htmlMode-BG5u2CSH.js → htmlMode-BfbLv-NB.js} +3 -3
- package/out/renderer/assets/{index-D65QIRev.js → index-HoDaBul3.js} +62 -34
- package/out/renderer/assets/{javascript-Dci_phmN.js → javascript-DJjWOxID.js} +2 -2
- package/out/renderer/assets/{jsonMode-Dmp3JJSm.js → jsonMode-BileWbig.js} +3 -3
- package/out/renderer/assets/{liquid-C9KVysk1.js → liquid-DvNU_dI9.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-IDD0-KWa.js → lspLanguageFeatures-Bb27EY8c.js} +1 -1
- package/out/renderer/assets/{mdx-ascmBFXX.js → mdx-CLkNPVgD.js} +1 -1
- package/out/renderer/assets/{python-DcbM4Hy5.js → python-DOJdL4kC.js} +1 -1
- package/out/renderer/assets/{razor-XJROxpYK.js → razor-CSr8UlJc.js} +1 -1
- package/out/renderer/assets/{tsMode-EXbzul3n.js → tsMode-sbsAvk21.js} +1 -1
- package/out/renderer/assets/{typescript-DhTtFBLt.js → typescript-r5QB4yRW.js} +1 -1
- package/out/renderer/assets/{xml-BLfEkVl1.js → xml-CYhKh3Pi.js} +1 -1
- package/out/renderer/assets/{yaml-DpzsqvWa.js → yaml-B8DsoaYW.js} +1 -1
- package/out/renderer/index.html +1 -1
- package/package.json +1 -1
- package/scripts/test-terminal-scroll.cjs +64 -0
- package/src/renderer/components/TerminalPanel.tsx +54 -20
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages } from "./index-
|
|
2
|
-
import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-
|
|
3
|
-
import { h, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages } from "./index-HoDaBul3.js";
|
|
2
|
+
import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
3
|
+
import { h, i, j, t, k } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages } from "./index-
|
|
2
|
-
import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-
|
|
3
|
-
import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages } from "./index-HoDaBul3.js";
|
|
2
|
+
import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
3
|
+
import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-DwHD6JSn.js","./lspLanguageFeatures-Bb27EY8c.js","./htmlMode-BfbLv-NB.js","./jsonMode-BileWbig.js","./javascript-DJjWOxID.js","./typescript-r5QB4yRW.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
function getDefaultExportFromCjs(x) {
|
|
3
3
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
4
4
|
}
|
|
@@ -19525,6 +19525,20 @@ function markGesture(tabId) {
|
|
|
19525
19525
|
const s = _terminals.get(tabId);
|
|
19526
19526
|
if (s) s.userScrollPending = true;
|
|
19527
19527
|
}
|
|
19528
|
+
function followLatest(state) {
|
|
19529
|
+
state.userScrollPending = false;
|
|
19530
|
+
setPinned(state, true);
|
|
19531
|
+
reassert(state);
|
|
19532
|
+
}
|
|
19533
|
+
function rememberScrollPosition(state) {
|
|
19534
|
+
state.userScrollPending = false;
|
|
19535
|
+
if (isAtBottom(state.terminal)) {
|
|
19536
|
+
setPinned(state, true);
|
|
19537
|
+
} else {
|
|
19538
|
+
state.anchorLine = state.terminal.buffer.active.viewportY;
|
|
19539
|
+
setPinned(state, false);
|
|
19540
|
+
}
|
|
19541
|
+
}
|
|
19528
19542
|
function getOrCreateTerminal(tabId, onExit) {
|
|
19529
19543
|
const existing = _terminals.get(tabId);
|
|
19530
19544
|
if (existing) {
|
|
@@ -19550,7 +19564,9 @@ function getOrCreateTerminal(tabId, onExit) {
|
|
|
19550
19564
|
fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace",
|
|
19551
19565
|
theme: currentTheme().terminal,
|
|
19552
19566
|
scrollback: 1e4,
|
|
19553
|
-
|
|
19567
|
+
// Follow explicit keyboard/paste input below. xterm also counts mouse
|
|
19568
|
+
// reports as user input, which must not pull someone out of scrollback.
|
|
19569
|
+
scrollOnUserInput: false,
|
|
19554
19570
|
allowTransparency: false
|
|
19555
19571
|
});
|
|
19556
19572
|
const fitAddon = new addonFitExports.FitAddon();
|
|
@@ -19612,17 +19628,10 @@ function getOrCreateTerminal(tabId, onExit) {
|
|
|
19612
19628
|
reassert(state);
|
|
19613
19629
|
return;
|
|
19614
19630
|
}
|
|
19615
|
-
state
|
|
19616
|
-
if (isAtBottom(terminal)) {
|
|
19617
|
-
setPinned(state, true);
|
|
19618
|
-
} else {
|
|
19619
|
-
state.anchorLine = terminal.buffer.active.viewportY;
|
|
19620
|
-
setPinned(state, false);
|
|
19621
|
-
}
|
|
19631
|
+
rememberScrollPosition(state);
|
|
19622
19632
|
});
|
|
19633
|
+
terminal.onKey(() => followLatest(state));
|
|
19623
19634
|
terminal.onData((data) => {
|
|
19624
|
-
setPinned(state, true);
|
|
19625
|
-
terminal.scrollToBottom();
|
|
19626
19635
|
window.worker.writePty(tabId, data);
|
|
19627
19636
|
});
|
|
19628
19637
|
state.unsubData = window.worker.onPtyData((eventTabId, data) => {
|
|
@@ -19680,8 +19689,7 @@ function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, isActive
|
|
|
19680
19689
|
const jumpToLatest = () => {
|
|
19681
19690
|
const s = _terminals.get(tabId);
|
|
19682
19691
|
if (!s) return;
|
|
19683
|
-
|
|
19684
|
-
s.terminal.scrollToBottom();
|
|
19692
|
+
followLatest(s);
|
|
19685
19693
|
s.terminal.focus();
|
|
19686
19694
|
};
|
|
19687
19695
|
const handleContextMenu = (e) => {
|
|
@@ -19761,6 +19769,22 @@ function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, isActive
|
|
|
19761
19769
|
if (attached) reassert(attached);
|
|
19762
19770
|
const onWheel = () => markGesture(tabId);
|
|
19763
19771
|
terminal.element?.addEventListener("wheel", onWheel, { capture: true, passive: true });
|
|
19772
|
+
const viewport = terminal.element?.querySelector(".xterm-viewport");
|
|
19773
|
+
const onViewportScroll = () => {
|
|
19774
|
+
const state = _terminals.get(tabId);
|
|
19775
|
+
if (state && !state.holding && state.userScrollPending) rememberScrollPosition(state);
|
|
19776
|
+
};
|
|
19777
|
+
viewport?.addEventListener("scroll", onViewportScroll);
|
|
19778
|
+
const onTextInput = () => {
|
|
19779
|
+
const state = _terminals.get(tabId);
|
|
19780
|
+
if (state) followLatest(state);
|
|
19781
|
+
};
|
|
19782
|
+
const onPaste = (event) => {
|
|
19783
|
+
if (event.clipboardData?.getData("text/plain")) onTextInput();
|
|
19784
|
+
};
|
|
19785
|
+
terminal.textarea?.addEventListener("paste", onPaste, true);
|
|
19786
|
+
terminal.textarea?.addEventListener("input", onTextInput, true);
|
|
19787
|
+
terminal.textarea?.addEventListener("compositionend", onTextInput, true);
|
|
19764
19788
|
let resizeTimeout;
|
|
19765
19789
|
const handleResize = () => {
|
|
19766
19790
|
clearTimeout(resizeTimeout);
|
|
@@ -19784,6 +19808,10 @@ function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, isActive
|
|
|
19784
19808
|
window.removeEventListener("resize", handleResize);
|
|
19785
19809
|
observer.disconnect();
|
|
19786
19810
|
terminal.element?.removeEventListener("wheel", onWheel, true);
|
|
19811
|
+
viewport?.removeEventListener("scroll", onViewportScroll);
|
|
19812
|
+
terminal.textarea?.removeEventListener("paste", onPaste, true);
|
|
19813
|
+
terminal.textarea?.removeEventListener("input", onTextInput, true);
|
|
19814
|
+
terminal.textarea?.removeEventListener("compositionend", onTextInput, true);
|
|
19787
19815
|
};
|
|
19788
19816
|
}, [tabId, onExit]);
|
|
19789
19817
|
reactExports.useEffect(() => {
|
|
@@ -208443,7 +208471,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
|
|
|
208443
208471
|
modeConfigurationDefault$2
|
|
208444
208472
|
);
|
|
208445
208473
|
function getMode$3() {
|
|
208446
|
-
return __vitePreload(() => import("./cssMode-
|
|
208474
|
+
return __vitePreload(() => import("./cssMode-DwHD6JSn.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
|
|
208447
208475
|
}
|
|
208448
208476
|
languages.onLanguage("less", () => {
|
|
208449
208477
|
getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
|
|
@@ -208548,7 +208576,7 @@ const razorLanguageService = registerHTMLLanguageService(
|
|
|
208548
208576
|
);
|
|
208549
208577
|
const razorDefaults = razorLanguageService.defaults;
|
|
208550
208578
|
function getMode$2() {
|
|
208551
|
-
return __vitePreload(() => import("./htmlMode-
|
|
208579
|
+
return __vitePreload(() => import("./htmlMode-BfbLv-NB.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
|
|
208552
208580
|
}
|
|
208553
208581
|
function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
|
|
208554
208582
|
const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
|
|
@@ -208632,7 +208660,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
|
|
|
208632
208660
|
);
|
|
208633
208661
|
const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
|
|
208634
208662
|
function getMode$1() {
|
|
208635
|
-
return __vitePreload(() => import("./jsonMode-
|
|
208663
|
+
return __vitePreload(() => import("./jsonMode-BileWbig.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
|
|
208636
208664
|
}
|
|
208637
208665
|
languages.register({
|
|
208638
208666
|
id: "json",
|
|
@@ -208878,7 +208906,7 @@ const getJavaScriptWorker = () => {
|
|
|
208878
208906
|
return getMode().then((mode) => mode.getJavaScriptWorker());
|
|
208879
208907
|
};
|
|
208880
208908
|
function getMode() {
|
|
208881
|
-
return __vitePreload(() => import("./tsMode-
|
|
208909
|
+
return __vitePreload(() => import("./tsMode-sbsAvk21.js"), true ? [] : void 0, import.meta.url);
|
|
208882
208910
|
}
|
|
208883
208911
|
languages.onLanguage("typescript", () => {
|
|
208884
208912
|
return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
|
|
@@ -209073,49 +209101,49 @@ registerLanguage({
|
|
|
209073
209101
|
extensions: [".ftl", ".ftlh", ".ftlx"],
|
|
209074
209102
|
aliases: ["FreeMarker2", "Apache FreeMarker2"],
|
|
209075
209103
|
loader: () => {
|
|
209076
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209104
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
209077
209105
|
}
|
|
209078
209106
|
});
|
|
209079
209107
|
registerLanguage({
|
|
209080
209108
|
id: "freemarker2.tag-angle.interpolation-dollar",
|
|
209081
209109
|
aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
|
|
209082
209110
|
loader: () => {
|
|
209083
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209111
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
|
|
209084
209112
|
}
|
|
209085
209113
|
});
|
|
209086
209114
|
registerLanguage({
|
|
209087
209115
|
id: "freemarker2.tag-bracket.interpolation-dollar",
|
|
209088
209116
|
aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
|
|
209089
209117
|
loader: () => {
|
|
209090
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209118
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
|
|
209091
209119
|
}
|
|
209092
209120
|
});
|
|
209093
209121
|
registerLanguage({
|
|
209094
209122
|
id: "freemarker2.tag-angle.interpolation-bracket",
|
|
209095
209123
|
aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
|
|
209096
209124
|
loader: () => {
|
|
209097
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209125
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
|
|
209098
209126
|
}
|
|
209099
209127
|
});
|
|
209100
209128
|
registerLanguage({
|
|
209101
209129
|
id: "freemarker2.tag-bracket.interpolation-bracket",
|
|
209102
209130
|
aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
|
|
209103
209131
|
loader: () => {
|
|
209104
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209132
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
|
|
209105
209133
|
}
|
|
209106
209134
|
});
|
|
209107
209135
|
registerLanguage({
|
|
209108
209136
|
id: "freemarker2.tag-auto.interpolation-dollar",
|
|
209109
209137
|
aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
|
|
209110
209138
|
loader: () => {
|
|
209111
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209139
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
|
|
209112
209140
|
}
|
|
209113
209141
|
});
|
|
209114
209142
|
registerLanguage({
|
|
209115
209143
|
id: "freemarker2.tag-auto.interpolation-bracket",
|
|
209116
209144
|
aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
|
|
209117
209145
|
loader: () => {
|
|
209118
|
-
return __vitePreload(() => import("./freemarker2-
|
|
209146
|
+
return __vitePreload(() => import("./freemarker2-Na9-bXYw.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
|
|
209119
209147
|
}
|
|
209120
209148
|
});
|
|
209121
209149
|
registerLanguage({
|
|
@@ -209136,7 +209164,7 @@ registerLanguage({
|
|
|
209136
209164
|
extensions: [".handlebars", ".hbs"],
|
|
209137
209165
|
aliases: ["Handlebars", "handlebars", "hbs"],
|
|
209138
209166
|
mimetypes: ["text/x-handlebars-template"],
|
|
209139
|
-
loader: () => __vitePreload(() => import("./handlebars-
|
|
209167
|
+
loader: () => __vitePreload(() => import("./handlebars-D7gzKLS8.js"), true ? [] : void 0, import.meta.url)
|
|
209140
209168
|
});
|
|
209141
209169
|
registerLanguage({
|
|
209142
209170
|
id: "hcl",
|
|
@@ -209149,7 +209177,7 @@ registerLanguage({
|
|
|
209149
209177
|
extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
|
|
209150
209178
|
aliases: ["HTML", "htm", "html", "xhtml"],
|
|
209151
209179
|
mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
|
|
209152
|
-
loader: () => __vitePreload(() => import("./html-
|
|
209180
|
+
loader: () => __vitePreload(() => import("./html-DDK7xN27.js"), true ? [] : void 0, import.meta.url)
|
|
209153
209181
|
});
|
|
209154
209182
|
registerLanguage({
|
|
209155
209183
|
id: "ini",
|
|
@@ -209172,7 +209200,7 @@ registerLanguage({
|
|
|
209172
209200
|
filenames: ["jakefile"],
|
|
209173
209201
|
aliases: ["JavaScript", "javascript", "js"],
|
|
209174
209202
|
mimetypes: ["text/javascript"],
|
|
209175
|
-
loader: () => __vitePreload(() => import("./javascript-
|
|
209203
|
+
loader: () => __vitePreload(() => import("./javascript-DJjWOxID.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
|
|
209176
209204
|
});
|
|
209177
209205
|
registerLanguage({
|
|
209178
209206
|
id: "julia",
|
|
@@ -209211,7 +209239,7 @@ registerLanguage({
|
|
|
209211
209239
|
extensions: [".liquid", ".html.liquid"],
|
|
209212
209240
|
aliases: ["Liquid", "liquid"],
|
|
209213
209241
|
mimetypes: ["application/liquid"],
|
|
209214
|
-
loader: () => __vitePreload(() => import("./liquid-
|
|
209242
|
+
loader: () => __vitePreload(() => import("./liquid-DvNU_dI9.js"), true ? [] : void 0, import.meta.url)
|
|
209215
209243
|
});
|
|
209216
209244
|
registerLanguage({
|
|
209217
209245
|
id: "m3",
|
|
@@ -209229,7 +209257,7 @@ registerLanguage({
|
|
|
209229
209257
|
id: "mdx",
|
|
209230
209258
|
extensions: [".mdx"],
|
|
209231
209259
|
aliases: ["MDX", "mdx"],
|
|
209232
|
-
loader: () => __vitePreload(() => import("./mdx-
|
|
209260
|
+
loader: () => __vitePreload(() => import("./mdx-CLkNPVgD.js"), true ? [] : void 0, import.meta.url)
|
|
209233
209261
|
});
|
|
209234
209262
|
registerLanguage({
|
|
209235
209263
|
id: "mips",
|
|
@@ -209328,7 +209356,7 @@ registerLanguage({
|
|
|
209328
209356
|
extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
|
|
209329
209357
|
aliases: ["Python", "py"],
|
|
209330
209358
|
firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
|
|
209331
|
-
loader: () => __vitePreload(() => import("./python-
|
|
209359
|
+
loader: () => __vitePreload(() => import("./python-DOJdL4kC.js"), true ? [] : void 0, import.meta.url)
|
|
209332
209360
|
});
|
|
209333
209361
|
registerLanguage({
|
|
209334
209362
|
id: "qsharp",
|
|
@@ -209347,7 +209375,7 @@ registerLanguage({
|
|
|
209347
209375
|
extensions: [".cshtml"],
|
|
209348
209376
|
aliases: ["Razor", "razor"],
|
|
209349
209377
|
mimetypes: ["text/x-cshtml"],
|
|
209350
|
-
loader: () => __vitePreload(() => import("./razor-
|
|
209378
|
+
loader: () => __vitePreload(() => import("./razor-CSr8UlJc.js"), true ? [] : void 0, import.meta.url)
|
|
209351
209379
|
});
|
|
209352
209380
|
registerLanguage({
|
|
209353
209381
|
id: "redis",
|
|
@@ -209480,7 +209508,7 @@ registerLanguage({
|
|
|
209480
209508
|
aliases: ["TypeScript", "ts", "typescript"],
|
|
209481
209509
|
mimetypes: ["text/typescript"],
|
|
209482
209510
|
loader: () => {
|
|
209483
|
-
return __vitePreload(() => import("./typescript-
|
|
209511
|
+
return __vitePreload(() => import("./typescript-r5QB4yRW.js"), true ? [] : void 0, import.meta.url);
|
|
209484
209512
|
}
|
|
209485
209513
|
});
|
|
209486
209514
|
registerLanguage({
|
|
@@ -209525,14 +209553,14 @@ registerLanguage({
|
|
|
209525
209553
|
firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
|
|
209526
209554
|
aliases: ["XML", "xml"],
|
|
209527
209555
|
mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
|
|
209528
|
-
loader: () => __vitePreload(() => import("./xml-
|
|
209556
|
+
loader: () => __vitePreload(() => import("./xml-CYhKh3Pi.js"), true ? [] : void 0, import.meta.url)
|
|
209529
209557
|
});
|
|
209530
209558
|
registerLanguage({
|
|
209531
209559
|
id: "yaml",
|
|
209532
209560
|
extensions: [".yaml", ".yml"],
|
|
209533
209561
|
aliases: ["YAML", "yaml", "YML", "yml"],
|
|
209534
209562
|
mimetypes: ["application/x-yaml", "text/x-yaml"],
|
|
209535
|
-
loader: () => __vitePreload(() => import("./yaml-
|
|
209563
|
+
loader: () => __vitePreload(() => import("./yaml-B8DsoaYW.js"), true ? [] : void 0, import.meta.url)
|
|
209536
209564
|
});
|
|
209537
209565
|
var __defProp = Object.defineProperty;
|
|
209538
209566
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { conf as conf$1, language as language$1 } from "./typescript-
|
|
2
|
-
import "./index-
|
|
1
|
+
import { conf as conf$1, language as language$1 } from "./typescript-r5QB4yRW.js";
|
|
2
|
+
import "./index-HoDaBul3.js";
|
|
3
3
|
const conf = conf$1;
|
|
4
4
|
const language = {
|
|
5
5
|
// Set defaultToken to invalid to see what you do not tokenize yet
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages, e as editor } from "./index-
|
|
2
|
-
import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-
|
|
3
|
-
import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages, e as editor } from "./index-HoDaBul3.js";
|
|
2
|
+
import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
3
|
+
import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-Bb27EY8c.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|
package/out/renderer/assets/{lspLanguageFeatures-IDD0-KWa.js → lspLanguageFeatures-Bb27EY8c.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-
|
|
1
|
+
import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-HoDaBul3.js";
|
|
2
2
|
var DocumentUri;
|
|
3
3
|
(function(DocumentUri2) {
|
|
4
4
|
function is(value) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-
|
|
1
|
+
import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-HoDaBul3.js";
|
|
2
2
|
class WorkerManager {
|
|
3
3
|
constructor(_modeId, _defaults) {
|
|
4
4
|
this._modeId = _modeId;
|
package/out/renderer/index.html
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
:root[data-theme='catppuccin-latte'] .boot-splash-title { color: #2f3145; }
|
|
107
107
|
:root[data-theme='catppuccin-latte'] .boot-splash-label { color: #7c7f93; }
|
|
108
108
|
</style>
|
|
109
|
-
<script type="module" crossorigin src="./assets/index-
|
|
109
|
+
<script type="module" crossorigin src="./assets/index-HoDaBul3.js"></script>
|
|
110
110
|
<link rel="stylesheet" crossorigin href="./assets/index-DID1LlMU.css">
|
|
111
111
|
</head>
|
|
112
112
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phenx-inc/ctlsurf",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Agent-agnostic terminal and desktop app for ctlsurf — run Claude Code, Codex, or any coding agent with live session logging and remote control",
|
|
5
5
|
"main": "out/main/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Exercise the actual React terminal panel and xterm parser in Electron.
|
|
2
|
+
// Run: node_modules/.bin/electron scripts/test-terminal-scroll.cjs
|
|
3
|
+
const { app, BrowserWindow } = require('electron')
|
|
4
|
+
const { build } = require('esbuild')
|
|
5
|
+
const fs = require('node:fs/promises')
|
|
6
|
+
const os = require('node:os')
|
|
7
|
+
const path = require('node:path')
|
|
8
|
+
app.on('window-all-closed', () => {})
|
|
9
|
+
app.on('child-process-gone', (_event, details) => console.error('Child process exited:', details))
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
console.log('Starting terminal scroll regression checks...')
|
|
13
|
+
const temp = await fs.mkdtemp(path.join(os.tmpdir(), 'ctlsurf-scroll-'))
|
|
14
|
+
app.setPath('userData', path.join(temp, 'profile'))
|
|
15
|
+
let win
|
|
16
|
+
try {
|
|
17
|
+
await build({
|
|
18
|
+
entryPoints: [path.join(__dirname, '../repro-terminal-scroll.tsx')],
|
|
19
|
+
outfile: path.join(temp, 'test.js'),
|
|
20
|
+
bundle: true,
|
|
21
|
+
platform: 'browser',
|
|
22
|
+
jsx: 'automatic',
|
|
23
|
+
external: ['@huggingface/transformers'],
|
|
24
|
+
})
|
|
25
|
+
await fs.writeFile(path.join(temp, 'index.html'), `<!doctype html><meta charset="UTF-8">
|
|
26
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'">
|
|
27
|
+
<link rel="stylesheet" href="test.css">
|
|
28
|
+
<style>
|
|
29
|
+
html, body, #root { margin: 0; width: 100%; height: 100%; }
|
|
30
|
+
.terminal-wrap, .terminal-container, .xterm { width: 100%; height: 100%; }
|
|
31
|
+
.terminal-wrap { position: relative; }
|
|
32
|
+
.term-jump-latest { position: absolute; bottom: 0; right: 0; }
|
|
33
|
+
</style>
|
|
34
|
+
<div id="root"></div><script src="test.js"></script>`)
|
|
35
|
+
await app.whenReady()
|
|
36
|
+
win = new BrowserWindow({
|
|
37
|
+
show: false, width: 900, height: 500,
|
|
38
|
+
webPreferences: { backgroundThrottling: false },
|
|
39
|
+
})
|
|
40
|
+
win.webContents.on('console-message', (event) => {
|
|
41
|
+
if (event.level === 'error') console.error(event.message)
|
|
42
|
+
})
|
|
43
|
+
win.webContents.on('render-process-gone', (_event, details) => console.error('Renderer exited:', details))
|
|
44
|
+
await win.loadFile(path.join(temp, 'index.html'))
|
|
45
|
+
let timeout
|
|
46
|
+
const result = await Promise.race([
|
|
47
|
+
win.webContents.executeJavaScript('window.scrollTest'),
|
|
48
|
+
new Promise((_, reject) => {
|
|
49
|
+
timeout = setTimeout(() => reject(new Error('Scroll test timed out')), 15_000)
|
|
50
|
+
}),
|
|
51
|
+
]).finally(() => clearTimeout(timeout))
|
|
52
|
+
for (const line of result.checks) console.log(line)
|
|
53
|
+
if (result.error) throw new Error(result.error)
|
|
54
|
+
console.log('Terminal scroll regression checks passed.')
|
|
55
|
+
} finally {
|
|
56
|
+
win?.destroy()
|
|
57
|
+
await fs.rm(temp, { recursive: true, force: true, maxRetries: 5 })
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
main().then(() => app.exit(0), (err) => {
|
|
62
|
+
console.error(err)
|
|
63
|
+
app.exit(1)
|
|
64
|
+
})
|
|
@@ -127,7 +127,7 @@ type TermState = {
|
|
|
127
127
|
// (neither down to the bottom, nor up to the top — the old bug).
|
|
128
128
|
anchorLine: number | null
|
|
129
129
|
// One-shot flag set by a real user scroll gesture (wheel / scroll keys) and
|
|
130
|
-
// consumed by the
|
|
130
|
+
// consumed by the next terminal/viewport scroll, so a redraw right after
|
|
131
131
|
// a gesture isn't mistaken for one. Spinner redraws (~10x/s while "thinking")
|
|
132
132
|
// would otherwise be misread as user intent and re-pin to the bottom.
|
|
133
133
|
userScrollPending: boolean
|
|
@@ -190,6 +190,22 @@ function markGesture(tabId: string): void {
|
|
|
190
190
|
if (s) s.userScrollPending = true
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
function followLatest(state: TermState): void {
|
|
194
|
+
state.userScrollPending = false
|
|
195
|
+
setPinned(state, true)
|
|
196
|
+
reassert(state)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function rememberScrollPosition(state: TermState): void {
|
|
200
|
+
state.userScrollPending = false
|
|
201
|
+
if (isAtBottom(state.terminal)) {
|
|
202
|
+
setPinned(state, true)
|
|
203
|
+
} else {
|
|
204
|
+
state.anchorLine = state.terminal.buffer.active.viewportY
|
|
205
|
+
setPinned(state, false)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
193
209
|
function getOrCreateTerminal(tabId: string, onExit: (tabId: string) => void): { terminal: Terminal; fitAddon: FitAddon } {
|
|
194
210
|
const existing = _terminals.get(tabId)
|
|
195
211
|
if (existing) {
|
|
@@ -216,7 +232,9 @@ function getOrCreateTerminal(tabId: string, onExit: (tabId: string) => void): {
|
|
|
216
232
|
fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace",
|
|
217
233
|
theme: currentTheme().terminal,
|
|
218
234
|
scrollback: 10000,
|
|
219
|
-
|
|
235
|
+
// Follow explicit keyboard/paste input below. xterm also counts mouse
|
|
236
|
+
// reports as user input, which must not pull someone out of scrollback.
|
|
237
|
+
scrollOnUserInput: false,
|
|
220
238
|
allowTransparency: false
|
|
221
239
|
})
|
|
222
240
|
|
|
@@ -302,19 +320,14 @@ function getOrCreateTerminal(tabId: string, onExit: (tabId: string) => void): {
|
|
|
302
320
|
reassert(state)
|
|
303
321
|
return
|
|
304
322
|
}
|
|
305
|
-
state
|
|
306
|
-
if (isAtBottom(terminal)) {
|
|
307
|
-
setPinned(state, true)
|
|
308
|
-
} else {
|
|
309
|
-
state.anchorLine = terminal.buffer.active.viewportY
|
|
310
|
-
setPinned(state, false)
|
|
311
|
-
}
|
|
323
|
+
rememberScrollPosition(state)
|
|
312
324
|
})
|
|
313
325
|
|
|
314
|
-
//
|
|
326
|
+
// onData includes automatic cursor/device/color replies and focus/mouse
|
|
327
|
+
// reports, not just keystrokes. Codex's terminal queries used to re-enable
|
|
328
|
+
// follow mode here, snapping the viewport down while reading old output.
|
|
329
|
+
terminal.onKey(() => followLatest(state))
|
|
315
330
|
terminal.onData((data) => {
|
|
316
|
-
setPinned(state, true)
|
|
317
|
-
terminal.scrollToBottom()
|
|
318
331
|
window.worker.writePty(tabId, data)
|
|
319
332
|
})
|
|
320
333
|
|
|
@@ -394,8 +407,7 @@ export function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, i
|
|
|
394
407
|
const jumpToLatest = () => {
|
|
395
408
|
const s = _terminals.get(tabId)
|
|
396
409
|
if (!s) return
|
|
397
|
-
|
|
398
|
-
s.terminal.scrollToBottom()
|
|
410
|
+
followLatest(s)
|
|
399
411
|
s.terminal.focus()
|
|
400
412
|
}
|
|
401
413
|
|
|
@@ -496,15 +508,33 @@ export function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, i
|
|
|
496
508
|
const attached = _terminals.get(tabId)
|
|
497
509
|
if (attached) reassert(attached)
|
|
498
510
|
|
|
499
|
-
// Wheel
|
|
500
|
-
// treats the resulting move as intentional (not an involuntary redraw jump).
|
|
501
|
-
// Capture is important: xterm handles wheel events on a descendant and
|
|
502
|
-
// emits onScroll synchronously. A bubbling listener runs too late, causing
|
|
503
|
-
// streamed Codex output to mistake the wheel scroll for a redraw and snap
|
|
504
|
-
// the viewport straight back to the bottom.
|
|
511
|
+
// Wheel handling starts inside xterm, so record intent in capture phase.
|
|
505
512
|
const onWheel = () => markGesture(tabId)
|
|
506
513
|
terminal.element?.addEventListener('wheel', onWheel, { capture: true, passive: true })
|
|
507
514
|
|
|
515
|
+
// xterm 5.5 suppresses its public onScroll event for native viewport
|
|
516
|
+
// scrolling. Observe the DOM event after xterm updates buffer.viewportY,
|
|
517
|
+
// otherwise a wheel gesture never pauses follow mode before the next write.
|
|
518
|
+
const viewport = terminal.element?.querySelector('.xterm-viewport')
|
|
519
|
+
const onViewportScroll = () => {
|
|
520
|
+
const state = _terminals.get(tabId)
|
|
521
|
+
if (state && !state.holding && state.userScrollPending) rememberScrollPosition(state)
|
|
522
|
+
}
|
|
523
|
+
viewport?.addEventListener('scroll', onViewportScroll)
|
|
524
|
+
|
|
525
|
+
// Paste and IME/emoji input can bypass onKey. Capture them before xterm
|
|
526
|
+
// handles the event (paste stops propagation inside xterm).
|
|
527
|
+
const onTextInput = () => {
|
|
528
|
+
const state = _terminals.get(tabId)
|
|
529
|
+
if (state) followLatest(state)
|
|
530
|
+
}
|
|
531
|
+
const onPaste = (event: ClipboardEvent) => {
|
|
532
|
+
if (event.clipboardData?.getData('text/plain')) onTextInput()
|
|
533
|
+
}
|
|
534
|
+
terminal.textarea?.addEventListener('paste', onPaste, true)
|
|
535
|
+
terminal.textarea?.addEventListener('input', onTextInput, true)
|
|
536
|
+
terminal.textarea?.addEventListener('compositionend', onTextInput, true)
|
|
537
|
+
|
|
508
538
|
// Resize handling — skip when the container is hidden (display:none → 0x0),
|
|
509
539
|
// otherwise fit() reports a tiny size and the PTY gets stuck at ~4 cols
|
|
510
540
|
// until the user switches back.
|
|
@@ -533,6 +563,10 @@ export function TerminalPanel({ tabId, agent, sessionVersion, onSpawn, onExit, i
|
|
|
533
563
|
window.removeEventListener('resize', handleResize)
|
|
534
564
|
observer.disconnect()
|
|
535
565
|
terminal.element?.removeEventListener('wheel', onWheel, true)
|
|
566
|
+
viewport?.removeEventListener('scroll', onViewportScroll)
|
|
567
|
+
terminal.textarea?.removeEventListener('paste', onPaste, true)
|
|
568
|
+
terminal.textarea?.removeEventListener('input', onTextInput, true)
|
|
569
|
+
terminal.textarea?.removeEventListener('compositionend', onTextInput, true)
|
|
536
570
|
// Do NOT dispose terminal or unsub PTY listeners — they persist across remounts
|
|
537
571
|
}
|
|
538
572
|
}, [tabId, onExit])
|