[PATCH] Add nofirstword completion option
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 --- 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/b
[PATCH] Add shopt to enable writing history to syslog at runtime
Currently writing history to syslog can be enabled at compile time by editing config-top.h and rebuilding. To allow more flexibility, and to allow users of distributions to enable this feature at runtime without having to rebuild bash, add a "syslog" shopt. To maintain backward compatibility keep using SYSLOG_HISTORY as before to enable logging to syslog unconditionally. Signed-off-by: Luca Boccassi --- bashhist.c | 27 +++ builtins/shopt.def | 11 +++ doc/bash.0 | 3 +++ doc/bash.1 | 5 + doc/bash.html | 6 ++ doc/bash.info | 5 + doc/bashref.html | 6 ++ doc/bashref.info | 5 + doc/builtins.0 | 3 +++ 9 files changed, 67 insertions(+), 4 deletions(-) diff --git a/bashhist.c b/bashhist.c index 4cf0e4f9..2a5cf35a 100644 --- a/bashhist.c +++ b/bashhist.c @@ -38,7 +38,7 @@ #include "bashintl.h" -#if defined (SYSLOG_HISTORY) +#if defined (HAVE_SYSLOG) # include #endif @@ -773,12 +773,27 @@ check_add_history (line, force) return 0; } -#if defined (SYSLOG_HISTORY) +#if defined (HAVE_SYSLOG) #define SYSLOG_MAXLEN 600 #ifndef OPENLOG_OPTS +/* Backward compatibility: leave _OPTS to 0 if not defined in config-tops.h + with SYSLOG_HISTORY. */ +#ifdef SYSLOG_HISTORY #define OPENLOG_OPTS 0 +#else +#define OPENLOG_OPTS LOG_PID #endif +#endif + +#ifndef SYSLOG_FACILITY +#define SYSLOG_FACILITY LOG_USER +#endif +#ifndef SYSLOG_LEVEL +#define SYSLOG_LEVEL LOG_INFO +#endif + +int syslog_history_enabled = 0; void bash_syslog_history (line) @@ -882,8 +897,12 @@ bash_add_history (line) if (add_it) really_add_history (line); -#if defined (SYSLOG_HISTORY) - bash_syslog_history (line); +#if defined (HAVE_SYSLOG) +/* Backward compatibility: SYSLOG_HISTORY always enables syslog. */ +#if !defined (SYSLOG_HISTORY) + if (syslog_history_enabled) +#endif +bash_syslog_history (line); #endif using_history (); diff --git a/builtins/shopt.def b/builtins/shopt.def index 467dc534..8340353a 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -121,6 +121,10 @@ extern int assoc_expand_once; extern int array_expand_once; #endif +#if defined (HAVE_SYSLOG) +extern int syslog_history_enabled; +#endif + static void shopt_error __P((char *)); static int set_shellopts_after_change __P((char *, int)); @@ -236,6 +240,9 @@ static struct { { "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL }, { "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL }, { "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL }, +#if defined (HAVE_SYSLOG) + { "syslog", &syslog_history_enabled, (shopt_set_func_t *)NULL }, +#endif { (char *)0, (int *)0, (shopt_set_func_t *)NULL } }; @@ -381,6 +388,10 @@ reset_shopt_options () xpg_echo = 0; #endif /* DEFAULT_ECHO_TO_XPG */ +#if defined (HAVE_SYSLOG) + syslog_history_enabled = 0; +#endif + shopt_login_shell = login_shell; } diff --git a/doc/bash.0 b/doc/bash.0 index bb2f7429..afceb443 100644 --- a/doc/bash.0 +++ b/doc/bash.0 @@ -5741,6 +5741,9 @@ SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS If set, the ssoouurrccee (..) builtin uses the value of PPAATTHH to find the directory containing the file supplied as an argument. This option is enabled by default. + ssyysslloogg If set, the history will be sent to syslog with facility + LLOOGG__UUSSEERR and level LLOOGG__IINNFFOO. This option is disabled by + default. xxppgg__eecchhoo If set, the eecchhoo builtin expands backslash-escape sequences by default. diff --git a/doc/bash.1 b/doc/bash.1 index cf712fe3..f19432ff 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -10152,6 +10152,11 @@ If set, the to find the directory containing the file supplied as an argument. This option is enabled by default. .TP 8 +.B syslog +If set, the history will be sent to syslog with facility +\fBLOG_USER\fP and level \fBLOG_INFO\fP. +This option is disabled by default. +.TP 8 .B xpg_echo If set, the \fBecho\fP builtin expands backslash-escape sequences by default. diff --git a/doc/bash.html b/doc/bash.html index 54b42fec..574db317 100644 --- a/doc/bash.html +++ b/doc/bash.html @@ -12869,6 +12869,12 @@ If set, the to find the directory containing the file supplied as an argument. This option is enabled by default. +syslog + + +If set, the history will be sent to syslog with facility +LOG_USER and level LOG_INFO. +This option is disabled by default. xpg_echo diff --git a/doc/bash.info b/doc/bash.info index 9a4edb08..1cef4bfd 100644 --- a/doc/bash.info +++ b/doc/bash.info @@ -4667,6 +4667,11 @@ This builtin allows you to change additional shell optional behavior. the directory containing the file supplied as an argumen
Documentation error
> After the string is decoded, it is expanded via parameter expansion, command substitution, arithmetic expansion, and quote removal, subject to the value of the |promptvars| shell option (see _Bash Builtins_). The documentation should point to the *The Set Builtin*, which is the section that covers the shell options, not Bash Builtins.