From 8b4766028aaed37b598c59599715e85a1a4d4217 Mon Sep 17 00:00:00 2001 From: TorchedSammy <38820196+TorchedSammy@users.noreply.github.com> Date: Wed, 30 Nov 2022 19:03:45 -0400 Subject: [PATCH] feat: add an opt for case insensitive completion --- complete.go | 53 ++++++++++++++++++++++++------------- docs/completions.txt | 4 +-- nature/completions.lua | 4 +-- nature/opts/init.lua | 3 ++- nature/opts/insensitive.lua | 1 + 5 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 nature/opts/insensitive.lua diff --git a/complete.go b/complete.go index df20f72..0458a27 100644 --- a/complete.go +++ b/complete.go @@ -72,13 +72,13 @@ func splitForFile(str string) []string { return split } -func fileComplete(query, ctx string, fields []string) ([]string, string) { +func fileComplete(query, ctx string, fields []string, caseInsensitive bool) ([]string, string) { q := splitForFile(ctx) - return matchPath(q[len(q) - 1]) + return matchPath(q[len(q) - 1], caseInsensitive) } -func binaryComplete(query, ctx string, fields []string) ([]string, string) { +func binaryComplete(query, ctx string, fields []string, caseInsensitive bool) ([]string, string) { q := splitForFile(ctx) query = q[len(q) - 1] @@ -87,7 +87,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) { prefixes := []string{"./", "../", "/", "~/"} for _, prefix := range prefixes { if strings.HasPrefix(query, prefix) { - fileCompletions, filePref := matchPath(query) + fileCompletions, filePref := matchPath(query, caseInsensitive) if len(fileCompletions) != 0 { for _, f := range fileCompletions { fullPath, _ := filepath.Abs(util.ExpandHome(query + strings.TrimPrefix(f, filePref))) @@ -132,7 +132,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) { return completions, query } -func matchPath(query string) ([]string, string) { +func matchPath(query string, caseInsensitive bool) ([]string, string) { oldQuery := query query = strings.TrimPrefix(query, "\"") var entries []string @@ -148,9 +148,17 @@ func matchPath(query string) ([]string, string) { baseName = filepath.Base(query) } + if caseInsensitive { + baseName = strings.ToLower(baseName) + } + files, _ := os.ReadDir(path) for _, file := range files { - if strings.HasPrefix(strings.ToLower(file.Name()), strings.ToLower(baseName)) { + fname := file.Name() + if caseInsensitive { + fname = strings.ToLower(fname) + } + if strings.HasPrefix(fname, baseName) { entry := file.Name() if file.IsDir() { entry = entry + string(os.PathSeparator) @@ -174,8 +182,8 @@ func escapeFilename(fname string) string { func completionLoader(rtm *rt.Runtime) *rt.Table { exports := map[string]util.LuaExport{ - "files": {luaFileComplete, 3, false}, - "bins": {luaBinaryComplete, 3, false}, + "files": {luaFileComplete, 3, true}, + "bins": {luaBinaryComplete, 3, true}, "call": {callLuaCompleter, 4, false}, "handler": {completionHandler, 2, false}, } @@ -231,12 +239,12 @@ func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { } func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - query, ctx, fds, err := getCompleteParams(t, c) + query, ctx, fds, insensitive, err := getCompleteParams(t, c) if err != nil { return nil, err } - completions, pfx := fileComplete(query, ctx, fds) + completions, pfx := fileComplete(query, ctx, fds, insensitive) luaComps := rt.NewTable() for i, comp := range completions { @@ -247,12 +255,12 @@ func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { } func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - query, ctx, fds, err := getCompleteParams(t, c) + query, ctx, fds, insensitive, err := getCompleteParams(t, c) if err != nil { return nil, err } - completions, pfx := binaryComplete(query, ctx, fds) + completions, pfx := binaryComplete(query, ctx, fds, insensitive) luaComps := rt.NewTable() for i, comp := range completions { @@ -262,21 +270,30 @@ func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil } -func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) { +func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, bool, error) { if err := c.CheckNArgs(3); err != nil { - return "", "", []string{}, err + return "", "", []string{}, false, err } query, err := c.StringArg(0) if err != nil { - return "", "", []string{}, err + return "", "", []string{}, false, err } ctx, err := c.StringArg(1) if err != nil { - return "", "", []string{}, err + return "", "", []string{}, false, err } fields, err := c.TableArg(2) if err != nil { - return "", "", []string{}, err + return "", "", []string{}, false, err + } + var insensitive bool + if len(c.Etc()) != 0 { + typ := c.Etc()[0] + var ok bool + insensitive, ok = typ.TryBool() + if !ok { + return "", "", []string{}, false, errors.New("bad argument #4 (expected bool, got " + typ.TypeName() + ")") + } } var fds []string @@ -286,5 +303,5 @@ func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, er } }) - return query, ctx, fds, err + return query, ctx, fds, insensitive, err } diff --git a/docs/completions.txt b/docs/completions.txt index 1354dc0..8b0b3ed 100644 --- a/docs/completions.txt +++ b/docs/completions.txt @@ -36,9 +36,9 @@ then there is the `files` function, which is mentioned below. # Completion Interface ## Functions -- `files(query, ctx, fields)` -> table, prefix: get file completions, based +- `files(query, ctx, fields, caseInsensitive)` -> table, prefix: get file completions, based on the user's query. -- `bins(query, ctx, fields)` -> table, prefix: get binary/executable +- `bins(query, ctx, fields, caseInsensitive)` -> table, prefix: get binary/executable completions, based on user query. - `call(scope, query, ctx, fields)` -> table, prefix: call a completion handler with `scope`, usually being in the form of `command.` diff --git a/nature/completions.lua b/nature/completions.lua index d20cc59..fc08261 100644 --- a/nature/completions.lua +++ b/nature/completions.lua @@ -15,7 +15,7 @@ function hilbish.completion.handler(line, pos) local query = fields[#fields] if #fields == 1 then - local comps, pfx = hilbish.completion.bins(query, ctx, fields) + local comps, pfx = hilbish.completion.bins(query, ctx, fields, hilbish.opts.insensitive) local compGroup = { items = comps, type = 'grid' @@ -29,7 +29,7 @@ function hilbish.completion.handler(line, pos) return compGroups, pfx end - local comps, pfx = hilbish.completion.files(query, ctx, fields) + local comps, pfx = hilbish.completion.files(query, ctx, fields, hilbish.opts.insensitive) local compGroup = { items = comps, type = 'grid' diff --git a/nature/opts/init.lua b/nature/opts/init.lua index ae95ee1..fa6ba9c 100644 --- a/nature/opts/init.lua +++ b/nature/opts/init.lua @@ -25,7 +25,8 @@ local defaultOpts = { greeting = string.format([[Welcome to {magenta}Hilbish{reset}, {cyan}%s{reset}. The nice lil shell for {blue}Lua{reset} fanatics! ]], hilbish.user), - motd = true + motd = true, + insensitive = true } for optsName, default in pairs(defaultOpts) do diff --git a/nature/opts/insensitive.lua b/nature/opts/insensitive.lua new file mode 100644 index 0000000..1fcd659 --- /dev/null +++ b/nature/opts/insensitive.lua @@ -0,0 +1 @@ +-- noop