@sayknow-cli/tui 0.5.2 → 0.5.8
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 +13 -0
- package/package.json +3 -3
- package/src/autocomplete.ts +11 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.5.8] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
## [0.5.7] - 2026-09-10
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `@` file search accepts Hangul chosung (초성): a bare consonant matches any syllable carrying it as its initial, so `@ㅎㄱ` finds `한글.txt`. Literal and full-syllable matches keep ranking above chosung matches, and a chosung query never matches a name with no Hangul in it.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- `@` file search and path autocomplete now match canonically decomposed (NFD) file names against composed (NFC) input. macOS reports Korean directory entries as conjoining jamo while composer keystrokes are precomposed, so `@한` found nothing even though `한글.txt` existed. Both the directory-listing prefix match and the native fuzzy matcher now compare composed forms while completion values keep the on-disk name.
|
|
16
|
+
- `@` fuzzy discovery no longer re-filters native matches through a plain ASCII subsequence check. The native matcher already returns only scored entries and is the authority on what matched, so the second pass could only discard valid Hangul results; it now filters by path (`.git` exclusion) alone.
|
|
17
|
+
|
|
5
18
|
## [0.7.8] - 2026-06-30
|
|
6
19
|
|
|
7
20
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@sayknow-cli/tui",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.8",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://sayknow-cli.com",
|
|
7
7
|
"author": "jaybeyond",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"fmt": "biome format --write ."
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@sayknow-cli/natives": "0.5.
|
|
42
|
-
"@sayknow-cli/utils": "0.5.
|
|
41
|
+
"@sayknow-cli/natives": "0.5.8",
|
|
42
|
+
"@sayknow-cli/utils": "0.5.8",
|
|
43
43
|
"lru-cache": "11.3.6",
|
|
44
44
|
"marked": "^18.0.3"
|
|
45
45
|
},
|
package/src/autocomplete.ts
CHANGED
|
@@ -743,8 +743,13 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
743
743
|
const entries = await this.#getCachedDirEntries(searchDir);
|
|
744
744
|
const suggestions: AutocompleteItem[] = [];
|
|
745
745
|
|
|
746
|
+
// Compare in NFC: macOS returns Korean directory entries as decomposed
|
|
747
|
+
// jamo while composer input is precomposed, so the same visible name
|
|
748
|
+
// would otherwise never prefix-match. Completion values keep the
|
|
749
|
+
// on-disk name.
|
|
750
|
+
const lowerSearchPrefix = searchPrefix.normalize("NFC").toLowerCase();
|
|
746
751
|
for (const entry of entries) {
|
|
747
|
-
if (!entry.name.toLowerCase().startsWith(
|
|
752
|
+
if (!entry.name.normalize("NFC").toLowerCase().startsWith(lowerSearchPrefix)) {
|
|
748
753
|
continue;
|
|
749
754
|
}
|
|
750
755
|
// Skip .git directory
|
|
@@ -835,14 +840,14 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|
|
835
840
|
const searchPath = scopedQuery?.baseDir ?? this.#basePath;
|
|
836
841
|
const fuzzyQuery = scopedQuery?.query ?? query;
|
|
837
842
|
const result = await fuzzyFind(buildAutocompleteFuzzyDiscoveryProfile(fuzzyQuery, searchPath));
|
|
838
|
-
|
|
843
|
+
// The native matcher is the authority for what matched: it returns only
|
|
844
|
+
// scored entries and understands Hangul composition and chosung queries.
|
|
845
|
+
// Re-running the plain ASCII subsequence check here can only discard
|
|
846
|
+
// valid matches, so this pass filters by path alone.
|
|
839
847
|
const filteredMatches = result.matches.filter(entry => {
|
|
840
848
|
const p = entry.path.endsWith("/") ? entry.path.slice(0, -1) : entry.path;
|
|
841
849
|
const normalized = p.replaceAll("\\", "/");
|
|
842
|
-
|
|
843
|
-
return false;
|
|
844
|
-
}
|
|
845
|
-
return lowerQuery.length === 0 || fuzzyMatch(lowerQuery, normalized.toLowerCase());
|
|
850
|
+
return !/(^|\/)\.git(\/|$)/.test(normalized);
|
|
846
851
|
});
|
|
847
852
|
const topEntries = filteredMatches.slice(0, 20);
|
|
848
853
|
const suggestions: AutocompleteItem[] = [];
|