From 95f2d8e38a23c0232d27654e4c37a88a01d3e10d Mon Sep 17 00:00:00 2001 From: Jack Wright Date: Sun, 27 Nov 2022 15:06:59 -0800 Subject: [PATCH] Added a whitelist to add cobra apps to to prevent non-cobra apps from being excuted --- completions.go | 14 +++++- nushell_completions.go | 104 ++++++++++++++++++++++------------------- shell_completions.md | 14 +++++- 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/completions.go b/completions.go index 509c7960..5e6e80d4 100644 --- a/completions.go +++ b/completions.go @@ -809,7 +809,7 @@ to your powershell profile. Short: fmt.Sprintf(shortDesc, "nushell"), Long: fmt.Sprintf(`Generate the autocompletion script for nushell. -To configure completions: +To configure the Nushell cobra external configurator for the first time: # 1. Copy the output of the command below: > %[1]s completion nushell @@ -822,7 +822,17 @@ To configure completions: # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell for this setup to take effect. + # 5. You will need to start a new shell or for this setup to take effect. + +If you have already setup the cobra external configurator: + + # 1. Edit the nushell config file: + > config nu + + # 2. Modify the cobra_apps varible to contain this application: + > let cobra_apps = [ "othercobraapp", "%[1]s" ] + + # 3. You will need to start a new shell or for this setup to take effect. `, c.Root().Name()), Args: NoArgs, diff --git a/nushell_completions.go b/nushell_completions.go index 3b4e2c67..568d3cb5 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -24,64 +24,72 @@ import ( func (c *Command) GenNushellCompletion(w io.Writer) error { buf := new(bytes.Buffer) WriteStringAndCheck(buf, fmt.Sprintf(` + +# A list of cobra that completion will be attempted for. +# Add new apps to this list to enable completion for them. +let cobra_apps = ["%[1]s"] + # An external configurator that works with any cobra based # command line application (e.g. kubectl, minikube) let cobra_completer = {|spans| - - let ShellCompDirectiveError = %[1]d - let ShellCompDirectiveNoSpace = %[2]d - let ShellCompDirectiveNoFileComp = %[3]d - let ShellCompDirectiveFilterFileExt = %[4]d - let ShellCompDirectiveFilterDirs = %[5]d - let cmd = $spans.0 - let last_span = ($spans | last | str trim) - # skip the first entry in the span (the command) and join the rest of the span to create __complete args - let cmd_args = ($spans | skip 1 | str join ' ') + if not ($cobra_apps | where $it == $cmd | is-empty) { + let ShellCompDirectiveError = %[2]d + let ShellCompDirectiveNoSpace = %[3]d + let ShellCompDirectiveNoFileComp = %[4]d + let ShellCompDirectiveFilterFileExt = %[5]d + let ShellCompDirectiveFilterDirs = %[6]d + + let last_span = ($spans | last | str trim) - # If the last span entry was empty add "" to the end of the command args - let cmd_args = if ($last_span | is-empty) { - $'($cmd_args) ""' + # skip the first entry in the span (the command) and join the rest of the span to create __complete args + let cmd_args = ($spans | skip 1 | str join ' ') + + # If the last span entry was empty add "" to the end of the command args + let cmd_args = if ($last_span | is-empty) { + $'($cmd_args) ""' + } else { + $cmd_args + } + + # The full command to be executed with active help disable (Nushell does not support active help) + let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' + + # Since nushell doesn't have anything like eval, execute in a subshell + let result = (do -i { nu -c $"'($full_cmd)'" } | complete) + + # Create a record with all completion related info. + # directive and directive_str are for posterity + let stdout_lines = ($result.stdout | lines) + let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) + let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) + + # Add space at the end of each completion + let completions = if $directive != $ShellCompDirectiveNoSpace { + ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) + } else { + $completions + } + + if $last_span =~ '=$' { + # return flag as part of the completion so that it doesn't get replaced + $completions | each {|it| $"($last_span)($it.value)" } + } else if $directive == $ShellCompDirectiveNoFileComp { + # Allow empty results as this will stop file completion + $completions + } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { + # Not returning null causes file completions to break + # Return null if there are no completions or ShellCompDirectiveError + null + } else { + $completions + } } else { - $cmd_args - } - - # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'($cmd)_ACTIVE_HELP=0 ($cmd) __complete ($cmd_args)' - - # Since nushell doesn't have anything like eval, execute in a subshell - let result = (do -i { nu -c $"'($full_cmd)'" } | complete) - - # Create a record with all completion related info. - # directive and directive_str are for posterity - let stdout_lines = ($result.stdout | lines) - let directive = ($stdout_lines | last | str trim | str replace ":" "" | into int) - let completions = ($stdout_lines | drop | parse -r '([\w\-\.:\+\=]*)\t?(.*)' | rename value description) - - # Add space at the end of each completion - let completions = if $directive != $ShellCompDirectiveNoSpace { - ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) - } else { - $completions - } - - if $last_span =~ '=$' { - # return flag as part of the completion so that it doesn't get replaced - $completions | each {|it| $"($last_span)($it.value)" } - } else if $directive == $ShellCompDirectiveNoFileComp { - # Allow empty results as this will stop file completion - $completions - } else if ($completions | is-empty) or $directive == $ShellCompDirectiveError { - # Not returning null causes file completions to break - # Return null if there are no completions or ShellCompDirectiveError null - } else { - $completions } - } -`, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, +`, c.Name(), ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) diff --git a/shell_completions.md b/shell_completions.md index 6672578b..89198cc4 100644 --- a/shell_completions.md +++ b/shell_completions.md @@ -72,6 +72,8 @@ PowerShell: Nushell: + # To configure the Nushell cobra external configurator for the first time: + # 1. Copy the output of the command below: > %[1]s completion nushell @@ -83,7 +85,17 @@ Nushell: # 4. Change the config block's external_completer line to be external_completer: $cobra_completer - # 5. You will need to start a new shell for this setup to take effect. + # 5. You will need to start a new shell or for this setup to take effect. + + # If you have already setup the cobra external configurator: + + # 1. Edit the nushell config file: + > config nu + + # 2. Modify the cobra_apps varible to contain this application: + > let cobra_apps = [ "othercobraapp", "%[1]s" ] + + # 3. You will need to start a new shell for this setup to take effect. `,cmd.Root().Name()), DisableFlagsInUseLine: true,