Currently, there isn't any way to request quoting of completion matches without getting also the attendant filename treatment.
In practice, authors of completion functions that need the matches to be quoted often use `-o filenames', which works fine unless the matches include slashes or happen to match existing directory names. Alternatively, some authors opt to do their own quoting of matches but doing so properly for partial word completion is tricky as it requires accounting for the quoting style chosen by the user when they typed the partial word. The attached patch hopefully addresses these difficulties by allowing for the decoupling of filename-specific match handling from match quoting. It adds a new completion option `allquote' (I'm not quite happy with the name) which controls the corresponding new readline variable rl_all_quoting_desired.
From 8049e9f920fde4f84422fd651ba4a4beeafb7f10 Mon Sep 17 00:00:00 2001 From: Grisha Levit <grishale...@gmail.com> Date: Fri, 14 Apr 2023 16:10:22 -0400 Subject: [PATCH] allow quoting completions w/o filename treatment lib/readline/complete.c - rl_all_quoting_desired: new variable to tell readline to quote matches even if not doing filename completion - QUOTING_DESIRED: new macro for checking if quoting is enabled - change checks of filename comoletion && filename quoting to use QUOTING_DESIRED. - set_completion_defaults: set rl_all_quoting_desired to 0 lib/readline/readline.h - rl_all_quoting_desired: extern declaration lib/readline/doc/rltech.texi - document rl_all_quoting_desired pcomplete.h - COPT_ALLQUOTE: new value for compspec option, corresponds to rl_all_quoting_desired pcomplete.c - pcomp_set_readline_variables: handle COPT_ALLQUOTE builtins/complete.def - compopts: add allquote option for COPT_ALLQUOTE lib/readline/doc/rluser.texi - document allquote compopt --- builtins/complete.def | 1 + lib/readline/complete.c | 26 +++++++++++++------------- lib/readline/doc/rltech.texi | 7 +++++++ lib/readline/doc/rluser.texi | 3 +++ lib/readline/readline.h | 6 ++++++ pcomplete.c | 2 ++ pcomplete.h | 3 ++- 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/builtins/complete.def b/builtins/complete.def index 881c4711..89ce0726 100644 --- a/builtins/complete.def +++ b/builtins/complete.def @@ -141,6 +141,7 @@ static const struct _compopt { const char * const optname; unsigned long optflag; } compopts[] = { + { "allquote", COPT_ALLQUOTE }, { "bashdefault", COPT_BASHDEFAULT }, { "default", COPT_DEFAULT }, { "dirnames", COPT_DIRNAMES }, diff --git a/lib/readline/complete.c b/lib/readline/complete.c index bf7cc856..3cf050fc 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -336,6 +336,14 @@ int rl_filename_completion_desired = 0; entry finder function. */ int rl_filename_quoting_desired = 1; +/* Non-zero means that we should apply filename quoting to the matches + even if we are not otherwise treating the matches as filenames. This + is ALWAYS zero on entry, and can only be changed within a completion + entry finder function. */ +int rl_all_quoting_desired = 0; + +#define QUOTING_DESIRED (rl_all_quoting_desired || (rl_filename_completion_desired && rl_filename_quoting_desired)) + /* This function, if defined, is called by the completer when real filename completion is done, after all the matching names have been generated. It is passed a (char**) known as matches in the code below. @@ -510,7 +518,7 @@ static void set_completion_defaults (int what_to_do) { /* Only the completion entry function can change these. */ - rl_filename_completion_desired = 0; + rl_filename_completion_desired = rl_all_quoting_desired = 0; rl_filename_quoting_desired = 1; rl_completion_type = what_to_do; rl_completion_suppress_append = rl_completion_suppress_quote = 0; @@ -1408,10 +1416,7 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text) check against the list of matches FI */ dtext = (char *)NULL; - if (rl_filename_completion_desired && - rl_filename_dequoting_function && - rl_completion_found_quote && - rl_filename_quoting_desired) + if (QUOTING_DESIRED && rl_completion_found_quote && rl_filename_dequoting_function) { dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); text = dtext; @@ -1766,10 +1771,7 @@ make_quoted_replacement (char *match, int mtype, char *qc) matches don't require a quoted substring. */ replacement = match; - should_quote = match && rl_completer_quote_characters && - rl_filename_completion_desired && - rl_filename_quoting_desired; - + should_quote = match && rl_completer_quote_characters && QUOTING_DESIRED; if (should_quote) should_quote = should_quote && (!qc || !*qc || (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); @@ -1980,8 +1982,7 @@ compare_match (char *text, const char *match) char *temp; int r; - if (rl_filename_completion_desired && rl_filename_quoting_desired && - rl_completion_found_quote && rl_filename_dequoting_function) + if (QUOTING_DESIRED && rl_completion_found_quote && rl_filename_dequoting_function) { temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); r = strcmp (temp, match); @@ -2043,8 +2044,7 @@ rl_complete_internal (int what_to_do) strcmp directly. */ /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ - if (rl_filename_completion_desired && rl_filename_quoting_desired && - rl_completion_found_quote && rl_filename_dequoting_function) + if (QUOTING_DESIRED && rl_completion_found_quote && rl_filename_dequoting_function) { char *t; t = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi index db38a311..df76f6f9 100644 --- a/lib/readline/doc/rltech.texi +++ b/lib/readline/doc/rltech.texi @@ -2300,6 +2300,13 @@ The quoting is effected via a call to the function pointed to by @code{rl_filename_quoting_function}. @end deftypevar +@deftypevar int rl_all_quoting_desired +Non-zero means that we should apply filename quoting to the matches +even if we are not otherwise treating the matches as filenames. This +is @emph{always} zero on entry, and can only be changed within a completion +entry finder function. +@end deftypevar + @deftypevar int rl_attempted_completion_over If an application-specific completion function assigned to @code{rl_attempted_completion_function} sets this variable to a non-zero diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index bb1a24f5..a9a702d5 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -2177,6 +2177,9 @@ beyond the simple generation of completions. @table @code +@item allquote +Tell readline to quote the completed words even if they are not filenames. + @item bashdefault Perform the rest of the default Bash completions if the compspec generates no matches. diff --git a/lib/readline/readline.h b/lib/readline/readline.h index 48f1210a..4a0c3d1d 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -790,6 +790,12 @@ extern int rl_filename_completion_desired; entry finder function. */ extern int rl_filename_quoting_desired; +/* Non-zero means that we should apply filename quoting to the matches + even if we are not otherwise treating the matches as filenames. This + is ALWAYS zero on entry, and can only be changed within a completion + entry finder function. */ +extern int rl_all_quoting_desired; + /* Set to a function to quote a filename in an application-specific fashion. Called with the text to quote, the type of match found (single or multiple) and a pointer to the quoting character to be used, which the function can diff --git a/pcomplete.c b/pcomplete.c index 553623d5..1d99c317 100644 --- a/pcomplete.c +++ b/pcomplete.c @@ -1486,6 +1486,8 @@ pcomp_set_readline_variables (int flags, int nval) rl_filename_quoting_desired = 1 - nval; if (flags & COPT_NOSORT) rl_sort_completion_matches = 1 - nval; + if (flags & COPT_ALLQUOTE) + rl_all_quoting_desired = nval; } /* Set or unset FLAGS in the options word of the current compspec. diff --git a/pcomplete.h b/pcomplete.h index f0821b19..076c2eb7 100644 --- a/pcomplete.h +++ b/pcomplete.h @@ -76,8 +76,9 @@ typedef struct compspec { #define COPT_BASHDEFAULT (1<<6) #define COPT_PLUSDIRS (1<<7) #define COPT_NOSORT (1<<8) +#define COPT_ALLQUOTE (1<<9) -#define COPT_LASTUSER COPT_NOSORT +#define COPT_LASTUSER COPT_ALLQUOTE #define PCOMP_RETRYFAIL (COPT_LASTUSER << 1) #define PCOMP_NOTFOUND (COPT_LASTUSER << 2) -- 2.40.0