scop / bash-completion

Programmable completion functions for bash
GNU General Public License v2.0
2.95k stars 380 forks source link

allow completion files for, e.g., units #1242

Open greg-minshall opened 2 months ago

greg-minshall commented 2 months ago

Describe the feature/solution

there is code in bash_completion that binds completion for some commands to _comp_complete_longopt, which means, unless sourced explicitly into bash, a completion file for any of these commands won't be used.

the request is to somehow allow such commands to have a completion file, which would then take over from _comp_complete_longopt for that command.

Maintenance (please complete the following information)

i'm not sure of the protocol. but, i have a patch that seems to allow this functionality.

other than possibly being wrong, a downside of the patch is that it will have any command in this set commands always go through _comp_load (presumably somewhat expensive) before calling _comp_complete_longopt. if the patch is accepted, that could probably be short-circuited.

no

no

greg-minshall commented 2 months ago

i apologize, but i can't figure out how to attach the patch (its extension is ".patch", and the error message says they allow a "PATCH" file, bug ...). here it is inline, but let me know if are interested in seeing it in some different form.

From d7644e821d4f94b3766a93b5370bbc5461c35531 Mon Sep 17 00:00:00 2001
From: Greg Minshall <minshall@umich.edu>
Date: Fri, 30 Aug 2024 16:20:50 +0300
Subject: [PATCH] bash_completion: run comp_load *before* comp_complete_longopt

in order to allow a certain set of commands (bound to
comp_complete_longopt in the code) to possibly have a completion file
added.

previously, completion for this set of commands was handled by
`_comp_complete_longopt`.  (these are commands that provide output for
`--help` that can be munged to produce completions when starting from
one or two hyphens on the "command line so far".)

with this patch, `_comp_load` is first called and, if it fails to find
a completion file for the active command, and the active command is in
the set, it calls `_comp_complete_longopt`.

there is a downside of this patch: for a command in this set that
does *not* have a completion file, `_comp_load` will be called each
time completion is requested for the command.  it should be possible
to do a `complete -F _comp_complete_longopt <CMD>` in this case.
---
 bash_completion | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/bash_completion b/bash_completion
index bf42e008..17a93b65 100644
--- a/bash_completion
+++ b/bash_completion
@@ -2990,8 +2990,17 @@ _comp_complete_longopt()
         _comp_compgen -a filedir
     fi
 }
-# makeinfo and texi2dvi are defined elsewhere.
-complete -F _comp_complete_longopt \
+
+declare -Ag _comp_longopts
+
+_comp__init_install_longopt()
+{
+    for cmd in "$@"; do
+        _comp_longopts[$cmd]="set"
+    done
+}
+
+_comp__init_install_longopt \
     a2ps awk base64 bash bc bison cat chroot colordiff cp \
     csplit cut date df diff dir du enscript expand fmt fold gperf \
     grep grub head irb ld ldd less ln ls m4 mkdir mkfifo mknod \
@@ -3249,8 +3258,9 @@ _comp_load()
     # Look up simple "xspec" completions
     [[ -v _comp_xspecs[$cmdname] || -v _xspecs[$cmdname] ]] &&
         complete -F _comp_complete_filedir_xspec "$cmdname" "$backslash$cmdname" && return 0
-
-    if [[ $flag_fallback_default ]]; then
+    if [[ -v _comp_longopts[$cmdname] || -v _longopts[$cmdname] ]]; then
+        _comp_complete_longopt $cmdname
+    elif [[ $flag_fallback_default ]]; then
         complete -F _comp_complete_minimal -- "$origcmd" && return 0
     fi

-- 
2.46.0
greg-minshall commented 2 months ago

sorry, two things. the affected commands are

    a2ps awk base64 bash bc bison cat chroot colordiff cp
    csplit cut date df diff dir du enscript expand fmt fold gperf 
    grep grub head irb ld ldd less ln ls m4 mkdir mkfifo mknod
    mv netstat nl nm objcopy objdump od paste pr ptx readelf rm rmdir
    sed seq shar sort split strip sum tac tail tee
    texindex touch tr uname unexpand uniq units vdir wc who

and, the following diff (to the result of the above patch) might solve the performance issue i worried about.

diff --git a/bash_completion b/bash_completion
index 17a93b65..6b98ce0c 100644
--- a/bash_completion
+++ b/bash_completion
@@ -3259,7 +3259,8 @@ _comp_load()
     [[ -v _comp_xspecs[$cmdname] || -v _xspecs[$cmdname] ]] &&
         complete -F _comp_complete_filedir_xspec "$cmdname" "$backslash$cmdname" && return 0
     if [[ -v _comp_longopts[$cmdname] || -v _longopts[$cmdname] ]]; then
-        _comp_complete_longopt $cmdname
+        _comp_complete_longopt "$cmdname"
+        complete -F _comp_complete_longopt "$cmdname"
     elif [[ $flag_fallback_default ]]; then
         complete -F _comp_complete_minimal -- "$origcmd" && return 0
     fi

(also fixes a shellcheck warning.)

scop commented 1 week ago

Sorry about the long delay. The idea in principle sounds good to me.

Could you file this as a pull request so we can review and eventually merge it using the usual process?