static void shell_expand_line ();
static void display_shell_version (), operate_and_get_next ();
static void history_expand_line (), bash_ignore_filenames ();
+#ifdef ALIAS
+static void alias_expand_line ();
+#endif
+static void history_and_alias_expand_line ();
+static void cleanup_expansion_error (), set_up_new_line ();
/* Helper functions for Readline. */
static int bash_directory_completion_hook ();
rl_add_defun ("history-expand-line", (Function *)history_expand_line, -1);
rl_bind_key_in_map ('^', (Function *)history_expand_line, emacs_meta_keymap);
+#ifdef ALIAS
+ rl_add_defun ("alias-expand-line", (Function *)alias_expand_line, -1);
+ rl_add_defun ("history-and-alias-expand-line", (Function *)history_and_alias_expand_line, -1);
+#endif
+
/* Backwards compatibility. */
rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
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 = " \t\n\\\"'@<>=;|&()#$`?*[!:";
rl_filename_quoting_function = bash_quote_filename;
rl_filename_dequoting_function = bash_dequote_filename;
rl_char_is_quoted_p = char_is_quoted;
the end of the history because fc ignores the last command (assumes
it's supposed to deal with the command before the `fc'). */
using_history ();
- add_history (rl_line_buffer);
- add_history ("");
+ bash_add_history (rl_line_buffer);
+ bash_add_history ("");
history_lines_this_session++;
using_history ();
command = savestring (VI_EDIT_COMMAND);
}
- parse_and_execute (command, "v", -1);
+ parse_and_execute (command, "v", SEVAL_NOHIST);
rl_line_buffer[0] = '\0'; /* XXX */
}
#endif /* VI_MODE */
assignments. */
}
- /* Special handling for command substitution. */
- if (*text == '`' && unclosed_pair (rl_line_buffer, start, "`"))
+ /* Check that we haven't incorrectly flagged a closed command substitution
+ as indicating we're in a command position. */
+ if (in_command_position && rl_line_buffer[ti] == '`' && *text != '`' &&
+ unclosed_pair (rl_line_buffer, 0, "`") == 0)
+ in_command_position = 0;
+
+ /* 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 == '`' && unclosed_pair (rl_line_buffer, start, "`") &&
+ unclosed_pair (rl_line_buffer, end, "`"))
matches = completion_matches (text, command_subst_completion_function);
/* Variable name? */
}
else
{
- int match;
+ int match, freetemp;
char *temp;
if (absolute_program (hint))
}
else
temp = savestring (val);
+ freetemp = 1;
}
else
{
if (temp)
{
temp++;
- match = strncmp (temp, hint, hint_len) == 0;
+ freetemp = match = strncmp (temp, hint, hint_len) == 0;
if (match)
temp = savestring (temp);
}
else
- match = 0;
+ freetemp = match = 0;
}
/* If we have found a match, and it is an executable file or a
}
else
{
+ if (freetemp)
+ free (temp);
free (val);
goto inner;
}
}
}
+/* Completion inside an unterminated command substitution. */
static char *
command_subst_completion_function (text, state)
char *text;
char *new_line;
new_line = pre_process_line (line, 0, 0);
- return new_line;
+ return (new_line == line) ? savestring (line) : new_line;
}
#if defined (ALIAS)
-/* Perform alias expansion on LINE and return the new line. */
-static char *
-alias_expand_line_internal (line)
- char *line;
+/* Expand aliases in the current readline line. */
+static void
+alias_expand_line (ignore)
+ int ignore;
{
- char *alias_line;
+ char *new_line;
+
+ new_line = alias_expand (rl_line_buffer);
- alias_line = alias_expand (line);
- return alias_line;
+ if (new_line)
+ set_up_new_line (new_line);
+ else
+ cleanup_expansion_error ();
}
#endif
fprintf (rl_outstream, "\r\n");
to_free = pre_process_line (rl_line_buffer, 1, 0);
- free (to_free);
+ if (to_free != rl_line_buffer)
+ free (to_free);
putc ('\r', rl_outstream);
rl_forced_update_display ();
}
char *new_line;
new_line = pre_process_line (rl_line_buffer, 0, 0);
+ if (new_line == rl_line_buffer)
+ new_line = savestring (new_line);
#if defined (ALIAS)
if (new_line)
WORD_LIST *expanded_string;
new_line = pre_process_line (rl_line_buffer, 0, 0);
+ if (new_line == rl_line_buffer)
+ new_line = savestring (new_line);
#if defined (ALIAS)
if (new_line)
/* If there is variable expansion to perform, do that as a separate
operation to be undone. */
- expanded_string = expand_string (rl_line_buffer, 0);
+ new_line = savestring (rl_line_buffer);
+ expanded_string = expand_string (new_line, 0);
+ FREE (new_line);
if (expanded_string == 0)
{
new_line = xmalloc (1);
return ret;
}
-/* Quote a filename using double quotes. */
+/* Quote characters that the readline completion code would treat as
+ word break characters with backslashes. Pass backslash-quoted
+ characters through without examination. */
+static char *
+quote_word_break_chars (text)
+ char *text;
+{
+ char *ret, *r, *s;
+ int l;
+
+ l = strlen (text);
+ ret = xmalloc ((2 * l) + 1);
+ for (s = text, r = ret; *s; s++)
+ {
+ /* Pass backslash-quoted characters through, including the backslash. */
+ if (*s == '\\')
+ {
+ *r++ = '\\';
+ *r++ = *++s;
+ if (*s == '\0')
+ break;
+ continue;
+ }
+ /* OK, we have an unquoted character. Check its presence in
+ rl_completer_word_break_characters. */
+ if (strchr (rl_completer_word_break_characters, *s))
+ *r++ = '\\';
+ *r++ = *s;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Quote a filename using double quotes, single quotes, or backslashes
+ depending on the value of completion_quoting_style. If we're
+ completing using backslashes, we need to quote some additional
+ characters (those that readline treats as word breaks), so we call
+ quote_word_break_chars on the result. */
static char *
bash_quote_filename (s, rtype, qcp)
char *s;
else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
history_expansion_inhibited == 0 && strchr (mtext, '!'))
cs = COMPLETE_BSQUOTE;
+
+ if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && strchr (mtext, '!'))
+ {
+ cs = COMPLETE_BSQUOTE;
+ *qcp = '\0';
+ }
#endif
switch (cs)
if (mtext != s)
free (mtext);
+ /* We may need to quote additional characters: those that readline treats
+ as word breaks that are not quoted by backslash_quote. */
+ if (rtext && cs == COMPLETE_BSQUOTE)
+ {
+ mtext = quote_word_break_chars (rtext);
+ free (rtext);
+ rtext = mtext;
+ }
+
/* Leave the opening quote intact. The readline completion code takes
care of avoiding doubled opening quotes. */
rlen = strlen (rtext);