📄 bashline.c
字号:
/* Have to jump through hoops here because there is a default binding for M-~ (rl_tilde_expand) */ kseq[0] = '~'; kseq[1] = '\0'; func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); if (func == 0 || func == rl_tilde_expand) rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap); rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap); rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap); rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap); rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap); rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);#endif /* SPECIFIC_COMPLETION_FUNCTIONS */ kseq[0] = TAB; kseq[1] = '\0'; func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); if (func == 0 || func == rl_tab_insert) rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap); /* Tell the completer that we want a crack first. */ rl_attempted_completion_function = attempt_shell_completion; /* 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; 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; /* Bind C-xC-e to invoke emacs and run result as commands. */ rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);#if defined (VI_MODE) rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);# if defined (ALIAS) rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);# endif rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap); rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap); rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);#endif rl_completer_quote_characters = "'\""; /* This sets rl_completer_word_break_characters and rl_special_prefixes to the appropriate values, depending on whether or not hostname completion is enabled. */ enable_hostname_completion (perform_hostname_completion); /* characters that need to be quoted when appearing in filenames. */ 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;#if 0 /* This is superfluous and makes it impossible to use tab completion in vi mode even when explicitly binding it in ~/.inputrc. sv_strict_posix() should already have called posix_readline_initialize() when posixly_correct was set. */ if (posixly_correct) posix_readline_initialize (1);#endif bash_readline_initialized = 1;}voidbashline_reinitialize (){ bash_readline_initialized = 0;}/* On Sun systems at least, rl_attempted_completion_function can end up getting set to NULL, and rl_completion_entry_function set to do command word completion if Bash is interrupted while trying to complete a command word. This just resets all the completion functions to the right thing. It's called from throw_to_top_level(). */voidbashline_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;}/* Contains the line to push into readline. */static char *push_to_readline = (char *)NULL;/* Push the contents of push_to_readline into the readline buffer. */static intbash_push_line (){ if (push_to_readline) { rl_insert_text (push_to_readline); free (push_to_readline); push_to_readline = (char *)NULL; rl_startup_hook = old_rl_startup_hook; } return 0;}/* Call this to set the initial text for the next line to read from readline. */intbash_re_edit (line) char *line;{ FREE (push_to_readline); push_to_readline = savestring (line); old_rl_startup_hook = rl_startup_hook; rl_startup_hook = bash_push_line; return (0);}static intdisplay_shell_version (count, c) int count, c;{ rl_crlf (); show_shell_version (0); putc ('\r', rl_outstream); fflush (rl_outstream); rl_on_new_line (); rl_redisplay (); return 0;}/* **************************************************************** *//* *//* Readline Stuff *//* *//* **************************************************************** *//* If the user requests hostname completion, then simply build a list of hosts, and complete from that forever more, or at least until HOSTFILE is unset. *//* THIS SHOULD BE A STRINGLIST. *//* The kept list of hostnames. */static char **hostname_list = (char **)NULL;/* The physical size of the above list. */static int hostname_list_size;/* The number of hostnames in the above list. */static int hostname_list_length;/* Whether or not HOSTNAME_LIST has been initialized. */int hostname_list_initialized = 0;/* Initialize the hostname completion table. */static voidinitialize_hostname_list (){ char *temp; temp = get_string_value ("HOSTFILE"); if (temp == 0) temp = get_string_value ("hostname_completion_file"); if (temp == 0) temp = DEFAULT_HOSTS_FILE; snarf_hosts_from_file (temp); if (hostname_list) hostname_list_initialized++;}/* Add NAME to the list of hosts. */static voidadd_host_name (name) char *name;{ if (hostname_list_length + 2 > hostname_list_size) { hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32); hostname_list = strvec_resize (hostname_list, hostname_list_size); } hostname_list[hostname_list_length++] = savestring (name); hostname_list[hostname_list_length] = (char *)NULL;}#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))static voidsnarf_hosts_from_file (filename) char *filename;{ FILE *file; char *temp, buffer[256], name[256]; register int i, start; file = fopen (filename, "r"); if (file == 0) return; while (temp = fgets (buffer, 255, file)) { /* Skip to first character. */ for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++) ; /* If comment or blank line, ignore. */ if (buffer[i] == '\0' || buffer[i] == '#') continue; /* If `preprocessor' directive, do the include. */ if (strncmp (buffer + i, "$include ", 9) == 0) { char *incfile, *t; /* Find start of filename. */ for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++) ; /* Find end of filename. */ for (t = incfile; *t && cr_whitespace (*t) == 0; t++) ; *t = '\0'; snarf_hosts_from_file (incfile); continue; } /* Skip internet address if present. */ if (DIGIT (buffer[i])) for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++); /* Gobble up names. Each name is separated with whitespace. */ while (buffer[i]) { for (; cr_whitespace (buffer[i]); i++) ; if (buffer[i] == '\0' || buffer[i] == '#') break; /* Isolate the current word. */ for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++) ; if (i == start) continue; strncpy (name, buffer + start, i - start); name[i - start] = '\0'; add_host_name (name); } } fclose (file);}/* Return the hostname list. */char **get_hostname_list (){ if (hostname_list_initialized == 0) initialize_hostname_list (); return (hostname_list);}voidclear_hostname_list (){ register int i; if (hostname_list_initialized == 0) return; for (i = 0; i < hostname_list_length; i++) free (hostname_list[i]); hostname_list_length = hostname_list_initialized = 0;}/* Return a NULL terminated list of hostnames which begin with TEXT. Initialize the hostname list the first time if neccessary. The array is malloc ()'ed, but not the individual strings. */static char **hostnames_matching (text) char *text;{ register int i, len, nmatch, rsize; char **result; if (hostname_list_initialized == 0) initialize_hostname_list (); if (hostname_list_initialized == 0) return ((char **)NULL); /* Special case. If TEXT consists of nothing, then the whole list is what is desired. */ if (*text == '\0') { result = strvec_create (1 + hostname_list_length); for (i = 0; i < hostname_list_length; i++) result[i] = hostname_list[i]; result[i] = (char *)NULL; return (result); } /* Scan until found, or failure. */ len = strlen (text); result = (char **)NULL; for (i = nmatch = rsize = 0; i < hostname_list_length; i++) { if (STREQN (text, hostname_list[i], len) == 0) continue; /* OK, it matches. Add it to the list. */ if (nmatch >= (rsize - 1)) { rsize = (rsize + 16) - (rsize % 16); result = strvec_resize (result, rsize); } result[nmatch++] = hostname_list[i]; } if (nmatch) result[nmatch] = (char *)NULL; return (result);}/* The equivalent of the Korn shell C-o operate-and-get-next-history-line editing command. */static int saved_history_line_to_use = -1;static intset_saved_history (){ if (saved_history_line_to_use >= 0) rl_get_previous_history (history_length - saved_history_line_to_use, 0); saved_history_line_to_use = -1; rl_startup_hook = old_rl_startup_hook; return (0);}static intoperate_and_get_next (count, c) int count, c;{ int where; /* Accept the current line. */ rl_newline (1, c); /* Find the current line, and find the next line to use. */ where = where_history (); if ((history_is_stifled () && (history_length >= history_max_entries)) || (where >= history_length - 1)) saved_history_line_to_use = where; else saved_history_line_to_use = where + 1; old_rl_startup_hook = rl_startup_hook; rl_startup_hook = set_saved_history; return 0;}/* This vi mode command causes VI_EDIT_COMMAND to be run on the current command being entered (if no explicit argument is given), otherwise on a command from the history file. */#define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-vi}}\""#define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""#define POSIX_VI_EDIT_COMMAND "fc -e vi"static intedit_and_execute_command (count, c, editing_mode, edit_command) int count, c, editing_mode; char *edit_command;{ char *command, *metaval; int r, rrs, metaflag; sh_parser_state_t ps; rrs = rl_readline_state; saved_command_line_count = current_command_line_count; /* Accept the current line. */ rl_newline (1, c); if (rl_explicit_arg) { command = (char *)xmalloc (strlen (edit_command) + 8); sprintf (command, "%s %d", edit_command, count); } else { /* Take the command we were just editing, add it to the history file, then call fc to operate on it. We have to add a dummy command to the end of the history because fc ignores the last command (assumes it's supposed to deal with the command before the `fc'). */ /* This breaks down when using command-oriented history and are not finished with the command, so we should not ignore the last command */ using_history (); bash_add_history (rl_line_buffer); bash_add_history (""); history_lines_this_session++; using_history (); command = savestring (edit_command); } metaval = rl_variable_value ("input-meta"); metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval); /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the temporary file should be placed into the history. We don't do that yet. */ if (rl_deprep_term_function) (*rl_deprep_term_function) (); save_parser_state (&ps); r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST); restore_parser_state (&ps); if (rl_prep_term_function) (*rl_prep_term_function) (metaflag); current_command_line_count = saved_command_line_count; /* Now erase the contents of the current line and undo the effects of the rl_accept_line() above. We don't even want to make the text we just executed available for undoing. */ rl_line_buffer[0] = '\0'; /* XXX */ rl_point = rl_end = 0; rl_done = 0; rl_readline_state = rrs; rl_forced_update_display (); return r;}#if defined (VI_MODE)static intvi_edit_and_execute_command (count, c) int count, c;{ if (posixly_correct) return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND)); else return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));}#endif /* VI_MODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -