fix: handle non-ascii characters command (#118)
closes #106 please read the conversation to understand this PR tested on: - Accented letters: é, ü, ñ - Non-Latin scripts: Chinese characters (中文), Arabic (العربية) - Symbols & Punctuation: ©, €, ™, — - Emojis: 🚀, 😀 <img width="1312" height="976" alt="image" src="https://github.com/user-attachments/assets/613f7e2b-3681-4a64-aeeb-e44f4276c8ee" />
This commit is contained in:
+26
-8
@@ -7,6 +7,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/versenilvis/fuzzy"
|
"github.com/versenilvis/fuzzy"
|
||||||
"github.com/versenilvis/iris/integration/shell"
|
"github.com/versenilvis/iris/integration/shell"
|
||||||
@@ -28,12 +29,13 @@ func RecordSessionCommand(cmd string) {
|
|||||||
if cmd == "" {
|
if cmd == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cmd = sanitizeUTF8(cmd)
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
|
|
||||||
sessionHistoryMu.Lock()
|
sessionHistoryMu.Lock()
|
||||||
defer sessionHistoryMu.Unlock()
|
defer sessionHistoryMu.Unlock()
|
||||||
|
|
||||||
if len(sessionHistory) > 0 && sessionHistory[len(sessionHistory)-1] == cmd {
|
if len(sessionHistory) > 0 && sessionHistory[len(sessionHistory)-1] == cmd {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -51,6 +53,21 @@ func init() {
|
|||||||
idMapCache = make(map[string]int)
|
idMapCache = make(map[string]int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sanitizeUTF8(s string) string {
|
||||||
|
if utf8.ValidString(s) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
var result strings.Builder
|
||||||
|
for _, r := range s {
|
||||||
|
if r == utf8.RuneError {
|
||||||
|
result.WriteRune('�')
|
||||||
|
} else {
|
||||||
|
result.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
||||||
func SearchHistory(query string, aliases map[string]string) ([]HistResult, error) {
|
func SearchHistory(query string, aliases map[string]string) ([]HistResult, error) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
@@ -132,6 +149,7 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error
|
|||||||
|
|
||||||
cmd = strings.TrimSpace(cmd)
|
cmd = strings.TrimSpace(cmd)
|
||||||
if cmd != "" {
|
if cmd != "" {
|
||||||
|
cmd = sanitizeUTF8(cmd)
|
||||||
allCmds = append(allCmds, cmd)
|
allCmds = append(allCmds, cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,12 +240,12 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error
|
|||||||
if len(words) == 0 {
|
if len(words) == 0 {
|
||||||
words = []string{qLow}
|
words = []string{qLow}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range historyCache {
|
for _, cmd := range historyCache {
|
||||||
if seenCmds[cmd] {
|
if seenCmds[cmd] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdLow := strings.ToLower(cmd)
|
cmdLow := strings.ToLower(cmd)
|
||||||
matchAll := true
|
matchAll := true
|
||||||
for _, w := range words {
|
for _, w := range words {
|
||||||
@@ -236,11 +254,11 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matchAll {
|
if !matchAll {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
seenCmds[cmd] = true
|
seenCmds[cmd] = true
|
||||||
results = append(results, HistResult{
|
results = append(results, HistResult{
|
||||||
ID: idMapCache[cmd],
|
ID: idMapCache[cmd],
|
||||||
@@ -258,8 +276,8 @@ func SearchHistory(query string, aliases map[string]string) ([]HistResult, error
|
|||||||
if seenCmds[m.Str] {
|
if seenCmds[m.Str] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter out extremely weak fuzzy matches (e.g. random garbage typing that
|
// filter out extremely weak fuzzy matches (e.g. random garbage typing that
|
||||||
// loosely matches across a very long command)
|
// loosely matches across a very long command)
|
||||||
if len(q) > 0 && m.Score/len(q) < 150 {
|
if len(q) > 0 && m.Score/len(q) < 150 {
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user