From 15823e76b938fc3cfb94005d4ae3e1842e65f838 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Thu, 9 Nov 2023 15:45:42 -0500 Subject: [PATCH] Print ActiveHelp for bash along other completions In the bash shell we used to print ActiveHelp messages on every tab-press. In the example below, notice the "Command help" line which is ActiveHelp: bash-5.1$ tanzu context u[tab] Command help: Configure and manage contexts for the Tanzu CLI bash-5.1$ tanzu context u[tab] Command help: Configure and manage contexts for the Tanzu CLI bash-5.1$ tanzu context u unset (Unset the active context so that it is not used by default.) use (Set the context to be used by default) bash-5.1$ tanzu context u Above, on the first [tab] press, only the ActiveHelp is printed. On the second [tab] press, the ActiveHelp is printed again, followed by a re-print of the command-line, followed by the completions choices. The separation between ActiveHelp and completion choices makes the ActiveHelp harder to see. Furthermore, I find the double printing of the ActiveHelp string to look bad. Note that for zsh, the UX is different and that ActiveHelp messages are printed at the same time as the completion choices. This commit aligns the UX for ActiveHelp in bash with the one for zsh: if there are other completions to be shown, the ActiveHelp messages are printed at the same time. New behaviour: 1- ActiveHelp is no longer printed on the first [tab] press. This is better aligned with bash's standard approach. 2- ActiveHelp is printed on the second [tab] press, above the completion choices, with a `--` delimiter. 3- If there are no completion choices, the `--` delimiter is omitted. This behaviour is the same as what is done for zsh (except that for zsh the first [tab] press immediately shows completion choices). Below is the above example, but using this commit. Notice the more concise and easier to read completion output: bash-5.1$ tanzu context u[tab][tab] Command help: Configure and manage contexts for the Tanzu CLI -- unset (Unset the active context so that it is not used by default.) use (Set the context to be used by default) bash-5.1$ tanzu context u Signed-off-by: Marc Khouzam --- bash_completionsV2.go | 66 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/bash_completionsV2.go b/bash_completionsV2.go index 1cce5c32..9035b6fe 100644 --- a/bash_completionsV2.go +++ b/bash_completionsV2.go @@ -177,23 +177,65 @@ __%[1]s_process_completion_results() { __%[1]s_handle_special_char "$cur" = # Print the activeHelp statements before we finish - if ((${#activeHelp[*]} != 0)); then - printf "\n"; - printf "%%s\n" "${activeHelp[@]}" - printf "\n" + __%[1]s_handle_activeHelp +} - # The prompt format is only available from bash 4.4. - # We test if it is available before using it. - if (x=${PS1@P}) 2> /dev/null; then - printf "%%s" "${PS1@P}${COMP_LINE[@]}" - else - # Can't print the prompt. Just print the - # text the user had typed, it is workable enough. - printf "%%s" "${COMP_LINE[@]}" +__%[1]s_handle_activeHelp() { + # Print the activeHelp statements + if ((${#activeHelp[*]} != 0)); then + # Only print ActiveHelp on the second TAB press + if [ $COMP_TYPE -eq 63 ]; then + printf "\n" + printf "%%s\n" "${activeHelp[@]}" + + if ((${#COMPREPLY[*]} == 0)); then + # When there are no completion choices from the program, file completion + # may kick in if the program has not disabled it; in such a case, we want + # to know if any files will match what the user typed, so that we know if + # there will be completions presented, so that we know how to handle ActiveHelp. + # To find out, we actually trigger the file completion ourselves; + # the call to _filedir will fill COMPREPLY if files match. + if (((directive & shellCompDirectiveNoFileComp) == 0)); then + __%[1]s_debug "Listing files" + _filedir + fi + fi + + if ((${#COMPREPLY[*]} != 0)); then + # If there are completion choices to be shown, print a delimiter. + # Re-printing the command-line will automatically be done + # by the shell when it prints the completion choices. + printf -- "--" + else + # When there are no completion choices at all, we need + # to re-print the command-line since the shell will + # not be doing it itself. + __%[1]s_reprint_commandLine + fi + elif [ $COMP_TYPE -eq 37 ] || [ $COMP_TYPE -eq 42 ]; then + # For completion type: menu-complete/menu-complete-backward and insert-completions + # the completions are immediately inserted into the command-line, so we first + # print the activeHelp message and reprint the command-line since the shell won't. + printf "\n" + printf "%%s\n" "${activeHelp[@]}" + + __%[1]s_reprint_commandLine fi fi } +__%[1]s_reprint_commandLine() { + # The prompt format is only available from bash 4.4. + # We test if it is available before using it. + if (x=${PS1@P}) 2> /dev/null; then + printf "%%s" "${PS1@P}${COMP_LINE[@]}" + else + # Can't print the prompt. Just print the + # text the user had typed, it is workable enough. + printf "%%s" "${COMP_LINE[@]}" + fi +} + # Separate activeHelp lines from real completions. # Fills the $activeHelp and $completions arrays. __%[1]s_extract_activeHelp() {