diff --git a/nushell_completions.go b/nushell_completions.go index 87c34a73..8f7c8568 100644 --- a/nushell_completions.go +++ b/nushell_completions.go @@ -31,7 +31,7 @@ let cobra_apps = ["%[1]s"] # An external completer that works with any cobra based # command line application (e.g. kubectl, minikube) -let cobra_completer = {|spans| +let-env cobra_completer = {|spans| let cmd = $spans.0 if not ($cobra_apps | where $cmd =~ $it | is-empty) { @@ -43,44 +43,96 @@ let cobra_completer = {|spans| 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 ' ') + def exec_complete [ + --fuzzy, + spans: list + ] { + let params = { + last_span: ($spans | last | str trim), + spans: $spans + } + + # If there is an equals in the last span + # parse the span into two + let params = if $last_span =~ '=' { + let split = ($last_span | split row '=') + if ($split | length) > 1 { + { + last_span: ($split | last), + spans: ($spans | drop | append ($split | first) | append ($split | last)) + } + } else { + { + last_span: '', + spans: ($spans | drop | append ($split | first) | append '') + } + } + } else { + $params + } - # 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 + let last_span = $params.last_span + let spans = $params.spans + + # Drop the last param so we can fuzzy search on it + let spans = if $fuzzy { + $spans | drop + } else { + $spans + } + + # 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) or $fuzzy { + $'($cmd_args) ""' + } else { + $cmd_args + } + + # The full command to be executed with active help disable (Nushell does not support active help) + let full_cmd = $'COBRA_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) + let completions = if $fuzzy { + $completions | where $it.value =~ $last_span + + } else { + ($completions | where {|it| $it.value | str starts-with $last_span }) + } + + { + directive: $directive, + completions: $completions + } } - # The full command to be executed with active help disable (Nushell does not support active help) - let full_cmd = $'%[7]s=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) - - # filter completions that don't contain the last span, for fuzzy searches - let filtered = ($completions | where $it.value =~ $last_span) - let completions = if not ($filtered | is-empty) { - $filtered + let result = (exec_complete $spans) + let result = if (not ($last_span | is-empty)) and ($result.completions | is-empty) { + exec_complete --fuzzy $spans } else { - $completions + $result } + let directive = $result.directive + let completions = $result.completions + # Add space at the end of each completion let completions = if $directive != $ShellCompDirectiveNoSpace { - ($completions | each {|it| {value: $"($it.value) ", description: $it.description}}) + $completions | each {|it| {value: $"($it.value) ", description: $it.description}} } else { $completions } - if $last_span =~ '=' { + let return_val = if $last_span =~ '=' { # if the completion is of the form -n= return flag as part of the completion so that it doesn't get replaced $completions | each {|it| $"($last_span | split row '=' | first)=($it.value)" } } else if $directive == $ShellCompDirectiveNoFileComp { @@ -93,12 +145,20 @@ let cobra_completer = {|spans| } else { $completions } + + $return_val } else { null } } + + + + + + `, name, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs)) _, err := buf.WriteTo(w) return err