From 0001803f0b9523c94fa2ede48eaecb047fef4524 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 21 Nov 2011 20:51:19 -0500 Subject: Bash-4.1 distribution source --- bashline.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 20 deletions(-) (limited to 'bashline.c') diff --git a/bashline.c b/bashline.c index 4594dcf7..7658771e 100644 --- a/bashline.c +++ b/bashline.c @@ -82,6 +82,9 @@ extern int bash_brace_completion __P((int, int)); #endif /* BRACE_COMPLETION */ +/* To avoid including curses.h/term.h/termcap.h and that whole mess. */ +extern int tputs __P((const char *string, int nlines, int (*outx)(int))); + /* Forward declarations */ /* Functions bound to keys in Readline for Bash users. */ @@ -112,6 +115,7 @@ static int bash_backward_kill_shellword __P((int, int)); /* Helper functions for Readline. */ static char *restore_tilde __P((char *, char *)); +static char *bash_filename_rewrite_hook __P((char *, int)); static void bash_directory_expansion __P((char **)); static int bash_directory_completion_hook __P((char **)); static int filename_completion_ignore __P((char **)); @@ -146,6 +150,7 @@ static char *bash_dequote_filename __P((char *, int)); static char *quote_word_break_chars __P((char *)); static char *bash_quote_filename __P((char *, int, char *)); +static int putx __P((int)); static int bash_execute_unix_command __P((int, int)); static void init_unix_command_map __P((void)); static int isolate_sequence __P((char *, int, int, int *)); @@ -245,6 +250,9 @@ static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL; static int dot_in_path = 0; +/* Set to non-zero when dabbrev-expand is running */ +static int dabbrev_expand_active = 0; + /* What kind of quoting is performed by bash_quote_filename: COMPLETE_DQUOTE = double-quoting the filename COMPLETE_SQUOTE = single_quoting the filename @@ -494,6 +502,8 @@ initialize_readline () do other expansion on directory names. */ rl_directory_completion_hook = bash_directory_completion_hook; + rl_filename_rewrite_hook = bash_filename_rewrite_hook; + /* Tell the filename completer we want a chance to ignore some names. */ rl_ignore_some_completions_function = filename_completion_ignore; @@ -748,7 +758,7 @@ clear_hostname_list () return; for (i = 0; i < hostname_list_length; i++) free (hostname_list[i]); - hostname_list_length = 0; + hostname_list_length = hostname_list_initialized = 0; } /* Return a NULL terminated list of hostnames which begin with TEXT. @@ -1187,7 +1197,7 @@ find_cmd_start (start) register int s, os; os = 0; - while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP)) <= start) && + while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP|SD_NOSKIPCMD)) <= start) && rl_line_buffer[s]) os = s+1; return os; @@ -1305,8 +1315,9 @@ attempt_shell_completion (text, start, end) /* Special handling for command substitution. If *TEXT is a backquote, it can be the start or end of an old-style command substitution, or unmatched. If it's unmatched, both calls to unclosed_pair will - succeed. */ - if (*text == '`' && + succeed. Don't bother if readline found a single quote and we are + completing on the substring. */ + if (*text == '`' && rl_completion_quote_character != '\'' && (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") && unclosed_pair (rl_line_buffer, end, "`")))) matches = rl_completion_matches (text, command_subst_completion_function); @@ -1386,7 +1397,7 @@ bash_default_completion (text, start, end, qc, compflags) /* If the word starts in `~', and there is no slash in the word, then try completing this word as a username. */ - if (!matches && *text == '~' && !xstrchr (text, '/')) + if (matches ==0 && *text == '~' && mbschr (text, '/') == 0) matches = rl_completion_matches (text, rl_username_completion_function); /* Another one. Why not? If the word starts in '@', then look through @@ -2652,6 +2663,20 @@ bash_directory_expansion (dirname) } } +/* If necessary, rewrite directory entry */ +static char * +bash_filename_rewrite_hook (fname, fnlen) + char *fname; + int fnlen; +{ + char *conv; + + conv = fnx_fromfs (fname, fnlen); + if (conv != fname) + conv = savestring (conv); + return conv; +} + /* Handle symbolic link references and other directory name expansions while hacking completion. */ static int @@ -2666,11 +2691,11 @@ bash_directory_completion_hook (dirname) return_value = should_expand_dirname = 0; local_dirname = *dirname; - if (xstrchr (local_dirname, '$')) + if (mbschr (local_dirname, '$')) should_expand_dirname = 1; else { - t = xstrchr (local_dirname, '`'); + t = mbschr (local_dirname, '`'); if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0) should_expand_dirname = 1; } @@ -2787,6 +2812,8 @@ build_history_completion_array () if (hlist) { for (i = 0; hlist[i]; i++) + ; + for ( --i; i >= 0; i--) { /* Separate each token, and place into an array. */ tokens = history_tokenize (hlist[i]->line); @@ -2803,7 +2830,8 @@ build_history_completion_array () } /* Sort the complete list of tokens. */ - qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp); + if (dabbrev_expand_active == 0) + qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp); } } @@ -2819,6 +2847,8 @@ history_completion_generator (hint_text, state) list of strings to complete over. */ if (state == 0) { + if (dabbrev_expand_active) /* This is kind of messy */ + rl_completion_suppress_append = 1; local_index = 0; build_history_completion_array (); text = hint_text; @@ -2862,25 +2892,33 @@ static int bash_dabbrev_expand (count, key) int count, key; { - int r; + int r, orig_suppress, orig_sort; rl_compentry_func_t *orig_func; rl_completion_func_t *orig_attempt_func; orig_func = rl_menu_completion_entry_function; orig_attempt_func = rl_attempted_completion_function; + orig_suppress = rl_completion_suppress_append; + orig_sort = rl_sort_completion_matches; rl_menu_completion_entry_function = history_completion_generator; rl_attempted_completion_function = (rl_completion_func_t *)NULL; rl_filename_completion_desired = 0; + rl_completion_suppress_append = 1; + rl_sort_completion_matches = 0; /* XXX - use rl_completion_mode here? */ + dabbrev_expand_active = 1; if (rl_last_func == bash_dabbrev_expand) rl_last_func = rl_menu_complete; r = rl_menu_complete (count, key); + dabbrev_expand_active = 0; rl_last_func = bash_dabbrev_expand; rl_menu_completion_entry_function = orig_func; rl_attempted_completion_function = orig_attempt_func; + rl_completion_suppress_append = orig_suppress; + rl_sort_completion_matches = orig_sort; return r; } @@ -3225,7 +3263,7 @@ bash_dequote_filename (text, quote_char) *r++ = *++p; if (*p == '\0') - break; + return ret; /* XXX - was break; */ continue; } /* Close quote. */ @@ -3271,7 +3309,7 @@ quote_word_break_chars (text) } /* OK, we have an unquoted character. Check its presence in rl_completer_word_break_characters. */ - if (xstrchr (rl_completer_word_break_characters, *s)) + if (mbschr (rl_completer_word_break_characters, *s)) *r++ = '\\'; /* XXX -- check for standalone tildes here and backslash-quote them */ if (s == text && *s == '~' && file_exists (text)) @@ -3313,7 +3351,7 @@ bash_quote_filename (s, rtype, qcp) the word being completed contains newlines, since those are not quoted correctly using backslashes (a backslash-newline pair is special to the shell parser). */ - if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && xstrchr (s, '\n')) + if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n')) cs = COMPLETE_SQUOTE; else if (*qcp == '"') cs = COMPLETE_DQUOTE; @@ -3321,11 +3359,11 @@ bash_quote_filename (s, rtype, qcp) cs = COMPLETE_SQUOTE; #if defined (BANG_HISTORY) else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE && - history_expansion_inhibited == 0 && xstrchr (s, '!')) + history_expansion_inhibited == 0 && mbschr (s, '!')) cs = COMPLETE_BSQUOTE; if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE && - history_expansion_inhibited == 0 && xstrchr (s, '!')) + history_expansion_inhibited == 0 && mbschr (s, '!')) { cs = COMPLETE_BSQUOTE; *qcp = '\0'; @@ -3379,6 +3417,13 @@ bash_quote_filename (s, rtype, qcp) /* Support for binding readline key sequences to Unix commands. */ static Keymap cmd_xmap; +static int +putx(c) + int c; +{ + putc (c, rl_outstream); +} + static int bash_execute_unix_command (count, key) int count; /* ignored */ @@ -3386,10 +3431,10 @@ bash_execute_unix_command (count, key) { Keymap ckmap; /* current keymap */ Keymap xkmap; /* unix command executing keymap */ - register int i; + register int i, r; intmax_t mi; sh_parser_state_t ps; - char *cmd, *value, *l; + char *cmd, *value, *l, *l1, *ce; SHELL_VAR *v; char ibuf[INT_STRLEN_BOUND(int) + 1]; @@ -3425,12 +3470,20 @@ bash_execute_unix_command (count, key) return 1; } - rl_crlf (); /* move to a new line */ + ce = rl_get_termcap ("ce"); + if (ce) /* clear current line */ + { + fprintf (rl_outstream, "\r"); + tputs (ce, 1, putx); + fflush (rl_outstream); + } + else + rl_crlf (); /* move to a new line */ v = bind_variable ("READLINE_LINE", rl_line_buffer, 0); if (v) VSETATTR (v, att_exported); - l = value_cell (v); + l = v ? value_cell (v) : 0; value = inttostr (rl_point, ibuf, sizeof (ibuf)); v = bind_int_variable ("READLINE_POINT", value); if (v) @@ -3438,11 +3491,12 @@ bash_execute_unix_command (count, key) array_needs_making = 1; save_parser_state (&ps); - parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE); + r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE); restore_parser_state (&ps); v = find_variable ("READLINE_LINE"); - if (value_cell (v) != l) + l1 = v ? value_cell (v) : 0; + if (l1 != l) maybe_make_readline_line (value_cell (v)); v = find_variable ("READLINE_POINT"); if (v && legal_number (value_cell (v), &mi)) -- cgit v1.2.1