📄 readline.c
字号:
{ if (chars_avail) rl_stuff_char (input); }#endif /* !__GO32__ */}static int next_macro_key ();/* Read a key, including pending input. */intrl_read_key (){ int c; rl_key_sequence_length++; if (rl_pending_input) { c = rl_pending_input; rl_pending_input = 0; } else { /* If input is coming from a macro, then use that. */ if (c = next_macro_key ()) return (c); /* If the user has an event function, then call it periodically. */ if (rl_event_hook) { while (rl_event_hook && !rl_get_char (&c)) { (*rl_event_hook) (); rl_gather_tyi (); } } else { if (!rl_get_char (&c)) c = rl_getc (in_stream); } } return (c);}/* Found later in this file. */static void add_macro_char (), with_macro_input ();/* Do the command associated with KEY in MAP. If the associated command is really a keymap, then read another key, and dispatch into that map. */int_rl_dispatch (key, map) register int key; Keymap map;{ int r = 0; if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { if (map[ESC].type == ISKMAP) { if (defining_kbd_macro) add_macro_char (ESC); map = FUNCTION_TO_KEYMAP (map, ESC); key = UNMETA (key); rl_key_sequence_length += 2; return (_rl_dispatch (key, map)); } else ding (); return 0; } if (defining_kbd_macro) add_macro_char (key); switch (map[key].type) { case ISFUNC: { Function *func = map[key].function; if (func != (Function *)NULL) { /* Special case rl_do_lowercase_version (). */ if (func == rl_do_lowercase_version) return (_rl_dispatch (to_lower (key), map)); r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); /* If we have input pending, then the last command was a prefix command. Don't change the state of rl_last_func. Otherwise, remember the last command executed in this variable. */ if (!rl_pending_input) rl_last_func = map[key].function; } else { rl_abort (); return -1; } } break; case ISKMAP: if (map[key].function != (Function *)NULL) { int newkey; rl_key_sequence_length++; newkey = rl_read_key (); r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key)); } else { rl_abort (); return -1; } break; case ISMACR: if (map[key].function != (Function *)NULL) { char *macro; macro = savestring ((char *)map[key].function); with_macro_input (macro); return 0; } break; }#if defined (VI_MODE) if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && rl_vi_textmod_command (key)) _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);#endif return (r);}/* **************************************************************** *//* *//* Hacking Keyboard Macros *//* *//* **************************************************************** *//* The currently executing macro string. If this is non-zero, then it is a malloc ()'ed string where input is coming from. */static char *executing_macro = (char *)NULL;/* The offset in the above string to the next character to be read. */static int executing_macro_index = 0;/* The current macro string being built. Characters get stuffed in here by add_macro_char (). */static char *current_macro = (char *)NULL;/* The size of the buffer allocated to current_macro. */static int current_macro_size = 0;/* The index at which characters are being added to current_macro. */static int current_macro_index = 0;/* A structure used to save nested macro strings. It is a linked list of string/index for each saved macro. */struct saved_macro { struct saved_macro *next; char *string; int sindex;};/* The list of saved macros. */struct saved_macro *macro_list = (struct saved_macro *)NULL;/* Forward declarations of static functions. Thank you C. */static void push_executing_macro (), pop_executing_macro ();/* This one has to be declared earlier in the file. *//* static void add_macro_char (); *//* Set up to read subsequent input from STRING. STRING is free ()'ed when we are done with it. */static voidwith_macro_input (string) char *string;{ push_executing_macro (); executing_macro = string; executing_macro_index = 0;}/* Return the next character available from a macro, or 0 if there are no macro characters. */static intnext_macro_key (){ if (!executing_macro) return (0); if (!executing_macro[executing_macro_index]) { pop_executing_macro (); return (next_macro_key ()); } return (executing_macro[executing_macro_index++]);}/* Save the currently executing macro on a stack of saved macros. */static voidpush_executing_macro (){ struct saved_macro *saver; saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); saver->next = macro_list; saver->sindex = executing_macro_index; saver->string = executing_macro; macro_list = saver;}/* Discard the current macro, replacing it with the one on the top of the stack of saved macros. */static voidpop_executing_macro (){ if (executing_macro) free (executing_macro); executing_macro = (char *)NULL; executing_macro_index = 0; if (macro_list) { struct saved_macro *disposer = macro_list; executing_macro = macro_list->string; executing_macro_index = macro_list->sindex; macro_list = macro_list->next; free (disposer); }}/* Add a character to the macro being built. */static voidadd_macro_char (c) int c;{ if (current_macro_index + 1 >= current_macro_size) { if (!current_macro) current_macro = xmalloc (current_macro_size = 25); else current_macro = xrealloc (current_macro, current_macro_size += 25); } current_macro[current_macro_index++] = c; current_macro[current_macro_index] = '\0';}/* Begin defining a keyboard macro. Keystrokes are recorded as they are executed. End the definition with rl_end_kbd_macro (). If a numeric argument was explicitly typed, then append this definition to the end of the existing macro, and start by re-executing the existing macro. */rl_start_kbd_macro (ignore1, ignore2) int ignore1, ignore2;{ if (defining_kbd_macro) { rl_abort (); return -1; } if (rl_explicit_arg) { if (current_macro) with_macro_input (savestring (current_macro)); } else current_macro_index = 0; defining_kbd_macro = 1; return 0;}/* Stop defining a keyboard macro. A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */rl_end_kbd_macro (count, ignore) int count, ignore;{ if (!defining_kbd_macro) { rl_abort (); return -1; } current_macro_index -= (rl_key_sequence_length - 1); current_macro[current_macro_index] = '\0'; defining_kbd_macro = 0; return (rl_call_last_kbd_macro (--count, 0));}/* Execute the most recently defined keyboard macro. COUNT says how many times to execute it. */rl_call_last_kbd_macro (count, ignore) int count, ignore;{ if (!current_macro) rl_abort (); if (defining_kbd_macro) { ding (); /* no recursive macros */ current_macro[--current_macro_index] = '\0'; /* erase this char */ return 0; } while (count--) with_macro_input (savestring (current_macro)); return 0;}void_rl_kill_kbd_macro (){ if (current_macro) { free (current_macro); current_macro = (char *) NULL; } current_macro_size = current_macro_index = 0; if (executing_macro) { free (executing_macro); executing_macro = (char *) NULL; } executing_macro_index = 0; defining_kbd_macro = 0;}/* **************************************************************** *//* *//* Initializations *//* *//* **************************************************************** *//* Initliaze readline (and terminal if not already). */rl_initialize (){ /* If we have never been called before, initialize the terminal and data structures. */ if (!rl_initialized) { readline_initialize_everything (); rl_initialized++; } /* Initalize the current line information. */ rl_point = rl_end = 0; the_line = rl_line_buffer; the_line[0] = 0; /* We aren't done yet. We haven't even gotten started yet! */ rl_done = 0; /* Tell the history routines what is going on. */ start_using_history (); /* Make the display buffer match the state of the line. */ rl_reset_line_state (); /* No such function typed yet. */ rl_last_func = (Function *)NULL; /* Parsing of key-bindings begins in an enabled state. */ _rl_parsing_conditionalized_out = 0; return 0;}/* Initialize the entire state of the world. */static voidreadline_initialize_everything (){ char *t; /* Find out if we are running in Emacs. */ running_in_emacs = getenv ("EMACS") != (char *)0; /* Set up input and output if they are not already set up. */ if (!rl_instream) rl_instream = stdin; if (!rl_outstream) rl_outstream = stdout; /* Bind in_stream and out_stream immediately. These values may change, but they may also be used before readline_internal () is called. */ in_stream = rl_instream; out_stream = rl_outstream; /* Allocate data structures. */ if (!rl_line_buffer) rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); /* Initialize the terminal interface. */ init_terminal_io ((char *)NULL);#if !defined (__GO32__) /* Bind tty characters to readline functions. */ readline_default_bindings ();#endif /* !__GO32__ */ /* Initialize the function names. */ rl_initialize_funmap (); /* Check for LC_CTYPE and use its value to decide the defaults for 8-bit character input and output. */ t = getenv ("LC_CTYPE"); if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0 || strcmp (t, "ISO-8859-1") == 0)) { _rl_meta_flag = 1; _rl_convert_meta_chars_to_ascii = 0; _rl_output_meta_chars = 1; } /* Read in the init file. */ rl_read_init_file ((char *)NULL); /* XXX */ if (_rl_horizontal_scroll_mode && term_xn) { screenwidth--; screenchars -= screenheight; } /* Override the effect of any `set keymap' assignments in the inputrc file. */ rl_set_keymap_from_edit_mode (); /* Try to bind a common arrow key prefix, if not already bound. */ bind_arrow_keys (); /* If the completion parser's default word break characters haven't been set yet, then do so now. */ if (rl_completer_word_break_characters == (char *)NULL) rl_completer_word_break_characters = rl_basic_word_break_characters;}/* If this system allows us to look at the values of the regular input editing characters, then bind them to their readline equivalents, iff the characters are not bound to keymaps. */static voidreadline_default_bindings (){ rltty_set_default_bindings (_rl_keymap);}static voidbind_arrow_keys_internal (){ Function *f; f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL); if (!f || f == rl_do_lowercase_version) { _rl_bind_if_unbound ("\033[A", rl_get_previous_history); _rl_bind_if_unbound ("\033[B", rl_get_next_history); _rl_bind_if_unbound ("\033[C", rl_forward); _rl_bind_if_unbound ("\033[D", rl_backward); } f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL); if (!f || f == rl_do_lowercase_version) { _rl_bind_if_unbound ("\033OA", rl_get_previous_history); _rl_bind_if_unbound ("\033OB", rl_get_next_history); _rl_bind_if_unbound ("\033OC", rl_forward); _rl_bind_if_unbound ("\033OD", rl_backward); }}/* Try and bind the common arrow key prefix after giving termcap and the inputrc file a chance to bind them and create `real' keymaps for the arrow key prefix. */static voidbind_arrow_keys (){ Keymap xkeymap; xkeymap = _rl_keymap; _rl_keymap = emacs_standard_keymap; bind_arrow_keys_internal ();#if defined (VI_MODE) _rl_keymap = vi_movement_keymap; bind_arrow_keys_internal ();#endif _rl_keymap = xkeymap;}/* **************************************************************** *//* *//* Numeric Arguments *//* *//* **************************************************************** *//* Handle C-u style numeric args, as well as M--, and M-digits. */static intrl_digit_loop (){ int key, c; while (1) { rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); key = c = rl_read_key (); if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { rl_numeric_arg *= 4; continue; } c = UNMETA (c); if (digit_p (c)) { if (rl_explicit_arg) rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0'); else rl_numeric_arg = (c - '0'); rl_explicit_arg = 1; } else { if (c == '-' && !rl_explicit_arg) { rl_numeric_arg = 1; rl_arg_sign = -1; } else { rl_clear_message (); return (_rl_dispatch (key, _rl_keymap)); } } } return 0;}/* Add the current digit to the argument in progress. */rl_digit_argument (ignore, key) int ignore, key;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -