Fixes bug where hints starting with the first alphabet's character are _almost never_ generated.

* Switches to "positional notation" to fix the bug.
* Consolidates `encode_hint` and `generate_prefix_free_hint` into `encode_hint`.
* Moves prefix_free_hints.go to hints_generator.go; `encode_hint` and `decode_hint` were moved here too.
* The "prefix-free" logic was made 0-index based instead of 1-index based for two reasons:
  1. To simplify 1-off discrepancies.
  2. To keep backwards compatibility with the old usage of `encode_hint`.
* Slight perfomance improvement added by reusing the runt-to-index map instead of rebuilding for each call to `decode_hint`.
* Unit tests added; for all new logic and old affected logic.

Fixes #10231
This commit is contained in:
Hector Tellez
2026-07-07 02:07:51 -07:00
parent cc95fccc8d
commit 501f28acdf
5 changed files with 136 additions and 114 deletions

View File

@@ -89,28 +89,6 @@ type Result struct {
Cwd string `json:"cwd"`
}
func encode_hint(num int, alphabet string) (res string) {
runes := []rune(alphabet)
d := len(runes)
for res == "" || num > 0 {
res = string(runes[num%d]) + res
num /= d
}
return
}
func decode_hint(x string, alphabet string) (ans int) {
base := len(alphabet)
index_map := make(map[rune]int, len(alphabet))
for i, c := range alphabet {
index_map[c] = i
}
for _, char := range x {
ans = ans*base + index_map[char]
}
return
}
func as_rgb(c uint32) [3]float32 {
return [3]float32{float32((c>>16)&255) / 255.0, float32((c>>8)&255) / 255.0, float32(c&255) / 255.0}
}
@@ -192,12 +170,7 @@ func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
text_style := fctx.SprintFunc(fmt.Sprintf("fg=%s bg=%s bold", o.HintsTextColor, o.HintsTextBackgroundColor))
highlight_mark := func(m *Mark, mark_text string) string {
var hint string
if o.PrefixFree {
hint = generate_prefix_free_hint(m.Index, alphabet)
} else {
hint = encode_hint(m.Index, alphabet)
}
hint := encode_hint(m.Index, alphabet)
if current_input != "" && !strings.HasPrefix(hint, current_input) {
return faint(mark_text)
}
@@ -316,13 +289,7 @@ func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
if changed {
matches := []*Mark{}
for idx, m := range index_map {
var eh string
if o.PrefixFree {
eh = generate_prefix_free_hint(idx, alphabet)
} else {
eh = encode_hint(idx, alphabet)
}
if strings.HasPrefix(eh, current_input) {
if eh := encode_hint(idx, alphabet); strings.HasPrefix(eh, current_input) {
matches = append(matches, m)
}
}
@@ -355,7 +322,8 @@ func main(_ *cli.Command, o *Options, args []string) (rc int, err error) {
} else if ev.MatchesPressOrRepeat("enter") || ev.MatchesPressOrRepeat("space") {
ev.Handled = true
if current_input != "" {
idx := decode_hint(current_input, alphabet)
char_to_index := rune_to_index_map(alphabet)
idx := decode_hint(current_input, char_to_index)
if m := index_map[idx]; m != nil {
chosen = append(chosen, m)
ignore_mark_indices.Add(idx)