@gajae-code/tui 0.15.5 → 0.16.0

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 CHANGED
@@ -2,11 +2,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.16.0] - 2026-09-02
6
+
7
+ ## [0.15.6] - 2026-08-30
8
+
9
+ ### Fixed
10
+
11
+ - Composer file autocomplete now keeps the `@` fuzzy/chosung path reachable from explicit Tab and while Korean query characters are typed, without changing ordinary path-prefix completion.
12
+
5
13
  ## [0.15.5] - 2026-08-29
6
14
 
7
15
  ### Added
8
16
 
9
17
  - `@` fuzzy file search supports Hangul chosung (초성) matching: a bare consonant matches any syllable with that initial, so `@ㅎㄱ` finds `한글.txt`. Literal and full-syllable matches keep ranking above chosung matches.
18
+
10
19
  ## [0.15.4] - 2026-08-29
11
20
 
12
21
  ### Fixed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/tui",
4
- "version": "0.15.5",
4
+ "version": "0.16.0",
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.15.5",
40
- "@gajae-code/utils": "0.15.5",
39
+ "@gajae-code/natives": "0.16.0",
40
+ "@gajae-code/utils": "0.16.0",
41
41
  "lru-cache": "11.3.6",
42
42
  "marked": "18.0.6"
43
43
  },
@@ -17,6 +17,7 @@ async function fuzzyFindNative(): Promise<NativeFuzzyFind> {
17
17
  }
18
18
 
19
19
  const PATH_DELIMITERS = new Set([" ", "\t", '"', "'", "="]);
20
+ const MAX_AUTOCOMPLETE_SUGGESTIONS = 100;
20
21
 
21
22
  function isAbsolutePathLike(value: string): boolean {
22
23
  return path.isAbsolute(value) || path.win32.isAbsolute(value);
@@ -408,16 +409,7 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
408
409
  // Check for @ file reference (fuzzy search) - must be after a delimiter or at start
409
410
  const atPrefix = this.#extractAtPrefix(textBeforeCursor);
410
411
  if (atPrefix) {
411
- const { rawPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);
412
- const suggestions =
413
- rawPrefix.length > 0
414
- ? await this.#getFuzzyFileSuggestions(rawPrefix, { isQuotedPrefix })
415
- : await this.#getFileSuggestions("@");
416
- if (suggestions.length === 0 && rawPrefix.length > 0) {
417
- const fallback = await this.#getFileSuggestions(atPrefix);
418
- if (fallback.length === 0) return null;
419
- return { items: fallback, prefix: atPrefix };
420
- }
412
+ const suggestions = await this.#getAtFileSuggestions(atPrefix);
421
413
  if (suggestions.length === 0) return null;
422
414
 
423
415
  return {
@@ -907,6 +899,23 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
907
899
  }
908
900
  }
909
901
 
902
+ async #getAtFileSuggestions(atPrefix: string): Promise<AutocompleteItem[]> {
903
+ const prefixSuggestions = await this.#getFileSuggestions(atPrefix);
904
+ const { rawPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);
905
+ if (rawPrefix.length === 0) return prefixSuggestions.slice(0, MAX_AUTOCOMPLETE_SUGGESTIONS);
906
+
907
+ const fuzzySuggestions = await this.#getFuzzyFileSuggestions(rawPrefix, { isQuotedPrefix });
908
+ const seen = new Set(fuzzySuggestions.map(item => item.value));
909
+ return [
910
+ ...fuzzySuggestions,
911
+ ...prefixSuggestions.filter(item => {
912
+ if (seen.has(item.value)) return false;
913
+ seen.add(item.value);
914
+ return true;
915
+ }),
916
+ ].slice(0, MAX_AUTOCOMPLETE_SUGGESTIONS);
917
+ }
918
+
910
919
  // Force file completion (called on Tab key) - always returns suggestions
911
920
  async getForceFileSuggestions(
912
921
  lines: string[],
@@ -922,6 +931,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
922
931
  }
923
932
 
924
933
  // Force extract path prefix - this will always return something
934
+ const atPrefix = this.#extractAtPrefix(textBeforeCursor);
935
+ if (atPrefix !== null) {
936
+ const suggestions = await this.#getAtFileSuggestions(atPrefix);
937
+ if (suggestions.length === 0) return null;
938
+
939
+ return { items: suggestions, prefix: atPrefix };
940
+ }
941
+
925
942
  const pathMatch = this.#extractPathPrefix(textBeforeCursor, true);
926
943
  if (pathMatch !== null) {
927
944
  const suggestions = await this.#getFileSuggestions(pathMatch);
@@ -1994,7 +1994,7 @@ export class Editor implements Component, Focusable {
1994
1994
  this.#tryTriggerAutocomplete();
1995
1995
  }
1996
1996
  // Also auto-trigger when typing letters/path chars in a completable context
1997
- else if (/[a-zA-Z0-9.\-_/]/.test(char)) {
1997
+ else if (/[\p{L}0-9.\-_/]/u.test(char)) {
1998
1998
  const currentLine = this.#state.lines[this.#state.cursorLine] || "";
1999
1999
  const textBeforeCursor = currentLine.slice(0, this.#state.cursorCol);
2000
2000
  // Check if we're in a slash command or inline slash token