From f47c691a764e978bd28d42c778c1b046dd281f08 Mon Sep 17 00:00:00 2001 From: rsteube Date: Mon, 31 Jul 2023 18:58:36 +0200 Subject: [PATCH] nushell: use lexer to patch arguments --- complete.go | 5 +++++ internal/shell/nushell/action.go | 12 +++++++++++- internal/shell/nushell/patch.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 internal/shell/nushell/patch.go diff --git a/complete.go b/complete.go index 26060cb7..75eed927 100644 --- a/complete.go +++ b/complete.go @@ -2,6 +2,7 @@ package carapace import ( "github.com/rsteube/carapace/internal/config" + "github.com/rsteube/carapace/internal/shell/nushell" "github.com/rsteube/carapace/pkg/ps" "github.com/spf13/cobra" ) @@ -14,6 +15,10 @@ func complete(cmd *cobra.Command, args []string) (string, error) { return Gen(cmd).Snippet(args[0]) default: initHelpCompletion(cmd) + + if shell := ps.DetermineShell(); shell == "nushell" { + args = nushell.Patch(args) + } action, context := traverse(cmd, args[2:]) if err := config.Load(); err != nil { action = ActionMessage("failed to load config: " + err.Error()) diff --git a/internal/shell/nushell/action.go b/internal/shell/nushell/action.go index 361393bd..e1e026ab 100644 --- a/internal/shell/nushell/action.go +++ b/internal/shell/nushell/action.go @@ -18,6 +18,11 @@ var sanitizer = strings.NewReplacer( "\r", ``, ) +var escaper = strings.NewReplacer( + `\`, `\\`, + `"`, `\"`, +) + func sanitize(values []common.RawValue) []common.RawValue { for index, v := range values { (&values[index]).Value = sanitizer.Replace(v.Value) @@ -32,7 +37,12 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu vals := make([]record, len(values)) for index, val := range sanitize(values) { if strings.ContainsAny(val.Value, ` {}()[]<>$&"|;#\`+"`") { - val.Value = fmt.Sprintf("'%v'", val.Value) + switch { + case strings.HasPrefix(val.Value, "~"): + val.Value = fmt.Sprintf(`~"%v"`, escaper.Replace(val.Value[1:])) + default: + val.Value = fmt.Sprintf(`"%v"`, escaper.Replace(val.Value)) + } } if !meta.Nospace.Matches(val.Value) { diff --git a/internal/shell/nushell/patch.go b/internal/shell/nushell/patch.go new file mode 100644 index 00000000..185e1cfb --- /dev/null +++ b/internal/shell/nushell/patch.go @@ -0,0 +1,29 @@ +package nushell + +import ( + "strings" + + "github.com/rsteube/carapace/internal/lexer" +) + +// Patch uses the lexer to parse and patch given arguments which +// are currently passed unprocessed to the completion function. +// +// see https://www.nushell.sh/book/working_with_strings.html +func Patch(args []string) []string { + for index, arg := range args { + if len(arg) == 0 { + continue + } + + switch arg[0] { + case '"', "'"[0]: + if tokenset, err := lexer.Split(arg, false); err == nil { + args[index] = tokenset.Tokens[0] + } + case '`': + args[index] = strings.Trim(arg, "`") + } + } + return args +}