@gajae-code/tui 0.12.12 → 0.12.13
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/CHANGELOG.md +3 -0
- package/dist/types/autocomplete.d.ts +8 -8
- package/package.json +3 -3
- package/src/autocomplete.ts +16 -9
- package/src/components/editor.ts +16 -14
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.12.13] - 2026-08-06
|
|
6
|
+
|
|
5
7
|
## [0.12.12] - 2026-08-05
|
|
6
8
|
### Fixed
|
|
7
9
|
|
|
10
|
+
- Applied the compact 12–32-column primary layout to slash-command autocomplete while leaving file and other completion lists on their existing layout.
|
|
8
11
|
- Restored 60 fps time-dependent loader gradients on direct local terminals while retaining the 80 ms cadence and congestion dropping on SSH and multiplexed terminals.
|
|
9
12
|
- Bounded loader animation scheduling to 80 ms, stopped OSC 11 polling after DA1 proves the query unsupported while preserving Mode 2031 recovery, and added the default-on `GJC_TUI_SYNCHRONIZED_OUTPUT=0` compatibility opt-out for terminal parsers that mishandle synchronized-output framing. Real iOS-client validation remains pending for #3798.
|
|
10
13
|
- Decorative animation ticks now pause while stdout has more than 64 KiB buffered, preventing slow SSH terminals and multiplexers from accumulating stale spinner frames.
|
|
@@ -8,6 +8,12 @@ export interface AutocompleteItem {
|
|
|
8
8
|
/** Dim hint text shown inline after cursor when this item is selected */
|
|
9
9
|
hint?: string;
|
|
10
10
|
}
|
|
11
|
+
export type AutocompleteSuggestionKind = "slash-command" | "default";
|
|
12
|
+
export interface AutocompleteSuggestions {
|
|
13
|
+
items: AutocompleteItem[];
|
|
14
|
+
prefix: string;
|
|
15
|
+
kind?: AutocompleteSuggestionKind;
|
|
16
|
+
}
|
|
11
17
|
type Awaitable<T> = T | Promise<T>;
|
|
12
18
|
export interface SlashCommand {
|
|
13
19
|
name: string;
|
|
@@ -24,10 +30,7 @@ export interface SlashCommand {
|
|
|
24
30
|
}
|
|
25
31
|
export interface AutocompleteProvider {
|
|
26
32
|
/** Get autocomplete suggestions for current text/cursor position */
|
|
27
|
-
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<
|
|
28
|
-
items: AutocompleteItem[];
|
|
29
|
-
prefix: string;
|
|
30
|
-
} | null>;
|
|
33
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<AutocompleteSuggestions | null>;
|
|
31
34
|
/** Apply the selected item and return new text + cursor position */
|
|
32
35
|
applyCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
|
|
33
36
|
lines: string[];
|
|
@@ -59,10 +62,7 @@ export interface AutocompleteProvider {
|
|
|
59
62
|
export declare class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
60
63
|
#private;
|
|
61
64
|
constructor(commands?: (SlashCommand | AutocompleteItem)[], basePath?: string);
|
|
62
|
-
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<
|
|
63
|
-
items: AutocompleteItem[];
|
|
64
|
-
prefix: string;
|
|
65
|
-
} | null>;
|
|
65
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<AutocompleteSuggestions | null>;
|
|
66
66
|
applyCompletion(lines: string[], cursorLine: number, cursorCol: number, item: AutocompleteItem, prefix: string): {
|
|
67
67
|
lines: string[];
|
|
68
68
|
cursorLine: number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/tui",
|
|
4
|
-
"version": "0.12.
|
|
4
|
+
"version": "0.12.13",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"fmt": "biome format --write ."
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@gajae-code/natives": "0.12.
|
|
40
|
-
"@gajae-code/utils": "0.12.
|
|
39
|
+
"@gajae-code/natives": "0.12.13",
|
|
40
|
+
"@gajae-code/utils": "0.12.13",
|
|
41
41
|
"lru-cache": "11.3.6",
|
|
42
42
|
"marked": "18.0.6"
|
|
43
43
|
},
|
package/src/autocomplete.ts
CHANGED
|
@@ -242,6 +242,13 @@ export interface AutocompleteItem {
|
|
|
242
242
|
/** Dim hint text shown inline after cursor when this item is selected */
|
|
243
243
|
hint?: string;
|
|
244
244
|
}
|
|
245
|
+
export type AutocompleteSuggestionKind = "slash-command" | "default";
|
|
246
|
+
|
|
247
|
+
export interface AutocompleteSuggestions {
|
|
248
|
+
items: AutocompleteItem[];
|
|
249
|
+
prefix: string;
|
|
250
|
+
kind?: AutocompleteSuggestionKind;
|
|
251
|
+
}
|
|
245
252
|
|
|
246
253
|
type Awaitable<T> = T | Promise<T>;
|
|
247
254
|
|
|
@@ -263,14 +270,7 @@ export interface SlashCommand {
|
|
|
263
270
|
|
|
264
271
|
export interface AutocompleteProvider {
|
|
265
272
|
/** Get autocomplete suggestions for current text/cursor position */
|
|
266
|
-
getSuggestions(
|
|
267
|
-
lines: string[],
|
|
268
|
-
cursorLine: number,
|
|
269
|
-
cursorCol: number,
|
|
270
|
-
): Promise<{
|
|
271
|
-
items: AutocompleteItem[];
|
|
272
|
-
prefix: string; // What we're matching against (e.g., "/" or "src/")
|
|
273
|
-
} | null>;
|
|
273
|
+
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<AutocompleteSuggestions | null>;
|
|
274
274
|
|
|
275
275
|
/** Apply the selected item and return new text + cursor position */
|
|
276
276
|
applyCompletion(
|
|
@@ -381,7 +381,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
381
381
|
lines: string[],
|
|
382
382
|
cursorLine: number,
|
|
383
383
|
cursorCol: number,
|
|
384
|
-
): Promise<
|
|
384
|
+
): Promise<AutocompleteSuggestions | null> {
|
|
385
385
|
const currentLine = lines[cursorLine] || "";
|
|
386
386
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
387
387
|
|
|
@@ -403,6 +403,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
403
403
|
return {
|
|
404
404
|
items: suggestions,
|
|
405
405
|
prefix: atPrefix,
|
|
406
|
+
kind: "default",
|
|
406
407
|
};
|
|
407
408
|
}
|
|
408
409
|
|
|
@@ -419,6 +420,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
419
420
|
|
|
420
421
|
return {
|
|
421
422
|
items: matches,
|
|
423
|
+
kind: "slash-command",
|
|
422
424
|
prefix: textBeforeCursor,
|
|
423
425
|
};
|
|
424
426
|
}
|
|
@@ -439,6 +441,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
439
441
|
|
|
440
442
|
return {
|
|
441
443
|
items: argumentSuggestions,
|
|
444
|
+
kind: "default",
|
|
442
445
|
prefix: argumentText,
|
|
443
446
|
};
|
|
444
447
|
}
|
|
@@ -452,6 +455,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
452
455
|
if (pathSuggestions.length > 0) {
|
|
453
456
|
return {
|
|
454
457
|
items: pathSuggestions,
|
|
458
|
+
kind: "default",
|
|
455
459
|
prefix: pathMatch,
|
|
456
460
|
};
|
|
457
461
|
}
|
|
@@ -461,6 +465,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
461
465
|
if (matches.length > 0) {
|
|
462
466
|
return {
|
|
463
467
|
items: matches,
|
|
468
|
+
kind: "slash-command",
|
|
464
469
|
prefix: slashPrefix,
|
|
465
470
|
};
|
|
466
471
|
}
|
|
@@ -479,12 +484,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
479
484
|
// We still return it so user can select it and add /
|
|
480
485
|
return {
|
|
481
486
|
items: suggestions,
|
|
487
|
+
kind: "default",
|
|
482
488
|
prefix: pathMatch,
|
|
483
489
|
};
|
|
484
490
|
}
|
|
485
491
|
|
|
486
492
|
return {
|
|
487
493
|
items: suggestions,
|
|
494
|
+
kind: "default",
|
|
488
495
|
prefix: pathMatch,
|
|
489
496
|
};
|
|
490
497
|
}
|
package/src/components/editor.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getProjectDir, logger, onDefaultTabWidthChange } from "@gajae-code/utils";
|
|
2
2
|
import {
|
|
3
3
|
type AutocompleteProvider,
|
|
4
|
+
type AutocompleteSuggestionKind,
|
|
4
5
|
type CombinedAutocompleteProvider,
|
|
5
6
|
extractSlashCommandTokenPrefix,
|
|
6
7
|
isInsideInlineCodeSpan,
|
|
@@ -2838,11 +2839,7 @@ export class Editor implements Component, Focusable {
|
|
|
2838
2839
|
);
|
|
2839
2840
|
}
|
|
2840
2841
|
|
|
2841
|
-
#
|
|
2842
|
-
if (this.#autocompleteState !== "regular") {
|
|
2843
|
-
return false;
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2842
|
+
#isSlashCommandNameAutocompleteContext(): boolean {
|
|
2846
2843
|
const currentLine = this.#state.lines[this.#state.cursorLine] || "";
|
|
2847
2844
|
const textBeforeCursor = currentLine.slice(0, this.#state.cursorCol).trimStart();
|
|
2848
2845
|
return (
|
|
@@ -2850,6 +2847,14 @@ export class Editor implements Component, Focusable {
|
|
|
2850
2847
|
);
|
|
2851
2848
|
}
|
|
2852
2849
|
|
|
2850
|
+
#isSlashCommandNameAutocompleteSelection(): boolean {
|
|
2851
|
+
if (this.#autocompleteState !== "regular") {
|
|
2852
|
+
return false;
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
return this.#isSlashCommandNameAutocompleteContext();
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2853
2858
|
#isCompletedSlashCommandAtCursor(): boolean {
|
|
2854
2859
|
const currentLine = this.#state.lines[this.#state.cursorLine] || "";
|
|
2855
2860
|
if (this.#state.cursorCol !== currentLine.length) {
|
|
@@ -2890,7 +2895,7 @@ export class Editor implements Component, Focusable {
|
|
|
2890
2895
|
|
|
2891
2896
|
if (suggestions && Array.isArray(suggestions.items) && suggestions.items.length > 0) {
|
|
2892
2897
|
this.#autocompletePrefix = suggestions.prefix;
|
|
2893
|
-
this.#autocompleteList = this.#createAutocompleteList(suggestions.
|
|
2898
|
+
this.#autocompleteList = this.#createAutocompleteList(suggestions.items, suggestions.kind ?? "default");
|
|
2894
2899
|
this.#autocompleteState = "regular";
|
|
2895
2900
|
this.#autocompleteOrigin = origin;
|
|
2896
2901
|
this.onAutocompleteUpdate?.();
|
|
@@ -2901,14 +2906,11 @@ export class Editor implements Component, Focusable {
|
|
|
2901
2906
|
}
|
|
2902
2907
|
}
|
|
2903
2908
|
#createAutocompleteList(
|
|
2904
|
-
prefix: string,
|
|
2905
2909
|
items: Array<{ value: string; label: string; description?: string }>,
|
|
2910
|
+
kind: AutocompleteSuggestionKind,
|
|
2906
2911
|
): SelectList {
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
// TODO: Pass layout to SelectList when constructor is updated to support it
|
|
2910
|
-
void layout; // Use layout variable to avoid lint warnings
|
|
2911
|
-
return new SelectList(items, this.#autocompleteMaxVisible, this.#theme.selectList);
|
|
2912
|
+
const layout = kind === "slash-command" ? SLASH_COMMAND_SELECT_LIST_LAYOUT : undefined;
|
|
2913
|
+
return new SelectList(items, this.#autocompleteMaxVisible, this.#theme.selectList, layout);
|
|
2912
2914
|
}
|
|
2913
2915
|
|
|
2914
2916
|
#handleTabCompletion(): void {
|
|
@@ -2985,7 +2987,7 @@ https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/
|
|
|
2985
2987
|
}
|
|
2986
2988
|
|
|
2987
2989
|
this.#autocompletePrefix = suggestions.prefix;
|
|
2988
|
-
this.#autocompleteList = this.#createAutocompleteList(suggestions.
|
|
2990
|
+
this.#autocompleteList = this.#createAutocompleteList(suggestions.items, "default");
|
|
2989
2991
|
this.#autocompleteState = "force";
|
|
2990
2992
|
this.#autocompleteOrigin = origin;
|
|
2991
2993
|
this.onAutocompleteUpdate?.();
|
|
@@ -3035,7 +3037,7 @@ https://github.com/EsotericSoftware/spine-runtimes/actions/runs/19536643416/job/
|
|
|
3035
3037
|
if (suggestions && Array.isArray(suggestions.items) && suggestions.items.length > 0) {
|
|
3036
3038
|
this.#autocompletePrefix = suggestions.prefix;
|
|
3037
3039
|
// Always create new SelectList to ensure update
|
|
3038
|
-
this.#autocompleteList = this.#createAutocompleteList(suggestions.
|
|
3040
|
+
this.#autocompleteList = this.#createAutocompleteList(suggestions.items, suggestions.kind ?? "default");
|
|
3039
3041
|
this.#autocompleteOrigin = origin;
|
|
3040
3042
|
this.onAutocompleteUpdate?.();
|
|
3041
3043
|
} else {
|