From ab6bc413586319e6a7c7cdd4f575e894af111e19 Mon Sep 17 00:00:00 2001 From: Justin Frank Date: Wed, 26 Sep 2018 14:42:01 -0700 Subject: [PATCH] Added shell command completion support to define-command and prompt This commit also introduces a regression in that I decided that the best way to avoid overly long and confusing names was to rename the current shell-* switches to script-*, and have the shell command completion be shell-completion. renamed script-{completion,candidates} to shell-script-* Updated docs with new switch names Added -shell-completion switch to x11-repl and kitty-repl --- doc/pages/commands.asciidoc | 5 ++- rc/base/ctags.kak | 2 +- rc/core/doc.kak | 2 +- rc/core/kakrc.kak | 8 ++-- rc/core/man.kak | 4 +- rc/extra/git-tools.kak | 2 +- rc/extra/kitty.kak | 4 +- rc/extra/x11-repl.kak | 2 +- share/kak/kakrc | 2 +- src/commands.cc | 39 ++++++++++++------- .../rc | 2 +- 11 files changed, 43 insertions(+), 29 deletions(-) diff --git a/doc/pages/commands.asciidoc b/doc/pages/commands.asciidoc index a373ef72..b5ebefd0 100644 --- a/doc/pages/commands.asciidoc +++ b/doc/pages/commands.asciidoc @@ -291,6 +291,9 @@ New commands can be defined using the *define-command* command: try command completion on any parameter passed to this command *-shell-completion*::: + try shell command completion on any parameter passed to this command + +*-shell-script-completion*::: following string is a shell command which takes parameters as positional params and output one completion candidate per line. The provided shell command will run after each keypress @@ -305,7 +308,7 @@ New commands can be defined using the *define-command* command: Position of the cursor inside the token being completed, in bytes from token start. -*-shell-candidates*::: +*-shell-script-candidates*::: following string is a shell command which takes parameters as positional params and output one completion candidate per line. The provided shell command will run once at the beginning of each diff --git a/rc/base/ctags.kak b/rc/base/ctags.kak index 4e77e2a1..f15eee82 100644 --- a/rc/base/ctags.kak +++ b/rc/base/ctags.kak @@ -7,7 +7,7 @@ declare-option -docstring "list of paths to tag files to parse when looking up a str-list ctagsfiles 'tags' define-command -params ..1 \ - -shell-candidates %{ + -shell-script-candidates %{ realpath() { ( path=$(readlink "$1"); cd "$(dirname "$1")"; printf "%s/%s\n" "$(pwd -P)" "$(basename "$1")" ) } eval "set -- $kak_opt_ctagsfiles" for candidate in "$@"; do diff --git a/rc/core/doc.kak b/rc/core/doc.kak index d0f730e3..d616be7b 100644 --- a/rc/core/doc.kak +++ b/rc/core/doc.kak @@ -131,7 +131,7 @@ define-command -params 1 -hidden doc-render %{ } define-command -params 1..2 \ - -shell-candidates %{ + -shell-script-candidates %{ if [ "$kak_token_to_complete" -eq 0 ]; then find "${kak_runtime}/doc/" -type f -name "*.asciidoc" | sed 's,.*/,,; s/\.[^/]*$//' elif [ "$kak_token_to_complete" -eq 1 ]; then diff --git a/rc/core/kakrc.kak b/rc/core/kakrc.kak index 4130b954..dbdae865 100644 --- a/rc/core/kakrc.kak +++ b/rc/core/kakrc.kak @@ -20,10 +20,10 @@ add-highlighter shared/kakrc/shell1 region -recurse '\{' '(^|\h)\K%?%sh\{' '\}' add-highlighter shared/kakrc/shell2 region -recurse '\(' '(^|\h)\K%?%sh\(' '\)' ref sh add-highlighter shared/kakrc/shell3 region -recurse '\[' '(^|\h)\K%?%sh\[' '\]' ref sh add-highlighter shared/kakrc/shell4 region -recurse '<' '(^|\h)\K%?%sh<' '>' ref sh -add-highlighter shared/kakrc/shell5 region -recurse '\{' '(^|\h)\K-shell-(completion|candidates)\h+%\{' '\}' ref sh -add-highlighter shared/kakrc/shell6 region -recurse '\(' '(^|\h)\K-shell-(completion|candidates)\h+%\(' '\)' ref sh -add-highlighter shared/kakrc/shell7 region -recurse '\[' '(^|\h)\K-shell-(completion|candidates)\h+%\[' '\]' ref sh -add-highlighter shared/kakrc/shell8 region -recurse '<' '(^|\h)\K-shell-(completion|candidates)\h+%<' '>' ref sh +add-highlighter shared/kakrc/shell5 region -recurse '\{' '(^|\h)\K-script-(completion|candidates)\h+%\{' '\}' ref sh +add-highlighter shared/kakrc/shell6 region -recurse '\(' '(^|\h)\K-script-(completion|candidates)\h+%\(' '\)' ref sh +add-highlighter shared/kakrc/shell7 region -recurse '\[' '(^|\h)\K-script-(completion|candidates)\h+%\[' '\]' ref sh +add-highlighter shared/kakrc/shell8 region -recurse '<' '(^|\h)\K-script-(completion|candidates)\h+%<' '>' ref sh evaluate-commands %sh{ # Grammar diff --git a/rc/core/man.kak b/rc/core/man.kak index 7bcdf8ac..660f184c 100644 --- a/rc/core/man.kak +++ b/rc/core/man.kak @@ -51,8 +51,8 @@ define-command -hidden -params 2..3 man-impl %{ evaluate-commands %sh{ } } define-command -params ..1 \ - -shell-candidates %{ - find /usr/share/man/ -name '*.[1-8]*' | sed 's,^.*/\(.*\)\.\([1-8][a-zA-Z]*\).*$,\1(\2),' + -shell-script-candidates %{ + find /usr/share/man/ -name '*.[1-8]*' | sed 's,^.*/\(.*\)\.\([1-8][a-zA-Z]*\).*$,\1(\2),' } \ -docstring %{man []: manpage viewer wrapper If no argument is passed to the command, the selection will be used as page diff --git a/rc/extra/git-tools.kak b/rc/extra/git-tools.kak index 82d62f78..55d5cf53 100644 --- a/rc/extra/git-tools.kak +++ b/rc/extra/git-tools.kak @@ -27,7 +27,7 @@ define-command -params 1.. \ -docstring %sh{printf 'git []: git wrapping helper All the optional arguments are forwarded to the git utility Available commands:\n add\n rm\n blame\n commit\n checkout\n diff\n hide-blame\n hide-diff\n log\n show\n show-diff\n status\n update-diff'} \ - -shell-candidates %{ + -shell-script-candidates %{ if [ $kak_token_to_complete -eq 0 ]; then printf "add\nrm\nblame\ncommit\ncheckout\ndiff\nhide-blame\nhide-diff\nlog\nshow\nshow-diff\nstatus\nupdate-diff\n" else diff --git a/rc/extra/kitty.kak b/rc/extra/kitty.kak index 3365afe2..b7f6b755 100644 --- a/rc/extra/kitty.kak +++ b/rc/extra/kitty.kak @@ -43,9 +43,7 @@ If no client is passed then the current one is used} \ define-command -docstring %{kitty-repl []: create a new window for repl interaction All optional parameters are forwarded to the new window} \ -params .. \ - -shell-candidates %{ - find $(echo $PATH | tr ':' ' ') -mindepth 1 -maxdepth 1 -executable -printf "%f\n" - } \ + -shell-completion \ kitty-repl %{ evaluate-commands %sh{ if [ $# -eq 0 ]; then cmd="${SHELL:-/bin/sh}"; else cmd="$*"; fi kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type --title kak_repl_window $cmd < /dev/null > /dev/null 2>&1 & diff --git a/rc/extra/x11-repl.kak b/rc/extra/x11-repl.kak index 6ec8175e..865e2748 100644 --- a/rc/extra/x11-repl.kak +++ b/rc/extra/x11-repl.kak @@ -2,7 +2,7 @@ define-command -docstring %{x11-repl []: create a new window for repl interaction All optional parameters are forwarded to the new window} \ -params .. \ - -command-completion \ + -shell-completion \ x11-repl %{ evaluate-commands %sh{ if [ -z "${kak_opt_termcmd}" ]; then echo "echo -markup '{Error}termcmd option is not set'" diff --git a/share/kak/kakrc b/share/kak/kakrc index b6461ec1..cd70642b 100644 --- a/share/kak/kakrc +++ b/share/kak/kakrc @@ -1,5 +1,5 @@ def -params 1 -docstring "colorscheme : enable named colorscheme" \ - -shell-candidates %{ + -shell-script-candidates %{ find -L "${kak_runtime}/colors" "${kak_config}/colors" -type f -name '*\.kak' \ | while read -r filename; do basename="${filename##*/}" diff --git a/src/commands.cc b/src/commands.cc index d5290734..0e7ccf97 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -997,7 +997,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel return complete_buffer_name(context, flags, params[token_to_complete], pos_in_token); }; } - else if (auto shell_cmd_opt = parser.get_switch("shell-completion")) + else if (auto shell_cmd_opt = parser.get_switch("shell-script-completion")) { String shell_cmd = shell_cmd_opt->str(); completer = [=](const Context& context, CompletionFlags flags, @@ -1022,7 +1022,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel return Completions{ 0_byte, pos_in_token, std::move(candidates) }; }; } - else if (auto shell_cmd_opt = parser.get_switch("shell-candidates")) + else if (auto shell_cmd_opt = parser.get_switch("shell-script-candidates")) { String shell_cmd = shell_cmd_opt->str(); Vector, MemoryDomain::Completion> candidates; @@ -1082,6 +1082,15 @@ void define_command(const ParametersParser& parser, Context& context, const Shel context, flags, params, token_to_complete, pos_in_token); }; } + else if (parser.get_switch("shell-completion")) + { + completer = [](const Context& context, CompletionFlags flags, + CommandParameters params, + size_t token_to_complete, ByteCount pos_in_token) + { + return shell_complete(context, flags, params[token_to_complete], pos_in_token); + }; + } auto docstring = trim_whitespaces(parser.get_switch("docstring").value_or(StringView{})); @@ -1093,17 +1102,18 @@ const CommandDesc define_command_cmd = { "def", "define-command [] : define a command executing ", ParameterDesc{ - { { "params", { true, "take parameters, accessible to each shell escape as $0..$N\n" - "parameter should take the form or .. (both omittable)" } }, - { "override", { false, "allow overriding an existing command" } }, - { "hidden", { false, "do not display the command in completion candidates" } }, - { "docstring", { true, "define the documentation string for command" } }, - { "file-completion", { false, "complete parameters using filename completion" } }, - { "client-completion", { false, "complete parameters using client name completion" } }, - { "buffer-completion", { false, "complete parameters using buffer name completion" } }, - { "command-completion", { false, "complete parameters using kakoune command completion" } }, - { "shell-completion", { true, "complete parameters using the given shell-script" } }, - { "shell-candidates", { true, "get the parameter candidates using the given shell-script" } } }, + { { "params", { true, "take parameters, accessible to each shell escape as $0..$N\n" + "parameter should take the form or .. (both omittable)" } }, + { "override", { false, "allow overriding an existing command" } }, + { "hidden", { false, "do not display the command in completion candidates" } }, + { "docstring", { true, "define the documentation string for command" } }, + { "file-completion", { false, "complete parameters using filename completion" } }, + { "client-completion", { false, "complete parameters using client name completion" } }, + { "buffer-completion", { false, "complete parameters using buffer name completion" } }, + { "command-completion", { false, "complete parameters using kakoune command completion" } }, + { "shell-completion", { false, "complete parameters using shell command completion" } }, + { "shell-script-completion", { true, "complete parameters using the given shell-script" } }, + { "shell-script-candidates", { true, "get the parameter candidates using the given shell-script" } } }, ParameterDesc::Flags::None, 2, 2 }, @@ -1828,6 +1838,7 @@ const CommandDesc prompt_cmd = { { "client-completion", { false, "use client completion for prompt" } }, { "buffer-completion", { false, "use buffer completion for prompt" } }, { "command-completion", { false, "use command completion for prompt" } }, + { "shell-completion", { false, "use shell command completion for prompt" } }, { "on-change", { true, "command to execute whenever the prompt changes" } }, { "on-abort", { true, "command to execute whenever the prompt is canceled" } } }, ParameterDesc::Flags::None, 2, 2 @@ -1863,6 +1874,8 @@ const CommandDesc prompt_cmd = { return CommandManager::instance().complete( context, flags, prefix, cursor_pos); }; + else if (parser.get_switch("shell-completion")) + completer = shell_complete; const auto flags = parser.get_switch("password") ? PromptFlags::Password : PromptFlags::None; diff --git a/test/regression/0-nothing-selected-on-prompt-initial-shift-tab/rc b/test/regression/0-nothing-selected-on-prompt-initial-shift-tab/rc index fa7913e2..53ad0d14 100644 --- a/test/regression/0-nothing-selected-on-prompt-initial-shift-tab/rc +++ b/test/regression/0-nothing-selected-on-prompt-initial-shift-tab/rc @@ -1 +1 @@ -def my-command -params 0..1 -shell-candidates %{ printf "aaa\nbbb\nccc" } %{ exec i %arg{1} } +def my-command -params 0..1 -shell-script-candidates %{ printf "aaa\nbbb\nccc" } %{ exec i %arg{1} }