📄 bashline.c
字号:
static intemacs_edit_and_execute_command (count, c) int count, c;{ return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));}#if defined (ALIAS)static intposix_edit_macros (count, key) int count, key;{ int c; char alias_name[3], *alias_value, *macro; c = rl_read_key (); alias_name[0] = '_'; alias_name[1] = c; alias_name[2] = '\0'; alias_value = get_alias_value (alias_name); if (alias_value && *alias_value) { macro = savestring (alias_value); rl_push_macro_input (macro); } return 0;}#endif/* Bindable commands that move `shell-words': that is, sequences of non-unquoted-metacharacters. */#define WORDDELIM(c) (shellmeta(c) || shellblank(c))static intbash_forward_shellword (count, key) int count, key;{ size_t slen; int sindex, c, p; DECLARE_MBSTATE; if (count < 0) return (bash_backward_shellword (-count, key)); /* The tricky part of this is deciding whether or not the first character we're on is an unquoted metacharacter. Not completely handled yet. */ /* XXX - need to test this stuff with backslash-escaped shell metacharacters and unclosed single- and double-quoted strings. */ p = rl_point; slen = rl_end; while (count) { if (p == rl_end) { rl_point = rl_end; return 0; } /* Are we in a quoted string? If we are, move to the end of the quoted string and continue the outer loop. We only want quoted strings, not backslash-escaped characters, but char_is_quoted doesn't differentiate. */ if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\') { do ADVANCE_CHAR (rl_line_buffer, slen, p); while (p < rl_end && char_is_quoted (rl_line_buffer, p)); count--; continue; } /* Rest of code assumes we are not in a quoted string. */ /* Move forward until we hit a non-metacharacter. */ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c)) { switch (c) { default: ADVANCE_CHAR (rl_line_buffer, slen, p); continue; /* straight back to loop, don't increment p */ case '\\': if (p < rl_end && rl_line_buffer[p]) ADVANCE_CHAR (rl_line_buffer, slen, p); break; case '\'': p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP); break; case '"': p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP); break; } if (p < rl_end) p++; } if (rl_line_buffer[p] == 0 || p == rl_end) { rl_point = rl_end; rl_ding (); return 0; } /* Now move forward until we hit a non-quoted metacharacter or EOL */ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0) { switch (c) { default: ADVANCE_CHAR (rl_line_buffer, slen, p); continue; /* straight back to loop, don't increment p */ case '\\': if (p < rl_end && rl_line_buffer[p]) ADVANCE_CHAR (rl_line_buffer, slen, p); break; case '\'': p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP); break; case '"': p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP); break; } if (p < rl_end) p++; } if (p == rl_end || rl_line_buffer[p] == 0) { rl_point = rl_end; return (0); } count--; } rl_point = p; return (0);}static intbash_backward_shellword (count, key) int count, key;{ size_t slen; int sindex, c, p; DECLARE_MBSTATE; if (count < 0) return (bash_forward_shellword (-count, key)); p = rl_point; slen = rl_end; while (count) { if (p == 0) { rl_point = 0; return 0; } /* Move backward until we hit a non-metacharacter. */ while (p > 0) { c = rl_line_buffer[p]; if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0) BACKUP_CHAR (rl_line_buffer, slen, p); break; } if (p == 0) { rl_point = 0; return 0; } /* Now move backward until we hit a metacharacter or BOL. */ while (p > 0) { c = rl_line_buffer[p]; if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0) break; BACKUP_CHAR (rl_line_buffer, slen, p); } count--; } rl_point = p; return 0;}static intbash_kill_shellword (count, key) int count, key;{ int p; if (count < 0) return (bash_backward_kill_shellword (-count, key)); p = rl_point; bash_forward_shellword (count, key); if (rl_point != p) rl_kill_text (p, rl_point); rl_point = p; if (rl_editing_mode == 1) /* 1 == emacs_mode */ rl_mark = rl_point; return 0;}static intbash_backward_kill_shellword (count, key) int count, key;{ int p; if (count < 0) return (bash_kill_shellword (-count, key)); p = rl_point; bash_backward_shellword (count, key); if (rl_point != p) rl_kill_text (p, rl_point); if (rl_editing_mode == 1) /* 1 == emacs_mode */ rl_mark = rl_point; return 0;}/* **************************************************************** *//* *//* How To Do Shell Completion *//* *//* **************************************************************** */#define COMMAND_SEPARATORS ";|&{(`"/* )} */ static intcheck_redir (ti) int ti;{ register int this_char, prev_char; /* Handle the two character tokens `>&', `<&', and `>|'. We are not in a command position after one of these. */ this_char = rl_line_buffer[ti]; prev_char = rl_line_buffer[ti - 1]; if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) || (this_char == '|' && prev_char == '>')) return (1); else if ((this_char == '{' && prev_char == '$') || /* } */ (char_is_quoted (rl_line_buffer, ti))) return (1); return (0);}#if defined (PROGRAMMABLE_COMPLETION)/* * XXX - because of the <= start test, and setting os = s+1, this can * potentially return os > start. This is probably not what we want to * happen, but fix later after 2.05a-release. */static intfind_cmd_start (start) int start;{ register int s, os; os = 0; 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;}static intfind_cmd_end (end) int end;{ register int e; e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP); return e;}static char *find_cmd_name (start) int start;{ char *name; register int s, e; for (s = start; whitespace (rl_line_buffer[s]); s++) ; /* skip until a shell break character */ e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP); name = substring (rl_line_buffer, s, e); return (name);}static char *prog_complete_return (text, matchnum) const char *text; int matchnum;{ static int ind; if (matchnum == 0) ind = 0; if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0) return (char *)NULL; return (prog_complete_matches[ind++]);}#endif /* PROGRAMMABLE_COMPLETION *//* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are at START and END. Return an array of matches, or NULL if none. */static char **attempt_shell_completion (text, start, end) const char *text; int start, end;{ int in_command_position, ti, saveti, qc, dflags; char **matches, *command_separator_chars; command_separator_chars = COMMAND_SEPARATORS; matches = (char **)NULL; rl_ignore_some_completions_function = filename_completion_ignore; /* 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 command word if we aren't at the top-level prompt. */ ti = start - 1; saveti = qc = -1; while ((ti > -1) && (whitespace (rl_line_buffer[ti]))) ti--;#if 1 /* If this is an open quote, maybe we're trying to complete a quoted command name. */ if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\'')) { qc = rl_line_buffer[ti]; saveti = ti--; while (ti > -1 && (whitespace (rl_line_buffer[ti]))) ti--; }#endif in_command_position = 0; if (ti < 0) { /* Only do command completion at the start of a line when we are prompting at the top level. */ if (current_prompt_string == ps1_prompt) in_command_position++; } else if (member (rl_line_buffer[ti], command_separator_chars)) { in_command_position++; if (check_redir (ti) == 1) in_command_position = 0; } else { /* This still could be in command position. It is possible that all of the previous words on the line are variable assignments. */ } /* Check that we haven't incorrectly flagged a closed command substitution as indicating we're in a command position. */ if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' && *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 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. 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);#if defined (PROGRAMMABLE_COMPLETION) /* Attempt programmable completion. */ if (matches == 0 && (in_command_position == 0 || text[0] == '\0') && prog_completion_enabled && (progcomp_size () > 0) && current_prompt_string == ps1_prompt) { int s, e, foundcs; char *n; /* XXX - don't free the members */ if (prog_complete_matches) free (prog_complete_matches); prog_complete_matches = (char **)NULL; s = find_cmd_start (start); e = find_cmd_end (end); n = find_cmd_name (s); if (e == 0 && e == s && text[0] == '\0') prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs); else if (e > s && assignment (n, 0) == 0) prog_complete_matches = programmable_completions (n, text, s, e, &foundcs); else foundcs = 0; FREE (n); /* XXX - if we found a COMPSPEC for the command, just return whatever the programmable completion code returns, and disable the default filename completion that readline will do unless the COPT_DEFAULT option has been set with the `-o default' option to complete or compopt. */ if (foundcs) { pcomp_set_readline_variables (foundcs, 1); /* Turn what the programmable completion code returns into what readline wants. I should have made compute_lcd_of_matches external... */ matches = rl_completion_matches (text, prog_complete_return); if ((foundcs & COPT_DEFAULT) == 0) rl_attempted_completion_over = 1; /* no default */ if (matches || ((foundcs & COPT_BASHDEFAULT) == 0)) return (matches); } }#endif if (matches == 0) { dflags = 0; if (in_command_position) dflags |= DEFCOMP_CMDPOS; matches = bash_default_completion (text, start, end, qc, dflags); } return matches;}char **bash_default_completion (text, start, end, qc, compflags)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -