@neuroplastio/xterm-addon-hotty 0.1.0-next.4 → 0.1.0-next.6
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/dist/hotty-xterm.js +103 -34
- package/dist/hotty-xterm.js.map +3 -3
- package/dist/types/keys.d.ts +32 -10
- package/dist/types/surface.d.ts +5 -1
- package/package.json +1 -1
package/dist/hotty-xterm.js
CHANGED
|
@@ -898,6 +898,7 @@ var ACTIONS = /* @__PURE__ */ new Set([
|
|
|
898
898
|
"page-down",
|
|
899
899
|
"input-start",
|
|
900
900
|
"input-end",
|
|
901
|
+
"select-all",
|
|
901
902
|
"newline",
|
|
902
903
|
"submit",
|
|
903
904
|
"program",
|
|
@@ -913,7 +914,21 @@ var ACTIONS = /* @__PURE__ */ new Set([
|
|
|
913
914
|
"scroll-end"
|
|
914
915
|
]);
|
|
915
916
|
var SCROLL_ACTIONS = new Set([...ACTIONS].filter((a) => a.startsWith("scroll-")));
|
|
916
|
-
var MULTILINE_ACTIONS = /* @__PURE__ */ new Set(["line-previous", "line-next", "page-up", "page-down", "
|
|
917
|
+
var MULTILINE_ACTIONS = /* @__PURE__ */ new Set(["line-previous", "line-next", "page-up", "page-down", "newline"]);
|
|
918
|
+
var MOVES = /* @__PURE__ */ new Set([
|
|
919
|
+
"char-backward",
|
|
920
|
+
"char-forward",
|
|
921
|
+
"word-backward",
|
|
922
|
+
"word-forward",
|
|
923
|
+
"line-start",
|
|
924
|
+
"line-end",
|
|
925
|
+
"line-previous",
|
|
926
|
+
"line-next",
|
|
927
|
+
"page-up",
|
|
928
|
+
"page-down",
|
|
929
|
+
"input-start",
|
|
930
|
+
"input-end"
|
|
931
|
+
]);
|
|
917
932
|
var ROW_ACTIONS = /* @__PURE__ */ new Set(["line-previous", "line-next", "page-up", "page-down"]);
|
|
918
933
|
var BACKWARD = /* @__PURE__ */ new Set(["char-backward", "word-backward", "line-start", "line-previous", "page-up", "input-start"]);
|
|
919
934
|
var INSERT = "insert";
|
|
@@ -921,7 +936,7 @@ var TERMINAL_KEYS = [
|
|
|
921
936
|
"ArrowLeft=char-backward Control+b=char-backward ArrowRight=char-forward Control+f=char-forward",
|
|
922
937
|
"Alt+ArrowLeft=word-backward Control+ArrowLeft=word-backward Alt+b=word-backward",
|
|
923
938
|
"Alt+ArrowRight=word-forward Control+ArrowRight=word-forward Alt+f=word-forward",
|
|
924
|
-
"Home=line-start
|
|
939
|
+
"Home=line-start End=line-end Control+e=line-end",
|
|
925
940
|
"Backspace=delete-char-backward Control+h=delete-char-backward",
|
|
926
941
|
"Delete=delete-char-forward Control+d=delete-char-forward",
|
|
927
942
|
"Alt+Backspace=delete-word-backward Control+w=delete-word-backward Control+Backspace=delete-word-backward",
|
|
@@ -930,6 +945,7 @@ var TERMINAL_KEYS = [
|
|
|
930
945
|
"ArrowUp=line-previous Control+p=line-previous ArrowDown=line-next Control+n=line-next",
|
|
931
946
|
"PageUp=page-up PageDown=page-down",
|
|
932
947
|
"Alt+<=input-start Control+Home=input-start Alt+>=input-end Control+End=input-end",
|
|
948
|
+
"Control+a=select-all",
|
|
933
949
|
"Control+m=newline"
|
|
934
950
|
].join(" ");
|
|
935
951
|
var segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
@@ -1181,6 +1197,15 @@ var Keymap = class {
|
|
|
1181
1197
|
if (isChar(value) && !mods.some((m) => m !== "Shift")) return INSERT;
|
|
1182
1198
|
return null;
|
|
1183
1199
|
}
|
|
1200
|
+
/** Whether the field selects with a key (SPEC §10.2, *Shift selects*):
|
|
1201
|
+
* it looks up a move, and the key's name has Shift. The field then moves
|
|
1202
|
+
* its caret and keeps the selection's anchor. */
|
|
1203
|
+
selects(name) {
|
|
1204
|
+
const k = parseKey(name);
|
|
1205
|
+
if (k === null) return false;
|
|
1206
|
+
const a = this.lookup(k);
|
|
1207
|
+
return a !== null && MOVES.has(a) && splitKey(k)[0].includes("Shift");
|
|
1208
|
+
}
|
|
1184
1209
|
};
|
|
1185
1210
|
function* bindingsOf(value) {
|
|
1186
1211
|
for (const b of value.split(/[ \t\n\f\r]+/)) {
|
|
@@ -1207,14 +1232,25 @@ function resolve(multiline, ...values) {
|
|
|
1207
1232
|
for (const [k, a] of [
|
|
1208
1233
|
["ArrowLeft", "char-backward"],
|
|
1209
1234
|
["ArrowRight", "char-forward"],
|
|
1235
|
+
["Control+ArrowLeft", "word-backward"],
|
|
1236
|
+
["Control+ArrowRight", "word-forward"],
|
|
1237
|
+
["Alt+ArrowLeft", "word-backward"],
|
|
1238
|
+
["Alt+ArrowRight", "word-forward"],
|
|
1210
1239
|
["Home", "line-start"],
|
|
1211
1240
|
["End", "line-end"],
|
|
1241
|
+
["Control+Home", "input-start"],
|
|
1242
|
+
["Control+End", "input-end"],
|
|
1212
1243
|
["Backspace", "delete-char-backward"],
|
|
1213
1244
|
["Delete", "delete-char-forward"],
|
|
1245
|
+
["Control+Backspace", "delete-word-backward"],
|
|
1246
|
+
["Control+Delete", "delete-word-forward"],
|
|
1247
|
+
["Alt+Backspace", "delete-word-backward"],
|
|
1248
|
+
["Alt+Delete", "delete-word-forward"],
|
|
1214
1249
|
["ArrowUp", "line-previous"],
|
|
1215
1250
|
["ArrowDown", "line-next"],
|
|
1216
1251
|
["PageUp", "page-up"],
|
|
1217
1252
|
["PageDown", "page-down"],
|
|
1253
|
+
["Control+a", "select-all"],
|
|
1218
1254
|
["Enter", multiline ? "newline" : "submit"]
|
|
1219
1255
|
])
|
|
1220
1256
|
m.bind(k, a);
|
|
@@ -1241,10 +1277,16 @@ function wordForward(t, p) {
|
|
|
1241
1277
|
while (p < t.chars.length && !isSpace(t.chars[p])) p++;
|
|
1242
1278
|
return p;
|
|
1243
1279
|
}
|
|
1244
|
-
function plan(t, action, rows, goal = null) {
|
|
1280
|
+
function plan(t, action, rows, goal = null, extend = false) {
|
|
1245
1281
|
if (MULTILINE_ACTIONS.has(action) && !t.multiline) return { kind: "none" };
|
|
1246
1282
|
const n = t.chars.length;
|
|
1247
1283
|
const selected = t.start < t.end;
|
|
1284
|
+
if (action === "select-all") return { kind: "move", anchor: 0, to: n };
|
|
1285
|
+
if (extend && MOVES.has(action)) {
|
|
1286
|
+
const anchor = t.caret === t.start ? t.end : t.start;
|
|
1287
|
+
const moved = plan({ ...t, start: t.caret, end: t.caret }, action, rows, goal);
|
|
1288
|
+
return moved.kind === "move" ? { ...moved, anchor } : moved;
|
|
1289
|
+
}
|
|
1248
1290
|
if (action.startsWith("delete-")) {
|
|
1249
1291
|
if (selected) return { kind: "replace", from: t.start, to: t.end, text: "" };
|
|
1250
1292
|
const p2 = t.start;
|
|
@@ -1384,6 +1426,9 @@ var Surface = class {
|
|
|
1384
1426
|
/** The document's base URL (SPEC §7.3). */
|
|
1385
1427
|
base = NO_BASE;
|
|
1386
1428
|
keyboard = false;
|
|
1429
|
+
/** The element the program knows has focus: the last `focus` named it,
|
|
1430
|
+
* or the program's `a=focus` gave it (SPEC §10.1). */
|
|
1431
|
+
told = null;
|
|
1387
1432
|
/** Detached (SPEC §5.5): nothing in the surface reaches the program. */
|
|
1388
1433
|
detachedState = false;
|
|
1389
1434
|
/** A press is on something that takes no focus (SPEC §10.1): the focus
|
|
@@ -1560,6 +1605,7 @@ var Surface = class {
|
|
|
1560
1605
|
this.dropDrag();
|
|
1561
1606
|
const had = this.keyboard || this.frameFocused();
|
|
1562
1607
|
this.keyboard = false;
|
|
1608
|
+
this.told = null;
|
|
1563
1609
|
this.focusedControl()?.blur();
|
|
1564
1610
|
if (had) this.giveBack();
|
|
1565
1611
|
}
|
|
@@ -1751,17 +1797,21 @@ var Surface = class {
|
|
|
1751
1797
|
if (target && !el) throw new Error(target);
|
|
1752
1798
|
this.programFocus = true;
|
|
1753
1799
|
try {
|
|
1754
|
-
this.
|
|
1755
|
-
|
|
1800
|
+
if (!this.frameFocused()) {
|
|
1801
|
+
this.frame.focus();
|
|
1802
|
+
this.frame.contentWindow?.focus();
|
|
1803
|
+
}
|
|
1756
1804
|
if (el) el.focus();
|
|
1757
1805
|
else if (!this.focusedControl()) this.tabbable()[0]?.focus();
|
|
1758
1806
|
this.keyboard = true;
|
|
1807
|
+
this.told = this.focusedControl();
|
|
1759
1808
|
} finally {
|
|
1760
1809
|
setTimeout(() => this.programFocus = false, 0);
|
|
1761
1810
|
}
|
|
1762
1811
|
}
|
|
1763
1812
|
/** `a=blur`, or the keyboard leaving: the edited control commits first. */
|
|
1764
1813
|
blur() {
|
|
1814
|
+
this.pressed = null;
|
|
1765
1815
|
this.commit();
|
|
1766
1816
|
if (this.keyboard) this.giveBack();
|
|
1767
1817
|
}
|
|
@@ -1812,6 +1862,7 @@ var Surface = class {
|
|
|
1812
1862
|
if (this.keyboard) {
|
|
1813
1863
|
this.commit();
|
|
1814
1864
|
this.keyboard = false;
|
|
1865
|
+
this.told = null;
|
|
1815
1866
|
this.emit("blur", "");
|
|
1816
1867
|
}
|
|
1817
1868
|
this.settle();
|
|
@@ -1839,16 +1890,24 @@ var Surface = class {
|
|
|
1839
1890
|
}
|
|
1840
1891
|
/** An element got focus: the surface takes the keyboard if the element is
|
|
1841
1892
|
* one that takes focus, and the focus is neither the program's (no echo)
|
|
1842
|
-
* nor a detached surface's.
|
|
1893
|
+
* nor a detached surface's. The program hears where the user put focus,
|
|
1894
|
+
* each time it is another element than the one it knows (SPEC §10.1). */
|
|
1843
1895
|
onFocusIn(e) {
|
|
1844
|
-
|
|
1845
|
-
if (this.
|
|
1896
|
+
const el = isElement(e.target) ? e.target : null;
|
|
1897
|
+
if (this.programFocus) {
|
|
1898
|
+
this.told = el;
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
if (this.auxPress) return;
|
|
1902
|
+
if (this.detachedState || this.pressNothing || !el || !takesFocus(el, this.hyper)) {
|
|
1846
1903
|
this.settle();
|
|
1847
1904
|
return;
|
|
1848
1905
|
}
|
|
1849
|
-
|
|
1906
|
+
const gained = !this.keyboard;
|
|
1850
1907
|
this.keyboard = true;
|
|
1851
|
-
this.
|
|
1908
|
+
if (!gained && el === this.told) return;
|
|
1909
|
+
this.told = el;
|
|
1910
|
+
this.emit("focus", el.closest('[id]:not([id=""])')?.id ?? "");
|
|
1852
1911
|
}
|
|
1853
1912
|
tabbable() {
|
|
1854
1913
|
const all = this.doc.querySelectorAll(
|
|
@@ -2001,6 +2060,7 @@ var Surface = class {
|
|
|
2001
2060
|
const keys = data === null ? [{ key: domKeyName(e), data: "" }] : inputKeys(data);
|
|
2002
2061
|
const keymap = this.keymapOf(el, multiline);
|
|
2003
2062
|
const uses = keys.map((k) => k.key === null ? null : keymap.lookup(k.key));
|
|
2063
|
+
const extend = keys.map((k) => k.key !== null && keymap.selects(k.key));
|
|
2004
2064
|
if (uses.every((u) => u === null)) {
|
|
2005
2065
|
const program = keys.some((k) => k.key !== null && keymap.program(k.key));
|
|
2006
2066
|
if (!program && this.axes && this.scrollKey(e)) return;
|
|
@@ -2029,7 +2089,7 @@ var Surface = class {
|
|
|
2029
2089
|
} else if (use === "submit") {
|
|
2030
2090
|
this.goal = null;
|
|
2031
2091
|
submitFrom(el);
|
|
2032
|
-
} else this.edit(el, multiline, { kind: "action", action: use });
|
|
2092
|
+
} else this.edit(el, multiline, { kind: "action", action: use, extend: extend[i] });
|
|
2033
2093
|
});
|
|
2034
2094
|
}
|
|
2035
2095
|
/** A field's keymap (SPEC §10.2): the default, then the `data-keys` of
|
|
@@ -2057,6 +2117,7 @@ var Surface = class {
|
|
|
2057
2117
|
};
|
|
2058
2118
|
const start = index(el.selectionStart ?? el.value.length);
|
|
2059
2119
|
const end = index(el.selectionEnd ?? el.value.length);
|
|
2120
|
+
const caret = el.selectionDirection === "backward" ? start : end;
|
|
2060
2121
|
if (what.kind === "type") {
|
|
2061
2122
|
this.goal = null;
|
|
2062
2123
|
this.replace(el, at[start], at[end], what.text);
|
|
@@ -2064,14 +2125,16 @@ var Surface = class {
|
|
|
2064
2125
|
}
|
|
2065
2126
|
const action = what.action;
|
|
2066
2127
|
const password = el.localName === "input" && this.inputType(el) === "password";
|
|
2067
|
-
const text2 = { chars: cl, start, end, multiline, password };
|
|
2128
|
+
const text2 = { chars: cl, start, end, caret, multiline, password };
|
|
2068
2129
|
const g = this.goal;
|
|
2069
|
-
const goal = ROW_ACTIONS.has(action) && g && g.el === el &&
|
|
2130
|
+
const goal = ROW_ACTIONS.has(action) && g && g.el === el && g.caret === caret ? g.x : null;
|
|
2070
2131
|
const rows = multiline && ROW_ACTIONS.has(action) ? this.textareaRows(el, cl) : null;
|
|
2071
|
-
const p = plan(text2, action, rows, goal);
|
|
2132
|
+
const p = plan(text2, action, rows, goal, what.extend);
|
|
2072
2133
|
this.goal = p.kind === "move" && p.goal !== void 0 ? { el, caret: p.to, x: p.goal } : null;
|
|
2073
|
-
if (p.kind === "move")
|
|
2074
|
-
|
|
2134
|
+
if (p.kind === "move") {
|
|
2135
|
+
const a = p.anchor ?? p.to;
|
|
2136
|
+
el.setSelectionRange(at[Math.min(a, p.to)], at[Math.max(a, p.to)], a > p.to ? "backward" : "forward");
|
|
2137
|
+
} else if (p.kind === "replace") this.replace(el, at[p.from], at[p.to], p.text);
|
|
2075
2138
|
}
|
|
2076
2139
|
/** Replaces code units `from` to `to` of a field's value with `text`, the
|
|
2077
2140
|
* caret after it, as typing does. */
|
|
@@ -2160,6 +2223,10 @@ var Surface = class {
|
|
|
2160
2223
|
d.execCommand("insertLineBreak", false);
|
|
2161
2224
|
return;
|
|
2162
2225
|
}
|
|
2226
|
+
if (action === "select-all") {
|
|
2227
|
+
sel.selectAllChildren(host);
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2163
2230
|
const within = () => sel.focusNode !== null && host.contains(sel.focusNode);
|
|
2164
2231
|
const next = (dir) => {
|
|
2165
2232
|
const [an, ao, fn, fo] = [sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset];
|
|
@@ -2169,26 +2236,26 @@ var Surface = class {
|
|
|
2169
2236
|
sel.setBaseAndExtent(an, ao, fn, fo);
|
|
2170
2237
|
return c;
|
|
2171
2238
|
};
|
|
2172
|
-
const walk = (
|
|
2239
|
+
const walk = (alter2, dir, go) => {
|
|
2173
2240
|
for (let i = 0; i < 1e5; i++) {
|
|
2174
2241
|
const c = next(dir);
|
|
2175
2242
|
if (!c || !go(c)) return;
|
|
2176
|
-
sel.modify(
|
|
2243
|
+
sel.modify(alter2, dir, "character");
|
|
2177
2244
|
}
|
|
2178
2245
|
};
|
|
2179
|
-
const back = (
|
|
2246
|
+
const back = (alter2, unit) => {
|
|
2180
2247
|
if (unit === "word") {
|
|
2181
|
-
walk(
|
|
2182
|
-
walk(
|
|
2183
|
-
} else if (unit === "line") walk(
|
|
2184
|
-
else sel.modify(
|
|
2248
|
+
walk(alter2, "backward", isSpace);
|
|
2249
|
+
walk(alter2, "backward", (c) => !isSpace(c));
|
|
2250
|
+
} else if (unit === "line") walk(alter2, "backward", (c) => !isBreak(c));
|
|
2251
|
+
else sel.modify(alter2, "backward", "character");
|
|
2185
2252
|
};
|
|
2186
|
-
const forward = (
|
|
2253
|
+
const forward = (alter2, unit) => {
|
|
2187
2254
|
if (unit === "word") {
|
|
2188
|
-
walk(
|
|
2189
|
-
walk(
|
|
2190
|
-
} else if (unit === "line") walk(
|
|
2191
|
-
else sel.modify(
|
|
2255
|
+
walk(alter2, "forward", isSpace);
|
|
2256
|
+
walk(alter2, "forward", (c) => !isSpace(c));
|
|
2257
|
+
} else if (unit === "line") walk(alter2, "forward", (c) => !isBreak(c));
|
|
2258
|
+
else sel.modify(alter2, "forward", "character");
|
|
2192
2259
|
};
|
|
2193
2260
|
if (action.startsWith("delete-")) {
|
|
2194
2261
|
if (sel.isCollapsed) {
|
|
@@ -2200,28 +2267,29 @@ var Surface = class {
|
|
|
2200
2267
|
return;
|
|
2201
2268
|
}
|
|
2202
2269
|
const backward = ["char-backward", "word-backward", "line-start", "line-previous", "page-up", "input-start"].includes(action);
|
|
2203
|
-
|
|
2270
|
+
const alter = what.extend ? "extend" : "move";
|
|
2271
|
+
if (!what.extend && !sel.isCollapsed) {
|
|
2204
2272
|
if (backward) sel.collapseToStart();
|
|
2205
2273
|
else sel.collapseToEnd();
|
|
2206
2274
|
if (action === "char-backward" || action === "char-forward") return;
|
|
2207
2275
|
}
|
|
2208
2276
|
const by = { "char-backward": "char", "char-forward": "char", "word-backward": "word", "word-forward": "word", "line-start": "line", "line-end": "line" }[action];
|
|
2209
2277
|
if (by) {
|
|
2210
|
-
if (backward) back(
|
|
2211
|
-
else forward(
|
|
2278
|
+
if (backward) back(alter, by);
|
|
2279
|
+
else forward(alter, by);
|
|
2212
2280
|
return;
|
|
2213
2281
|
}
|
|
2214
2282
|
if (action === "input-start" || action === "input-end") {
|
|
2215
|
-
sel.modify(
|
|
2283
|
+
sel.modify(alter, backward ? "backward" : "forward", "documentboundary");
|
|
2216
2284
|
return;
|
|
2217
2285
|
}
|
|
2218
2286
|
if (ROW_ACTIONS.has(action)) {
|
|
2219
2287
|
const rows = action.startsWith("page") ? Math.max(1, Math.round(host.clientHeight / (parseFloat(this.frame.contentWindow.getComputedStyle(host).lineHeight) || 16))) : 1;
|
|
2220
2288
|
for (let i = 0; i < rows; i++) {
|
|
2221
2289
|
const [fn, fo] = [sel.focusNode, sel.focusOffset];
|
|
2222
|
-
sel.modify(
|
|
2290
|
+
sel.modify(alter, backward ? "backward" : "forward", "line");
|
|
2223
2291
|
if (sel.focusNode === fn && sel.focusOffset === fo) {
|
|
2224
|
-
sel.modify(
|
|
2292
|
+
sel.modify(alter, backward ? "backward" : "forward", "documentboundary");
|
|
2225
2293
|
return;
|
|
2226
2294
|
}
|
|
2227
2295
|
}
|
|
@@ -2712,6 +2780,7 @@ var Surface = class {
|
|
|
2712
2780
|
this.commit();
|
|
2713
2781
|
if (this.keyboard) {
|
|
2714
2782
|
this.keyboard = false;
|
|
2783
|
+
this.told = null;
|
|
2715
2784
|
this.emit("blur", "");
|
|
2716
2785
|
}
|
|
2717
2786
|
});
|