bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add nofirstword completion option


From: Luca Boccassi
Subject: Re: [PATCH] Add nofirstword completion option
Date: Fri, 25 May 2018 18:42:47 +0100

On Wed, 2018-05-23 at 09:53 -0400, Chet Ramey wrote:
> On 5/23/18 9:34 AM, Luca Boccassi wrote:
> > On Wed, 2018-05-23 at 09:15 -0400, Chet Ramey wrote:
> > > On 5/23/18 5:44 AM, Luca Boccassi wrote:
> > > 
> > > > So by that, do you mean that it's possible to stop
> > > > autocompleting
> > > > to
> > > > files/dirs/binaries just using a programmable completion
> > > > script? Or
> > > > did
> > > > I misunderstand? Apologies if that's the case.
> > > > 
> > > > Right now we do have completion scripts to implement the help
> > > > text
> > > > for
> > > > the commands (and for the empty set, which displays a general
> > > > help
> > > > with
> > > > a summary), what's missing is stopping files/dirs/binaries
> > > > completion
> > > > for the first word, so that exclusively the commands are shown.
> > > 
> > > Exactly. What you want, I gather, is a way to restrict
> > > completions on
> > > the
> > > command word to the small set of router commands valid in
> > > whichever
> > > mode
> > > the console happens to be. Programmable completion provides a
> > > mechanism to
> > > do that, but there is a missing piece of functionality that would
> > > allow it
> > > to work on the command word. That's the change I would prefer to
> > > see.
> > > 
> > > Chet
> > 
> > Ah I see - I am more than happy to work on that instead, but
> > (forgive
> > my n00bness, first time hacking on Bash) could you please describe
> > in a
> > couple of lines what the missing piece is and what it should look
> > like?
> 
> There is already logic that determines whether the shell is trying to
> complete a command word (in_command_position). The existing code does
> not attempt programmable completion if in_command_position == 1. The
> additional functionality would:
> 
> 1. Add an option to the complete builtin to specify how to complete
>    command names, and store it in a specially-named compspec, like
>    completion for empty lines does.
> 
> 2. Add code to invoke that completion, if it exists and programmable
>    completion is active, before attempting bash's default completion,
>    if in_command_position == 1.
> 
> Chet

Hi,

Thanks for the guidance! Unfortunately I'm still not quite there yet -
inlined are the changes based on my understanding of the above. It
implements a "usercmd/-U" option similar to the existing -E for empty
line.

But at the moment all it does is to allow (via "complete -U -F foo") to
complete when nothing is typed in, which seemed to be possible already
with -E. If some characters are already typed in, it will still do the
default completion to commands in the PATH.

What have I missed?

Thank you for the help!

-- 
Kind regards,
Luca Boccassi

diff --git a/bashline.c b/bashline.c
index ae8fe1cc..9dfe3283 100644
--- a/bashline.c
+++ b/bashline.c
@@ -1425,6 +1425,7 @@ attempt_shell_completion (text, start, end)
   int in_command_position, ti, qc, dflags;
   char **matches, *command_separator_chars;
 #if defined (PROGRAMMABLE_COMPLETION)
+  COMPSPEC *cs;
   int have_progcomps, was_assignment;
 #endif
 
@@ -1484,6 +1485,9 @@ attempt_shell_completion (text, start, end)
         that all of the previous words on the line are variable
         assignments. */
     }
+#if defined (PROGRAMMABLE_COMPLETION)
+  cs = progcomp_search(USERCMD);
+#endif /* PROGRAMMABLE_COMPLETION */
 
   if (in_command_position && invalid_completion (text, ti))
     {
@@ -1599,6 +1603,8 @@ attempt_shell_completion (text, start, end)
         }
       else
        foundcs = 0;
+      if (cs && in_command_position == 1)
+        prog_complete_matches = programmable_completions (USERCMD, text, s, e, 
&foundcs);
       FREE (n);
       /* XXX - if we found a COMPSPEC for the command, just return whatever
         the programmable completion code returns, and disable the default
diff --git a/builtins/complete.def b/builtins/complete.def
index 3ca8c1fa..60f7b17a 100644
--- a/builtins/complete.def
+++ b/builtins/complete.def
@@ -23,7 +23,7 @@ $PRODUCES complete.c
 $BUILTIN complete
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION complete_builtin
-$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G 
globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] 
[-S suffix] [name ...]
+$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-DEU] [-o option] [-A action] [-G 
globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] 
[-S suffix] [name ...]
 Specify how arguments are to be completed by Readline.
 
 For each NAME, specify how arguments are to be completed.  If no options
@@ -38,10 +38,12 @@ Options:
                without any specific completion defined
   -E   apply the completions and actions to "empty" commands --
                completion attempted on a blank line
+  -U   apply the completions and actions to "user" commands --
+               completion attempted on a command name
 
 When completion is attempted, the actions are applied in the order the
 uppercase-letter options are listed above.  The -D option takes
-precedence over -E.
+precedence over -E which takes precedence over -U.
 
 Exit Status:
 Returns success unless an invalid option is supplied or an error occurs.
@@ -79,6 +81,7 @@ struct _optflags {
   int rflag;
   int Dflag;
   int Eflag;
+  int Uflag;
 };
 
 static int find_compact __P((char *));
@@ -195,7 +198,7 @@ build_actions (list, flagp, actp, optp)
   opt_given = 0;
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DE")) 
!= -1)
+  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEU")) 
!= -1)
     {
       opt_given = 1;
       switch (opt)
@@ -319,6 +322,18 @@ build_actions (list, flagp, actp, optp)
        case 'S':
          Sarg = list_optarg;
          break;
+       case 'U':
+         if (flagp)
+           {
+             flagp->Uflag = 1;
+             break;
+           }
+         else
+           {
+             sh_invalidopt ("-U");
+             builtin_usage ();
+             return (EX_USAGE);
+           }
        case 'W':
          Warg = list_optarg;
          break;
@@ -355,7 +370,7 @@ complete_builtin (list)
       return (EXECUTION_SUCCESS);
     }
 
-  opt_given = oflags.pflag = oflags.rflag = oflags.Dflag = oflags.Eflag = 0;
+  opt_given = oflags.pflag = oflags.rflag = oflags.Dflag = oflags.Eflag = 
oflags.Uflag = 0;
 
   acts = copts = (unsigned long)0L;
   Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
@@ -371,7 +386,8 @@ complete_builtin (list)
   list = loptend;
 
   wl = oflags.Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST 
*)NULL)
-                   : (oflags.Eflag ? make_word_list (make_bare_word 
(EMPTYCMD), (WORD_LIST *)NULL) : 0);
+                   : (oflags.Eflag ? make_word_list (make_bare_word 
(EMPTYCMD), (WORD_LIST *)NULL)
+                       : (oflags.Uflag ? make_word_list (make_bare_word 
(USERCMD), (WORD_LIST *)NULL) : 0));
 
   /* -p overrides everything else */
   if (oflags.pflag || (list == 0 && opt_given == 0))
@@ -568,6 +584,8 @@ print_one_completion (cmd, cs)
     printf ("-E\n");
   else if (STREQ (cmd, DEFAULTCMD))
     printf ("-D\n");
+  else if (STREQ (cmd, USERCMD))
+    printf ("-U\n");
   else
     printf ("%s\n", cmd);
 
@@ -612,6 +630,8 @@ print_compopts (cmd, cs, full)
     printf ("-E\n");
   else if (STREQ (cmd, DEFAULTCMD))
     printf ("-D\n");
+  else if (STREQ (cmd, USERCMD))
+    printf ("-U\n");
   else
     printf ("%s\n", cmd);
 }
@@ -769,7 +789,7 @@ compgen_builtin (list)
 $BUILTIN compopt
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION compopt_builtin
-$SHORT_DOC compopt [-o|+o option] [-DE] [name ...]
+$SHORT_DOC compopt [-o|+o option] [-DEU] [name ...]
 Modify or display completion options.
 
 Modify the completion options for each NAME, or, if no NAMEs are supplied,
@@ -780,6 +800,7 @@ Options:
        -o option       Set completion option OPTION for each NAME
        -D              Change options for the "default" command completion
        -E              Change options for the "empty" command completion
+       -U              Change options for the "user" command completion
 
 Using `+o' instead of `-o' turns off the specified option.
 
@@ -800,15 +821,15 @@ int
 compopt_builtin (list)
      WORD_LIST *list;
 {
-  int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag;
+  int opts_on, opts_off, *opts, opt, oind, ret, Dflag, Eflag, Uflag;
   WORD_LIST *l, *wl;
   COMPSPEC *cs;
 
-  opts_on = opts_off = Eflag = Dflag = 0;
+  opts_on = opts_off = Eflag = Dflag = Uflag = 0;
   ret = EXECUTION_SUCCESS;
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "+o:DE")) != -1)
+  while ((opt = internal_getopt (list, "+o:DEU")) != -1)
     {
       opts = (list_opttype == '-') ? &opts_on : &opts_off;
 
@@ -829,6 +850,9 @@ compopt_builtin (list)
        case 'E':
          Eflag = 1;
          break;
+       case 'U':
+         Uflag = 1;
+         break;
        CASE_HELPOPT;
        default:
          builtin_usage ();
@@ -838,7 +862,8 @@ compopt_builtin (list)
   list = loptend;
 
   wl = Dflag ? make_word_list (make_bare_word (DEFAULTCMD), (WORD_LIST *)NULL)
-            : (Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST 
*)NULL) : 0);
+            : (Eflag ? make_word_list (make_bare_word (EMPTYCMD), (WORD_LIST 
*)NULL)
+               : (Uflag ? make_word_list (make_bare_word (USERCMD), (WORD_LIST 
*)NULL) : 0));
 
   if (list == 0 && wl == 0)
     {
diff --git a/pcomplete.h b/pcomplete.h
index 2ae8224e..005b38e8 100644
--- a/pcomplete.h
+++ b/pcomplete.h
@@ -107,6 +107,7 @@ typedef struct _list_of_items {
 
 #define EMPTYCMD       "_EmptycmD_"
 #define DEFAULTCMD     "_DefaultCmD_"
+#define USERCMD        "_UserCmD_"
 
 extern HASH_TABLE *prog_completes;
 
-- 
2.14.2

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]