Bash-4.2 direxpand shopt variable and associated changes, including heuristics to avoid quoting shell variables during word completion

This commit is contained in:
Chet Ramey
2011-11-23 17:58:51 -05:00
parent 42a5896e24
commit b3203139c0
6 changed files with 156 additions and 12 deletions
+110 -11
View File
@@ -121,6 +121,9 @@ static int bash_directory_completion_hook __P((char **));
static int filename_completion_ignore __P((char **));
static int bash_push_line __P((void));
static rl_icppfunc_t *save_directory_hook __P((void));
static void reset_directory_hook __P((rl_icppfunc_t *));
static void cleanup_expansion_error __P((void));
static void maybe_make_readline_line __P((char *));
static void set_up_new_line __P((char *));
@@ -243,10 +246,16 @@ int force_fignore = 1;
/* Perform spelling correction on directory names during word completion */
int dircomplete_spelling = 0;
/* Expand directory names during word/filename completion. */
int dircomplete_expand = 0;
static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
/* )) */
static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
static char *custom_filename_quote_characters = 0;
static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
static int dot_in_path = 0;
@@ -501,7 +510,7 @@ initialize_readline ()
/* Tell the completer that we might want to follow symbolic links or
do other expansion on directory names. */
rl_directory_rewrite_hook = bash_directory_completion_hook;
set_directory_hook ();
rl_filename_rewrite_hook = bash_filename_rewrite_hook;
@@ -529,7 +538,7 @@ initialize_readline ()
enable_hostname_completion (perform_hostname_completion);
/* characters that need to be quoted when appearing in filenames. */
rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
rl_filename_quote_characters = default_filename_quote_characters;
rl_filename_quoting_function = bash_quote_filename;
rl_filename_dequoting_function = bash_dequote_filename;
@@ -564,8 +573,10 @@ bashline_reset ()
tilde_initialize ();
rl_attempted_completion_function = attempt_shell_completion;
rl_completion_entry_function = NULL;
rl_directory_rewrite_hook = bash_directory_completion_hook;
rl_ignore_some_completions_function = filename_completion_ignore;
rl_filename_quote_characters = default_filename_quote_characters;
set_directory_hook ();
}
/* Contains the line to push into readline. */
@@ -1279,6 +1290,9 @@ attempt_shell_completion (text, start, end)
matches = (char **)NULL;
rl_ignore_some_completions_function = filename_completion_ignore;
rl_filename_quote_characters = default_filename_quote_characters;
set_directory_hook ();
/* Determine if this could be a command word. It is if it appears at
the start of the line (ignoring preceding whitespace), or if it
appears after a character that separates commands. It cannot be a
@@ -1591,6 +1605,12 @@ command_word_completion_function (hint_text, state)
}
else
{
if (dircomplete_expand && dot_or_dotdot (filename_hint))
{
dircomplete_expand = 0;
set_directory_hook ();
dircomplete_expand = 1;
}
mapping_over = 4;
goto inner;
}
@@ -1791,6 +1811,9 @@ globword:
inner:
val = rl_filename_completion_function (filename_hint, istate);
if (mapping_over == 4 && dircomplete_expand)
set_directory_hook ();
istate = 1;
if (val == 0)
@@ -2693,6 +2716,52 @@ bash_filename_rewrite_hook (fname, fnlen)
return conv;
}
/* Functions to save and restore the appropriate directory hook */
/* This is not static so the shopt code can call it */
void
set_directory_hook ()
{
if (dircomplete_expand)
{
rl_directory_completion_hook = bash_directory_completion_hook;
rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
}
else
{
rl_directory_rewrite_hook = bash_directory_completion_hook;
rl_directory_completion_hook = (rl_icppfunc_t *)0;
}
}
static rl_icppfunc_t *
save_directory_hook ()
{
rl_icppfunc_t *ret;
if (dircomplete_expand)
{
ret = rl_directory_completion_hook;
rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
}
else
{
ret = rl_directory_rewrite_hook;
rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
}
return ret;
}
static void
restore_directory_hook (hookf)
rl_icppfunc_t *hookf;
{
if (dircomplete_expand)
rl_directory_completion_hook = hookf;
else
rl_directory_rewrite_hook = hookf;
}
/* Handle symbolic link references and other directory name
expansions while hacking completion. This should return 1 if it modifies
the DIRNAME argument, 0 otherwise. It should make sure not to modify
@@ -2702,20 +2771,31 @@ bash_directory_completion_hook (dirname)
char **dirname;
{
char *local_dirname, *new_dirname, *t;
int return_value, should_expand_dirname;
int return_value, should_expand_dirname, nextch, closer;
WORD_LIST *wl;
struct stat sb;
return_value = should_expand_dirname = 0;
return_value = should_expand_dirname = nextch = closer = 0;
local_dirname = *dirname;
if (mbschr (local_dirname, '$'))
should_expand_dirname = 1;
if (t = mbschr (local_dirname, '$'))
{
should_expand_dirname = '$';
nextch = t[1];
/* Deliberately does not handle the deprecated $[...] arithmetic
expansion syntax */
if (nextch == '(')
closer = ')';
else if (nextch == '{')
closer = '}';
else
nextch = 0;
}
else
{
t = mbschr (local_dirname, '`');
if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
should_expand_dirname = 1;
should_expand_dirname = '`';
}
#if defined (HAVE_LSTAT)
@@ -2739,6 +2819,23 @@ bash_directory_completion_hook (dirname)
free (new_dirname);
dispose_words (wl);
local_dirname = *dirname;
/* XXX - change rl_filename_quote_characters here based on
should_expand_dirname/nextch/closer. This is the only place
custom_filename_quote_characters is modified. */
if (rl_filename_quote_characters && *rl_filename_quote_characters)
{
int i, j, c;
i = strlen (default_filename_quote_characters);
custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
for (i = j = 0; c = default_filename_quote_characters[i]; i++)
{
if (c == should_expand_dirname || c == nextch || c == closer)
continue;
custom_filename_quote_characters[j++] = c;
}
custom_filename_quote_characters[j] = '\0';
rl_filename_quote_characters = custom_filename_quote_characters;
}
}
else
{
@@ -3002,12 +3099,13 @@ bash_complete_filename_internal (what_to_do)
orig_func = rl_completion_entry_function;
orig_attempt_func = rl_attempted_completion_function;
orig_dir_func = rl_directory_rewrite_hook;
orig_ignore_func = rl_ignore_some_completions_function;
orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
orig_dir_func = save_directory_hook ();
rl_completion_entry_function = rl_filename_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
rl_ignore_some_completions_function = filename_completion_ignore;
rl_completer_word_break_characters = " \t\n\"\'";
@@ -3015,10 +3113,11 @@ bash_complete_filename_internal (what_to_do)
rl_completion_entry_function = orig_func;
rl_attempted_completion_function = orig_attempt_func;
rl_directory_rewrite_hook = orig_dir_func;
rl_ignore_some_completions_function = orig_ignore_func;
rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
restore_directory_hook (orig_dir_func);
return r;
}
+5
View File
@@ -33,10 +33,15 @@ extern void bashline_reset __P((void));
extern void bashline_reinitialize __P((void));
extern int bash_re_edit __P((char *));
extern void bashline_set_event_hook __P((void));
extern void bashline_reset_event_hook __P((void));
extern int bind_keyseq_to_unix_command __P((char *));
extern char **bash_default_completion __P((const char *, int, int, int, int));
void set_directory_hook __P((void));
/* Used by programmable completion code. */
extern char *command_word_completion_function __P((const char *, int));
extern char *bash_groupname_completion_function __P((const char *, int));
+21 -1
View File
@@ -61,6 +61,10 @@ $END
#include "common.h"
#include "bashgetopt.h"
#if defined (READLINE)
# include "../bashline.h"
#endif
#if defined (HISTORY)
# include "../bashhist.h"
#endif
@@ -94,7 +98,7 @@ extern int extended_glob;
extern int hist_verify, history_reediting, perform_hostname_completion;
extern int no_empty_command_completion;
extern int force_fignore;
extern int dircomplete_spelling;
extern int dircomplete_spelling, dircomplete_expand;
extern int enable_hostname_completion __P((int));
#endif
@@ -121,6 +125,10 @@ static int set_compatibility_level __P((char *, int));
static int set_restricted_shell __P((char *, int));
#endif
#if defined (READLINE)
static int shopt_set_complete_direxpand __P((char *, int));
#endif
static int shopt_login_shell;
static int shopt_compat31;
static int shopt_compat32;
@@ -150,6 +158,7 @@ static struct {
{ "compat40", &shopt_compat40, set_compatibility_level },
{ "compat41", &shopt_compat41, set_compatibility_level },
#if defined (READLINE)
{ "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
{ "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
#endif
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
@@ -535,6 +544,17 @@ set_compatibility_level (option_name, mode)
return 0;
}
#if defined (READLINE)
static int
shopt_set_complete_direxpand (option_name, mode)
char *option_name;
int mode;
{
set_directory_hook ();
return 0;
}
#endif
#if defined (RESTRICTED_SHELL)
/* Don't allow the value of restricted_shell to be modified. */
+10
View File
@@ -8948,6 +8948,16 @@ parameter expansion as a special character. The single quotes must match
quoted. This is the behavior of posix mode through version 4.1.
The default bash behavior remains as in previous versions.
.TP 8
.B direxpand
If set,
.B bash
replaces directory names with the results of word expansion when performing
filename completion. This changes the contents of the readline editing
buffer.
If not set,
.B bash
attempts to preserve what the user typed.
.TP 8
.B dirspell
If set,
.B bash
+7
View File
@@ -4535,6 +4535,13 @@ parameter expansion as a special character. The single quotes must match
quoted. This is the behavior of @sc{posix} mode through version 4.1.
The default Bash behavior remains as in previous versions.
@item direxpand
If set, Bash
replaces directory names with the results of word expansion when performing
filename completion. This changes the contents of the readline editing
buffer.
If not set, Bash attempts to preserve what the user typed.
@item dirspell
If set, Bash
attempts spelling correction on directory names during word completion
+3
View File
@@ -12,6 +12,7 @@ shopt -u compat31
shopt -u compat32
shopt -u compat40
shopt -u compat41
shopt -u direxpand
shopt -u dirspell
shopt -u dotglob
shopt -u execfail
@@ -68,6 +69,7 @@ shopt -u compat31
shopt -u compat32
shopt -u compat40
shopt -u compat41
shopt -u direxpand
shopt -u dirspell
shopt -u dotglob
shopt -u execfail
@@ -101,6 +103,7 @@ compat31 off
compat32 off
compat40 off
compat41 off
direxpand off
dirspell off
dotglob off
execfail off