bug-bash
[Top][All Lists]
Advanced

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

[PATCH] Add nofirstword completion option


From: Luca Boccassi
Subject: [PATCH] Add nofirstword completion option
Date: Fri, 18 May 2018 12:06:11 +0100

Network operating systems traditionally have provided a command
line interface with "operation mode" and "configuration mode", with
different auto-completion behaviour - specifically, with a small set
of supported commands that are printed using the auto-completion
shortcut key, depending on the mode.
In order to be able to implement such modes using Bash, Linux and Free
Software, it's necessary to be able to optionally disable
auto-completion on the first word, so that the relevant help text
(depending on the mode) can be printed on the console instead.
Add and document a nofirstword completion option to implement this
feature.

Signed-off-by: Luca Boccassi <bluca@debian.org>
---
 bashline.c            | 47 +++++++++++++++++++++++++++++++++++++++--------
 builtins/complete.def |  4 ++++
 doc/bash.1            |  4 ++++
 doc/bash.html         |  5 +++++
 doc/bash.info         |  5 +++++
 doc/bashref.html      |  5 +++++
 doc/bashref.info      |  5 +++++
 pcomplete.h           |  1 +
 8 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/bashline.c b/bashline.c
index ae8fe1cc..436bf8d3 100644
--- a/bashline.c
+++ b/bashline.c
@@ -1313,8 +1313,9 @@ static int
 find_cmd_start (start)
      int start;
 {
-  register int s, os, ns;
+  register int s, os, ns, last;
 
+  last = 0;
   os = 0;
   /* Flags == SD_NOJMP only because we want to skip over command substitutions
      in assignment statements.  Have to test whether this affects `standalone'
@@ -1332,7 +1333,13 @@ find_cmd_start (start)
          continue;
        }
       os = s+1;
+      last = s;
     }
+  /* If the last seperator is a pipe keep it at the beginning of the command. 
The
+     pipe character is a command seperator and a command. */
+  if (rl_line_buffer[last] == '|')
+    os = last;
+
   return os;
 }
 
@@ -1352,13 +1359,18 @@ find_cmd_name (start, sp, ep)
      int *sp, *ep;
 {
   char *name;
-  register int s, e;
+  register int s, s1, e;
 
   for (s = start; whitespace (rl_line_buffer[s]); s++)
     ;
 
+  /* If first character is a pipe char scan from next char */
+  s1 = s;
+  if (rl_line_buffer[s] == '|')
+    ++s1;
+
   /* skip until a shell break character */
-  e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP|SD_COMPLETE);
+  e = skip_to_delim (rl_line_buffer, s1, "()<>;&| \t\n", SD_NOJMP|SD_COMPLETE);
 
   name = substring (rl_line_buffer, s, e);
 
@@ -1425,6 +1437,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 +1497,11 @@ 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(DEFAULTCMD);
+  if (cs && cs->options & COPT_NOFIRSTWORD)
+    in_command_position = 0;
+#endif /* PROGRAMMABLE_COMPLETION */
 
   if (in_command_position && invalid_completion (text, ti))
     {
@@ -1571,12 +1589,20 @@ attempt_shell_completion (text, start, end)
        {
          /* not assignment statement, but still want to perform command
             completion if we are composing command word. */
-         foundcs = 0;
-         in_command_position = s == start && STREQ (n, text);  /* XXX */
+         if (cs && cs->options & COPT_NOFIRSTWORD)
+           prog_complete_matches = programmable_completions (EMPTYCMD, text, 
s, e, &foundcs);
+         else
+           {
+             foundcs = 0;
+             in_command_position = s == start && STREQ (n, text);      /* XXX 
*/
+           }
        }
       else if (e > s && was_assignment == 0 && have_progcomps)
        {
-         prog_complete_matches = programmable_completions (n, text, s, e, 
&foundcs);
+          if (n[0] == '|' && cs && cs->options & COPT_NOFIRSTWORD)
+            prog_complete_matches = programmable_completions (EMPTYCMD, text, 
s, e, &foundcs);
+          else
+            prog_complete_matches = programmable_completions (n, text, s, e, 
&foundcs);
          /* command completion if programmable completion fails */
          in_command_position = s == start && STREQ (n, text);  /* XXX */
        }
@@ -1584,8 +1610,13 @@ attempt_shell_completion (text, start, end)
       else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0 &&
                was_assignment == 0 && member (rl_line_buffer[start-1], 
COMMAND_SEPARATORS))
        {
-         foundcs = 0;
-         in_command_position = 1;
+          if (cs && cs->options & COPT_NOFIRSTWORD)
+            prog_complete_matches = programmable_completions (EMPTYCMD, text, 
s, e, &foundcs);
+          else
+            {
+             foundcs = 0;      /* empty command name following assignments */
+              in_command_position = was_assignment;
+            }
        }
       else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
         {
diff --git a/builtins/complete.def b/builtins/complete.def
index 3ca8c1fa..9830fb3b 100644
--- a/builtins/complete.def
+++ b/builtins/complete.def
@@ -137,6 +137,7 @@ static const struct _compopt {
   { "default", COPT_DEFAULT },
   { "dirnames", COPT_DIRNAMES },
   { "filenames",COPT_FILENAMES},
+  { "nofirstword", COPT_NOFIRSTWORD },
   { "noquote", COPT_NOQUOTE },
   { "nosort", COPT_NOSORT },
   { "nospace", COPT_NOSPACE },
@@ -515,6 +516,7 @@ print_one_completion (cmd, cs)
   PRINTCOMPOPT (COPT_DEFAULT, "default");
   PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
   PRINTCOMPOPT (COPT_FILENAMES, "filenames");
+  PRINTCOMPOPT (COPT_NOFIRSTWORD, "nofirstword");
   PRINTCOMPOPT (COPT_NOQUOTE, "noquote");
   PRINTCOMPOPT (COPT_NOSORT, "nosort");
   PRINTCOMPOPT (COPT_NOSPACE, "nospace");
@@ -591,6 +593,7 @@ print_compopts (cmd, cs, full)
       XPRINTCOMPOPT (COPT_DEFAULT, "default");
       XPRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
       XPRINTCOMPOPT (COPT_FILENAMES, "filenames");
+      XPRINTCOMPOPT (COPT_NOFIRSTWORD, "nofirstword");
       XPRINTCOMPOPT (COPT_NOQUOTE, "noquote");
       XPRINTCOMPOPT (COPT_NOSORT, "nosort");
       XPRINTCOMPOPT (COPT_NOSPACE, "nospace");
@@ -602,6 +605,7 @@ print_compopts (cmd, cs, full)
       PRINTCOMPOPT (COPT_DEFAULT, "default");
       PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
       PRINTCOMPOPT (COPT_FILENAMES, "filenames");
+      PRINTCOMPOPT (COPT_NOFIRSTWORD, "nofirstword");
       PRINTCOMPOPT (COPT_NOQUOTE, "noquote");
       PRINTCOMPOPT (COPT_NOSORT, "nosort");
       PRINTCOMPOPT (COPT_NOSPACE, "nospace");
diff --git a/doc/bash.1 b/doc/bash.1
index f19432ff..89ac1607 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -7696,6 +7696,10 @@ filename\-specific processing (like adding a slash to 
directory names,
 quoting special characters, or suppressing trailing spaces).
 Intended to be used with shell functions.
 .TP 8
+.B nofirstword
+Disable autocompletion on the first word. Useful when it is necessary to
+implement a "configuration mode", for example in networking operating systems.
+.TP 8
 .B noquote
 Tell readline not to quote the completed words if they are filenames
 (quoting filenames is the default).
diff --git a/doc/bash.html b/doc/bash.html
index 574db317..acaac109 100644
--- a/doc/bash.html
+++ b/doc/bash.html
@@ -9806,6 +9806,11 @@ Tell readline that the compspec generates filenames, so 
it can perform any
 filename-specific processing (like adding a slash to directory names,
 quoting special characters, or suppressing trailing spaces).
 Intended to be used with shell functions.
+<DT><B>nofirstword</B>
+
+<DD>
+Disable autocompletion on the first word. Useful when it is necessary
+to implement a "configuration mode", for example in networking operating 
systems.
 <DT><B>noquote</B>
 
 <DD>
diff --git a/doc/bash.info b/doc/bash.info
index 1cef4bfd..5e5f161d 100644
--- a/doc/bash.info
+++ b/doc/bash.info
@@ -8793,6 +8793,11 @@ happening.
                is intended to be used with shell functions specified
                with '-F'.
 
+          'nofirstword'
+               Disable autocompletion on the first word. Useful when it
+               is necessary to implement a "configuration mode", for
+               example in networking operating systems.
+
           'noquote'
                Tell Readline not to quote the completed words if they
                are filenames (quoting filenames is the default).
diff --git a/doc/bashref.html b/doc/bashref.html
index f64fbf21..7f8e3039 100644
--- a/doc/bashref.html
+++ b/doc/bashref.html
@@ -12039,6 +12039,11 @@ This option is intended to be used with shell 
functions specified
 with <samp>-F</samp>.
 </p>
 </dd>
+<dt><code>nofirstword</code></dt>
+<dd><p>Disable autocompletion on the first word. Useful when it is necessary
+to implement a "configuration mode", for example in networking operating 
systems.
+</p>
+</dd>
 <dt><code>noquote</code></dt>
 <dd><p>Tell Readline not to quote the completed words if they are filenames
 (quoting filenames is the default).
diff --git a/doc/bashref.info b/doc/bashref.info
index c2ccaa58..d5675a66 100644
--- a/doc/bashref.info
+++ b/doc/bashref.info
@@ -8793,6 +8793,11 @@ happening.
                is intended to be used with shell functions specified
                with '-F'.
 
+          'nofirstword'
+               Disable autocompletion on the first word. Useful when it
+               is necessary to implement a "configuration mode", for
+               example in networking operating systems.
+
           'noquote'
                Tell Readline not to quote the completed words if they
                are filenames (quoting filenames is the default).
diff --git a/pcomplete.h b/pcomplete.h
index 2ae8224e..62c4e83e 100644
--- a/pcomplete.h
+++ b/pcomplete.h
@@ -76,6 +76,7 @@ typedef struct compspec {
 #define COPT_BASHDEFAULT (1<<6)
 #define COPT_PLUSDIRS  (1<<7)
 #define COPT_NOSORT    (1<<8)
+#define COPT_NOFIRSTWORD (1<<9)
 
 #define COPT_LASTUSER  COPT_NOSORT
 
-- 
2.14.2




reply via email to

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