From 4401df6e4c85e6d8f1086c7c9209bc9facbe5d18 Mon Sep 17 00:00:00 2001 From: rsteube Date: Sat, 13 Jan 2024 14:10:35 +0100 Subject: [PATCH] added join --- cmd/carapace-shlex/cmd/root.go | 29 ++++++++++++++++++++++------- shlex.go | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/cmd/carapace-shlex/cmd/root.go b/cmd/carapace-shlex/cmd/root.go index 5319092..26a974f 100644 --- a/cmd/carapace-shlex/cmd/root.go +++ b/cmd/carapace-shlex/cmd/root.go @@ -11,7 +11,7 @@ import ( ) var rootCmd = &cobra.Command{ - Use: "carapace-spec", + Use: "carapace-shlex", Long: "simple shell lexer", CompletionOptions: cobra.CompletionOptions{ DisableDefaultCmd: true, @@ -32,15 +32,24 @@ var rootCmd = &cobra.Command{ if cmd.Flag("words").Changed { tokens = tokens.Words() } - if cmd.Flag("prefix").Changed { + + switch { + case cmd.Flag("prefix").Changed: fmt.Fprintln(cmd.OutOrStdout(), tokens.WordbreakPrefix()) return nil + case cmd.Flag("join").Changed: + words := make([]string, 0) + for _, word := range tokens.Words() { + words = append(words, word.Value) + } + fmt.Fprintln(cmd.OutOrStdout(), shlex.Join(words)) + return nil + default: + encoder := json.NewEncoder(cmd.OutOrStdout()) + encoder.SetEscapeHTML(false) + encoder.SetIndent("", " ") + return encoder.Encode(tokens) } - - encoder := json.NewEncoder(cmd.OutOrStdout()) - encoder.SetEscapeHTML(false) - encoder.SetIndent("", " ") - return encoder.Encode(tokens) }, } @@ -53,6 +62,12 @@ func init() { rootCmd.Flags().Bool("current", false, "show current pipeline") rootCmd.Flags().Bool("prefix", false, "show wordbreak prefix") rootCmd.Flags().Bool("words", false, "show words") + rootCmd.Flags().Bool("join", false, "re-join words") + + rootCmd.MarkFlagsMutuallyExclusive( + "join", + "prefix", + ) carapace.Gen(rootCmd).PositionalCompletion( bridge.ActionCarapaceBin().SplitP(), diff --git a/shlex.go b/shlex.go index caedbfc..79c4d63 100644 --- a/shlex.go +++ b/shlex.go @@ -417,3 +417,25 @@ func Split(s string) (TokenSlice, error) { tokens = append(tokens, *token) } } + +// Join concatenates words to create a single string. +// It quotes and escapes where appropriate. +// TODO experimental +func Join(s []string) string { + replacer := strings.NewReplacer( + "$", "\\$", + "`", "\\`", + ) + + formatted := make([]string, 0, len(s)) + for _, arg := range s { + switch { + case arg == "", + strings.ContainsAny(arg, `"' `+"\n\r\t"): + formatted = append(formatted, replacer.Replace(fmt.Sprintf("%#v", arg))) + default: + formatted = append(formatted, arg) + } + } + return strings.Join(formatted, " ") +}