diff --git a/README.md b/README.md index f7144899..3a848687 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ There are differences between spanner-mycli and spanner-cli that include not onl * Pager support when `CLI_USE_PAGER = TRUE` * Progress bar of DDL execution. * Syntax highlight when `CLI_ENABLE_HIGHLIGHT = TRUE` + * Fuzzy finder (default `Ctrl+T`, configurable via `CLI_FUZZY_FINDER_KEY`) powered by [fzf](https://github.com/junegunn/fzf) for databases, tables, system variables, and statement names * Utilize other libraries * Dogfooding [`cloudspannerecosystem/memefish`](https://github.com/cloudspannerecosystem/memefish) * Spin out memefish logic as [`apstndb/gsqlutils`](https://github.com/apstndb/gsqlutils). @@ -945,6 +946,7 @@ They have almost same semantics with [Spanner JDBC properties](https://cloud.goo | CLI_FIXED_WIDTH | READ_WRITE | `80` | | CLI_STREAMING | READ_WRITE | `"AUTO"` | | CLI_TABLE_PREVIEW_ROWS | READ_WRITE | `50` | +| CLI_FUZZY_FINDER_KEY | READ_WRITE | `"C_T"` | > **Note**: `CLI_FORMAT` accepts the following values: > - `TABLE` - ASCII table with borders (default for both interactive and batch modes) diff --git a/go.mod b/go.mod index 21a4812f..cdff9f8e 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 github.com/hymkor/go-multiline-ny v0.22.4 github.com/jessevdk/go-flags v1.6.1 + github.com/junegunn/fzf v0.68.0 github.com/k0kubun/pp/v3 v3.5.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/ktr0731/go-fuzzyfinder v0.9.0 github.com/mattn/go-runewidth v0.0.19 github.com/modelcontextprotocol/go-sdk v0.3.0 github.com/ngicks/go-iterator-helper v0.0.21 @@ -80,6 +80,7 @@ require ( github.com/apstndb/treeprint v0.0.0-20250529153958-e82576b37da6 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/charlievieth/fastwalk v1.0.14 // indirect github.com/clipperhouse/uax29/v2 v2.2.0 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/containerd/errdefs v1.0.0 // indirect @@ -99,7 +100,7 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gdamore/encoding v1.0.1 // indirect - github.com/gdamore/tcell/v2 v2.6.0 // indirect + github.com/gdamore/tcell/v2 v2.9.0 // indirect github.com/go-jose/go-jose/v4 v4.1.2 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -117,8 +118,8 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/gojq v0.12.17 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect + github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741 // indirect github.com/klauspost/compress v1.18.0 // indirect - github.com/ktr0731/go-ansisgr v0.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d // indirect github.com/magiconair/properties v1.8.10 // indirect @@ -135,7 +136,6 @@ require ( github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.2 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/nsf/termbox-go v1.1.1 // indirect github.com/nyaosorg/go-ttyadapter v0.3.0 // indirect github.com/olekukonko/cat v0.0.0-20250817074551-3280053e4e00 // indirect github.com/olekukonko/errors v1.1.0 // indirect diff --git a/go.sum b/go.sum index d4fd8f06..5618aec0 100644 --- a/go.sum +++ b/go.sum @@ -2517,6 +2517,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charlievieth/fastwalk v1.0.14 h1:3Eh5uaFGwHZd8EGwTjJnSpBkfwfsak9h6ICgnWlhAyg= +github.com/charlievieth/fastwalk v1.0.14/go.mod h1:diVcUreiU1aQ4/Wu3NbxxH4/KYdKpLDojrQ1Bb2KgNY= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -2631,11 +2633,10 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= -github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= -github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= +github.com/gdamore/tcell/v2 v2.9.0 h1:N6t+eqK7/xwtRPwxzs1PXeRWnm0H9l02CrgJ7DLn1ys= +github.com/gdamore/tcell/v2 v2.9.0/go.mod h1:8/ZoqM9rxzYphT9tH/9LnunhV9oPBqwS8WHGYm5nrmo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= @@ -2756,8 +2757,6 @@ github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMc github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/jsonschema-go v0.2.0 h1:Uh19091iHC56//WOsAd1oRg6yy1P9BpSvpjOL6RcjLQ= github.com/google/jsonschema-go v0.2.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -2882,6 +2881,10 @@ github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPG github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/junegunn/fzf v0.68.0 h1:5ZpGfEVOaU9bsPaIQowepyF36/sxG+czr7mTdtnZS1E= +github.com/junegunn/fzf v0.68.0/go.mod h1:xlXX2/rmsccKQUnr9QOXPDi5DyV9cM0UjKy/huScBeE= +github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741 h1:7dYDtfMDfKzjT+DVfIS4iqknSEKtZpEcXtu6vuaasHs= +github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741/go.mod h1:6EILKtGpo5t+KLb85LNZLAF6P9LKp78hJI80PXMcn3c= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/pp/v3 v3.5.0 h1:iYNlYA5HJAJvkD4ibuf9c8y6SHM0QFhaBuCqm1zHp0w= @@ -2907,10 +2910,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/ktr0731/go-ansisgr v0.1.0 h1:fbuupput8739hQbEmZn1cEKjqQFwtCCZNznnF6ANo5w= -github.com/ktr0731/go-ansisgr v0.1.0/go.mod h1:G9lxwgBwH0iey0Dw5YQd7n6PmQTwTuTM/X5Sgm/UrzE= -github.com/ktr0731/go-fuzzyfinder v0.9.0 h1:JV8S118RABzRl3Lh/RsPhXReJWc2q0rbuipzXQH7L4c= -github.com/ktr0731/go-fuzzyfinder v0.9.0/go.mod h1:uybx+5PZFCgMCSDHJDQ9M3nNKx/vccPmGffsXPn2ad8= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= @@ -2935,8 +2934,6 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -2976,8 +2973,6 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/ngicks/go-iterator-helper v0.0.21 h1:34dorbGaeL7RgxdymHBqZeL+VLL3hUyAL9QdE5HZrRQ= github.com/ngicks/go-iterator-helper v0.0.21/go.mod h1:g++KxWVGEkOnIhXVvpNNOdn7ON57aOpfu80ccBvPVHI= -github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= -github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= github.com/nyaosorg/go-readline-ny v1.14.1 h1:bWyXpR6jRaCXysx4bnioxk36+YjQ6dypHKMjHnzIXdk= github.com/nyaosorg/go-readline-ny v1.14.1/go.mod h1:/BDf3/H/AScnvey4LoDws1bjTZDB76EE7uKnW2apoKU= github.com/nyaosorg/go-ttyadapter v0.3.0 h1:/Y7+rGJ0LEcs+AExevwNmND2VJvvpBmgbMuCbntKq3c= @@ -3023,8 +3018,6 @@ github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= diff --git a/internal/mycli/cli_readline.go b/internal/mycli/cli_readline.go index c35a4766..95772bec 100644 --- a/internal/mycli/cli_readline.go +++ b/internal/mycli/cli_readline.go @@ -127,7 +127,7 @@ func initializeMultilineEditor(c *Cli) (*multiline.Editor, History, error) { return nil, nil, err } - if c.SystemVariables.EnableFuzzyFinder { + if c.SystemVariables.FuzzyFinderKey != "" { if keyCode, ok := keys.NameToCode[keys.NormalizeName(c.SystemVariables.FuzzyFinderKey)]; ok { fuzzyCmd := &fuzzyFinderCommand{cli: c} err = ed.BindKey(keyCode, fuzzyCmd) diff --git a/internal/mycli/fuzzy_finder.go b/internal/mycli/fuzzy_finder.go index a557f9f8..a2164208 100644 --- a/internal/mycli/fuzzy_finder.go +++ b/internal/mycli/fuzzy_finder.go @@ -28,7 +28,7 @@ import ( "cloud.google.com/go/spanner" "cloud.google.com/go/spanner/admin/database/apiv1/databasepb" "github.com/hymkor/go-multiline-ny" - "github.com/ktr0731/go-fuzzyfinder" + fzf "github.com/junegunn/fzf/src" "github.com/nyaosorg/go-readline-ny" "google.golang.org/api/iterator" ) @@ -73,30 +73,29 @@ func (f *fuzzyFinderCommand) Call(ctx context.Context, B *readline.Buffer) readl // Terminal handoff: move cursor below editor, run fzf, then restore rewind := f.editor.GotoEndLine() - opts := []fuzzyfinder.Option{} - if result.argPrefix != "" { - opts = append(opts, fuzzyfinder.WithQuery(result.argPrefix)) - } - - idx, err := fuzzyfinder.Find(candidates, func(i int) string { - return candidates[i] - }, opts...) + chosen, ok := runFzf(candidates, result.argPrefix, completionHeader(result.completionType)) rewind() B.RepaintLastLine() - if err != nil { - // User cancelled (Escape/Ctrl+C) or other error + if !ok { + // User cancelled (Escape/Ctrl+C) or no match return readline.CONTINUE } var selected string if result.completionType != 0 { // Argument completion: insert the candidate with optional suffix - selected = candidates[idx] + result.suffix + selected = chosen + result.suffix } else { - // Statement name completion: insert the fixed prefix text - selected = statementNameCandidates[idx].InsertText + // Statement name completion: insert the fixed prefix text. + // No-arg statements (no trailing space) get a semicolon for immediate submit. + insertText := statementNameInsertText(chosen) + if strings.HasSuffix(insertText, " ") { + selected = insertText + } else { + selected = insertText + ";" + } } // Replace the argument portion: delete from argStartPos to end of buffer, @@ -173,8 +172,83 @@ type statementNameCandidate struct { // statementNameCandidates is built at init time from clientSideStatementDefs. var statementNameCandidates []statementNameCandidate +// statementNameInsertMap maps display text to insert text for statement name completion. +// fzf returns the selected string (not an index), so we need this lookup. +var statementNameInsertMap map[string]string + func init() { statementNameCandidates = buildStatementNameCandidates() + statementNameInsertMap = make(map[string]string, len(statementNameCandidates)) + for _, c := range statementNameCandidates { + statementNameInsertMap[c.DisplayText] = c.InsertText + } +} + +// statementNameInsertText returns the insert text for a given display text. +// Falls back to the display text itself if not found in the map. +func statementNameInsertText(displayText string) string { + if t, ok := statementNameInsertMap[displayText]; ok { + return t + } + return displayText +} + +// completionHeader returns a header string for the fzf UI based on completion type. +func completionHeader(ct fuzzyCompletionType) string { + switch ct { + case fuzzyCompleteDatabase: + return "Databases" + case fuzzyCompleteVariable: + return "System Variables" + case fuzzyCompleteTable: + return "Tables" + case fuzzyCompleteVariableValue: + return "Variable Values" + default: + return "Statements" + } +} + +// runFzf runs the fzf fuzzy finder with the given candidates and optional initial query. +// Returns the selected string and true, or ("", false) if cancelled or no match. +func runFzf(candidates []string, query string, header string) (string, bool) { + opts, err := fzf.ParseOptions(false, []string{ + "--reverse", "--no-sort", + "--height=~20", + "--border=rounded", + "--info=inline-right", + }) + if err != nil { + slog.Debug("fuzzy finder: parse fzf options", "err", err) + return "", false + } + if query != "" { + opts.Query = query + } + if header != "" { + opts.Header = []string{header} + } + opts.ForceTtyIn = true + + inputChan := make(chan string, len(candidates)) + for _, c := range candidates { + inputChan <- c + } + close(inputChan) + opts.Input = inputChan + + var result string + var selected bool + opts.Printer = func(s string) { + result = s + selected = true + } + + code, err := fzf.Run(opts) + if err != nil && code != fzf.ExitInterrupt && code != fzf.ExitNoMatch { + slog.Debug("fuzzy finder: fzf run error", "code", code, "err", err) + } + return result, selected } // statementNameDisplayTexts returns the display texts for fzf. diff --git a/internal/mycli/fuzzy_finder_test.go b/internal/mycli/fuzzy_finder_test.go index 4f1f64ad..047ede02 100644 --- a/internal/mycli/fuzzy_finder_test.go +++ b/internal/mycli/fuzzy_finder_test.go @@ -394,6 +394,37 @@ func TestBuildStatementNameCandidates(t *testing.T) { assert.Equal(t, "SHOW COLUMNS FROM ", displayTexts["SHOW COLUMNS FROM "]) } +func TestStatementNameInsertText(t *testing.T) { + tests := []struct { + name string + displayText string + want string + }{ + { + name: "known no-arg statement", + displayText: "SHOW DATABASES", + want: "SHOW DATABASES", + }, + { + name: "known arg statement", + displayText: "USE [ROLE ]", + want: "USE ", + }, + { + name: "unknown display text falls back to input", + displayText: "NONEXISTENT COMMAND", + want: "NONEXISTENT COMMAND", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := statementNameInsertText(tt.displayText) + assert.Equal(t, tt.want, got) + }) + } +} + func TestStatementNameDisplayTexts(t *testing.T) { texts := statementNameDisplayTexts() assert.Equal(t, len(statementNameCandidates), len(texts)) diff --git a/internal/mycli/main_test.go b/internal/mycli/main_test.go index e8c6c8da..9e926b77 100644 --- a/internal/mycli/main_test.go +++ b/internal/mycli/main_test.go @@ -139,9 +139,8 @@ func Test_initializeSystemVariables(t *testing.T) { "p1": lo.Must(memefish.ParseExpr("", "'string_value'")), "p2": lo.Must(memefish.ParseType("", "FLOAT64")), }, - EnableFuzzyFinder: true, - FuzzyFinderKey: "C_T", - TablePreviewRows: 50, + FuzzyFinderKey: "C_T", + TablePreviewRows: 50, }, wantErr: false, }, @@ -175,7 +174,6 @@ func Test_initializeSystemVariables(t *testing.T) { ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, Params: make(map[string]ast.Node), ReadOnlyStaleness: lo.ToPtr(spanner.ReadTimestamp(lo.Must(time.Parse(time.RFC3339Nano, "2023-01-01T00:00:00Z")))), - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -218,7 +216,6 @@ func Test_initializeSystemVariables(t *testing.T) { ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, Params: make(map[string]ast.Node), StatementTimeout: lo.ToPtr(30 * time.Second), - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -245,7 +242,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -272,7 +268,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -298,7 +293,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -344,10 +338,9 @@ func Test_initializeSystemVariables(t *testing.T) { }, }, }, - CLIFormat: enums.DisplayModeTable, - EnableFuzzyFinder: true, - FuzzyFinderKey: "C_T", - TablePreviewRows: 50, + CLIFormat: enums.DisplayModeTable, + FuzzyFinderKey: "C_T", + TablePreviewRows: 50, }, wantErr: false, }, @@ -396,7 +389,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -425,7 +417,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -455,7 +446,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -482,7 +472,6 @@ func Test_initializeSystemVariables(t *testing.T) { CLIFormat: enums.DisplayModeTable, OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -507,7 +496,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "output_full.tmpl", // OutputTemplate: should be parsed from file, hard to compare directly ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -534,7 +522,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -561,7 +548,6 @@ func Test_initializeSystemVariables(t *testing.T) { OutputTemplateFile: "", OutputTemplate: defaultOutputFormat, ParsedAnalyzeColumns: DefaultParsedAnalyzeColumns, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, }, @@ -666,7 +652,6 @@ func Test_newSystemVariablesWithDefaults(t *testing.T) { HistoryFile: defaultHistoryFile, VertexAIModel: defaultVertexAIModel, LogLevel: slog.LevelWarn, - EnableFuzzyFinder: true, FuzzyFinderKey: "C_T", TablePreviewRows: 50, Params: make(map[string]ast.Node), diff --git a/internal/mycli/system_variables.go b/internal/mycli/system_variables.go index 0db0628d..48c6c854 100644 --- a/internal/mycli/system_variables.go +++ b/internal/mycli/system_variables.go @@ -150,8 +150,7 @@ type systemVariables struct { AsyncDDL bool // CLI_ASYNC_DDL SkipSystemCommand bool // CLI_SKIP_SYSTEM_COMMAND SkipColumnNames bool // CLI_SKIP_COLUMN_NAMES - EnableFuzzyFinder bool // CLI_ENABLE_FUZZY_FINDER - FuzzyFinderKey string // CLI_FUZZY_FINDER_KEY + FuzzyFinderKey string // CLI_FUZZY_FINDER_KEY (empty = disabled) // Streaming output configuration StreamingMode enums.StreamingMode // CLI_STREAMING @@ -267,8 +266,7 @@ func newSystemVariablesWithDefaults() systemVariables { LogLevel: slog.LevelWarn, // Interactive defaults - EnableFuzzyFinder: true, - FuzzyFinderKey: "C_T", + FuzzyFinderKey: "C_T", // Streaming defaults StreamingMode: enums.StreamingModeAuto, // Default to automatic selection based on format diff --git a/internal/mycli/var_registry.go b/internal/mycli/var_registry.go index fa7e8ca4..0db759e4 100644 --- a/internal/mycli/var_registry.go +++ b/internal/mycli/var_registry.go @@ -212,10 +212,8 @@ func (r *VarRegistry) registerAll() { "Controls whether system commands are disabled.")) r.Register("CLI_SKIP_COLUMN_NAMES", BoolVar(&sv.SkipColumnNames, "A boolean indicating whether to suppress column headers in output. The default is false.")) - r.Register("CLI_ENABLE_FUZZY_FINDER", BoolVar(&sv.EnableFuzzyFinder, - "Enable fuzzy finder. The default is true.")) r.Register("CLI_FUZZY_FINDER_KEY", StringVar(&sv.FuzzyFinderKey, - "Key binding for fuzzy finder. Uses go-readline-ny key names (e.g., C_T, M_F, F1). The default is C_T (Ctrl+T).")) + "Key binding for fuzzy finder. Uses go-readline-ny key names (e.g., C_T, M_F, F1). Set to empty string to disable. The default is C_T (Ctrl+T).")) r.Register("CLI_STREAMING", StreamingModeVar(&sv.StreamingMode, "Controls streaming output mode: AUTO (format-dependent), TRUE (always stream), FALSE (never stream). Default is AUTO."))