📄 readline.c
字号:
if (entry && rl_undo_list) { temp = savestring (the_line); rl_revert_line (1, 0); entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL); _rl_free_history_entry (entry); strcpy (the_line, temp); xfree (temp); } if (_rl_revert_all_at_newline) _rl_revert_all_lines (); /* At any rate, it is highly likely that this line has an undo list. Get rid of it now. */ if (rl_undo_list) rl_free_undo_list (); /* Restore normal cursor, if available. */ _rl_set_insert_mode (RL_IM_INSERT, 0); return (eof ? (char *)NULL : savestring (the_line));}void_rl_internal_char_cleanup (){#if defined (VI_MODE) /* In vi mode, when you exit insert mode, the cursor moves back over the previous character. We explicitly check for that here. */ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) rl_vi_check ();#endif /* VI_MODE */ if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) { (*rl_redisplay_function) (); _rl_want_redisplay = 0; rl_newline (1, '\n'); } if (rl_done == 0) { (*rl_redisplay_function) (); _rl_want_redisplay = 0; } /* If the application writer has told us to erase the entire line if the only character typed was something bound to rl_newline, do so. */ if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && rl_point == 0 && rl_end == 0) _rl_erase_entire_line ();}STATIC_CALLBACK int#if defined (READLINE_CALLBACKS)readline_internal_char ()#elsereadline_internal_charloop ()#endif{ static int lastc, eof_found; int c, code, lk; lastc = -1; eof_found = 0;#if !defined (READLINE_CALLBACKS) while (rl_done == 0) {#endif lk = _rl_last_command_was_kill; code = setjmp (_rl_top_level); if (code) { (*rl_redisplay_function) (); _rl_want_redisplay = 0; /* If we get here, we're not being called from something dispatched from _rl_callback_read_char(), which sets up its own value of _rl_top_level (saving and restoring the old, of course), so we can just return here. */ if (RL_ISSTATE (RL_STATE_CALLBACK)) return (0); } if (rl_pending_input == 0) { /* Then initialize the argument and number of keys read. */ _rl_reset_argument (); rl_key_sequence_length = 0; } RL_SETSTATE(RL_STATE_READCMD); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_READCMD); /* look at input.c:rl_getc() for the circumstances under which this will be returned; punt immediately on read error without converting it to a newline. */ if (c == READERR) {#if defined (READLINE_CALLBACKS) RL_SETSTATE(RL_STATE_DONE); return (rl_done = 1);#else eof_found = 1; break;#endif } /* EOF typed to a non-blank line is a <NL>. */ if (c == EOF && rl_end) c = NEWLINE; /* The character _rl_eof_char typed to blank line, and not as the previous character is interpreted as EOF. */ if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) {#if defined (READLINE_CALLBACKS) RL_SETSTATE(RL_STATE_DONE); return (rl_done = 1);#else eof_found = 1; break;#endif } lastc = c; _rl_dispatch ((unsigned char)c, _rl_keymap); RL_CHECK_SIGNALS (); /* If there was no change in _rl_last_command_was_kill, then no kill has taken place. Note that if input is pending we are reading a prefix command, so nothing has changed yet. */ if (rl_pending_input == 0 && lk == _rl_last_command_was_kill) _rl_last_command_was_kill = 0; _rl_internal_char_cleanup ();#if defined (READLINE_CALLBACKS) return 0;#else } return (eof_found);#endif}#if defined (READLINE_CALLBACKS)static intreadline_internal_charloop (){ int eof = 1; while (rl_done == 0) eof = readline_internal_char (); return (eof);}#endif /* READLINE_CALLBACKS *//* Read a line of input from the global rl_instream, doing output on the global rl_outstream. If rl_prompt is non-null, then that is our prompt. */static char *readline_internal (){ int eof; readline_internal_setup (); eof = readline_internal_charloop (); return (readline_internal_teardown (eof));}void_rl_init_line_state (){ rl_point = rl_end = rl_mark = 0; the_line = rl_line_buffer; the_line[0] = 0;}void_rl_set_the_line (){ the_line = rl_line_buffer;}#if defined (READLINE_CALLBACKS)_rl_keyseq_cxt *_rl_keyseq_cxt_alloc (){ _rl_keyseq_cxt *cxt; cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt)); cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0; cxt->okey = 0; cxt->ocxt = _rl_kscxt; cxt->childval = 42; /* sentinel value */ return cxt;}void_rl_keyseq_cxt_dispose (cxt) _rl_keyseq_cxt *cxt;{ xfree (cxt);}void_rl_keyseq_chain_dispose (){ _rl_keyseq_cxt *cxt; while (_rl_kscxt) { cxt = _rl_kscxt; _rl_kscxt = _rl_kscxt->ocxt; _rl_keyseq_cxt_dispose (cxt); }}#endifstatic int_rl_subseq_getchar (key) int key;{ int k; if (key == ESC) RL_SETSTATE(RL_STATE_METANEXT); RL_SETSTATE(RL_STATE_MOREINPUT); k = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); if (key == ESC) RL_UNSETSTATE(RL_STATE_METANEXT); return k;}#if defined (READLINE_CALLBACKS)int_rl_dispatch_callback (cxt) _rl_keyseq_cxt *cxt;{ int nkey, r; /* For now */ /* The first time this context is used, we want to read input and dispatch on it. When traversing the chain of contexts back `up', we want to use the value from the next context down. We're simulating recursion using a chain of contexts. */ if ((cxt->flags & KSEQ_DISPATCHED) == 0) { nkey = _rl_subseq_getchar (cxt->okey); if (nkey < 0) { _rl_abort_internal (); return -1; } r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); cxt->flags |= KSEQ_DISPATCHED; } else r = cxt->childval; /* For now */ if (r != -3) /* don't do this if we indicate there will be other matches */ r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); RL_CHECK_SIGNALS (); if (r == 0) /* success! */ { _rl_keyseq_chain_dispose (); RL_UNSETSTATE (RL_STATE_MULTIKEY); return r; } if (r != -3) /* magic value that says we added to the chain */ _rl_kscxt = cxt->ocxt; if (_rl_kscxt) _rl_kscxt->childval = r; if (r != -3) _rl_keyseq_cxt_dispose (cxt); return r;}#endif /* READLINE_CALLBACKS */ /* 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;{ _rl_dispatching_keymap = map; return _rl_dispatch_subseq (key, map, 0);}int_rl_dispatch_subseq (key, map, got_subseq) register int key; Keymap map; int got_subseq;{ int r, newkey; char *macro; rl_command_func_t *func;#if defined (READLINE_CALLBACKS) _rl_keyseq_cxt *cxt;#endif if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { if (map[ESC].type == ISKMAP) { if (RL_ISSTATE (RL_STATE_MACRODEF)) _rl_add_macro_char (ESC); map = FUNCTION_TO_KEYMAP (map, ESC); key = UNMETA (key); rl_key_sequence_length += 2; return (_rl_dispatch (key, map)); } else rl_ding (); return 0; } if (RL_ISSTATE (RL_STATE_MACRODEF)) _rl_add_macro_char (key); r = 0; switch (map[key].type) { case ISFUNC: func = map[key].function; if (func) { /* Special case rl_do_lowercase_version (). */ if (func == rl_do_lowercase_version) return (_rl_dispatch (_rl_to_lower (key), map)); rl_executing_keymap = map; rl_dispatching = 1; RL_SETSTATE(RL_STATE_DISPATCHING); (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); RL_UNSETSTATE(RL_STATE_DISPATCHING); rl_dispatching = 0; /* 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 == 0 && map[key].function != rl_digit_argument) rl_last_func = map[key].function; RL_CHECK_SIGNALS (); } else if (map[ANYOTHERKEY].function) { /* OK, there's no function bound in this map, but there is a shadow function that was overridden when the current keymap was created. Return -2 to note that. */ _rl_unget_char (key); return -2; } else if (got_subseq) { /* Return -1 to note that we're in a subsequence, but we don't have a matching key, nor was one overridden. This means we need to back up the recursion chain and find the last subsequence that is bound to a function. */ _rl_unget_char (key); return -1; } else {#if defined (READLINE_CALLBACKS) RL_UNSETSTATE (RL_STATE_MULTIKEY); _rl_keyseq_chain_dispose ();#endif _rl_abort_internal (); return -1; } break; case ISKMAP: if (map[key].function != 0) {#if defined (VI_MODE) /* The only way this test will be true is if a subsequence has been bound starting with ESC, generally the arrow keys. What we do is check whether there's input in the queue, which there generally will be if an arrow key has been pressed, and, if there's not, just dispatch to (what we assume is) rl_vi_movement_mode right away. This is essentially an input test with a zero timeout. */ if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap && _rl_input_queued (0) == 0) return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));#endif rl_key_sequence_length++; _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key); /* Allocate new context here. Use linked contexts (linked through cxt->ocxt) to simulate recursion */#if defined (READLINE_CALLBACKS) if (RL_ISSTATE (RL_STATE_CALLBACK)) { /* Return 0 only the first time, to indicate success to _rl_callback_read_char. The rest of the time, we're called from _rl_dispatch_callback, so we return -3 to indicate special handling is necessary. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -