📄 readline.c
字号:
return (_rl_dispatch (_rl_to_lower (key), map));
rl_executing_keymap = map;
#if 0
_rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available ();
#endif
rl_dispatching = 1;
r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
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 && map[key].function != rl_digit_argument)
rl_last_func = map[key].function;
}
else
{
_rl_abort_internal ();
return -1;
}
break;
case ISKMAP:
if (map[key].function != (Function *)NULL)
{
rl_key_sequence_length++;
newkey = rl_read_key ();
r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
}
else
{
_rl_abort_internal ();
return -1;
}
break;
case ISMACR:
if (map[key].function != (Function *)NULL)
{
macro = savestring ((char *)map[key].function);
_rl_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);
}
/* **************************************************************** */
/* */
/* Initializations */
/* */
/* **************************************************************** */
/* Initialize readline (and terminal if not already). */
int
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_init_line_state ();
/* 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;
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
_rl_vi_initialize_line ();
#endif
return 0;
}
#if 0
#if defined (__EMX__)
static void
_emx_build_environ ()
{
TIB *tibp;
PIB *pibp;
char *t, **tp;
int c;
DosGetInfoBlocks (&tibp, &pibp);
t = pibp->pib_pchenv;
for (c = 1; *t; c++)
t += strlen (t) + 1;
tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
t = pibp->pib_pchenv;
while (*t)
{
*tp++ = t;
t += strlen (t) + 1;
}
*tp = 0;
}
#endif /* __EMX__ */
#endif
/* Initialize the entire state of the world. */
static void
readline_initialize_everything ()
{
#if 0
#if defined (__EMX__)
if (environ == 0)
_emx_build_environ ();
#endif
#endif
/* Find out if we are running in Emacs. */
running_in_emacs = get_env_value ("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 _rl_in_stream and _rl_out_stream immediately. These values
may change, but they may also be used before readline_internal ()
is called. */
_rl_in_stream = rl_instream;
_rl_out_stream = rl_outstream;
/* Allocate data structures. */
if (rl_line_buffer == 0)
rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
/* Initialize the terminal interface. */
_rl_init_terminal_io ((char *)NULL);
/* Bind tty characters to readline functions. */
readline_default_bindings ();
/* Initialize the function names. */
rl_initialize_funmap ();
/* Decide whether we should automatically go into eight-bit mode. */
_rl_init_eightbit ();
/* Read in the init file. */
rl_read_init_file ((char *)NULL);
/* XXX */
if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
{
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 ();
/* Enable the meta key, if this terminal has one. */
if (_rl_enable_meta)
_rl_enable_meta_key ();
/* 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 void
readline_default_bindings ()
{
rltty_set_default_bindings (_rl_keymap);
}
static void
bind_arrow_keys_internal ()
{
Function *f;
#if defined (__MSDOS__) && 0
f = rl_function_of_keyseq ("\033[0A", _rl_keymap, (int *)NULL);
if (!f || f == rl_do_lowercase_version)
{
_rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
_rl_bind_if_unbound ("\033[0B", rl_get_next_history);
_rl_bind_if_unbound ("\033[0C", rl_forward);
_rl_bind_if_unbound ("\033[0D", rl_backward);
}
#endif
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 void
bind_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 int
rl_digit_loop ()
{
int key, c, sawminus, sawdigits;
rl_save_prompt ();
sawminus = sawdigits = 0;
while (1)
{
if (rl_numeric_arg > 1000000)
{
sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
ding ();
rl_restore_prompt ();
rl_clear_message ();
return 1;
}
rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
key = c = rl_read_key ();
/* If we see a key bound to `universal-argument' after seeing digits,
it ends the argument but is otherwise ignored. */
if (_rl_keymap[c].type == ISFUNC &&
_rl_keymap[c].function == rl_universal_argument)
{
if (sawdigits == 0)
{
rl_numeric_arg *= 4;
continue;
}
else
{
key = rl_read_key ();
rl_restore_prompt ();
rl_clear_message ();
return (_rl_dispatch (key, _rl_keymap));
}
}
c = UNMETA (c);
if (_rl_digit_p (c))
{
rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
sawdigits = rl_explicit_arg = 1;
}
else if (c == '-' && rl_explicit_arg == 0)
{
rl_numeric_arg = sawminus = 1;
rl_arg_sign = -1;
}
else
{
/* Make M-- command equivalent to M--1 command. */
if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
rl_explicit_arg = 1;
rl_restore_prompt ();
rl_clear_message ();
return (_rl_dispatch (key, _rl_keymap));
}
}
return 0;
}
/* Add the current digit to the argument in progress. */
int
rl_digit_argument (ignore, key)
int ignore, key;
{
rl_pending_input = key;
return (rl_digit_loop ());
}
/* What to do when you abort reading an argument. */
int
rl_discard_argument ()
{
ding ();
rl_clear_message ();
_rl_init_argument ();
return 0;
}
/* Create a default argument. */
int
_rl_init_argument ()
{
rl_numeric_arg = rl_arg_sign = 1;
rl_explicit_arg = 0;
return 0;
}
/* C-u, universal argument. Multiply the current argument by 4.
Read a key. If the key has nothing to do with arguments, then
dispatch on it. If the key is the abort character then abort. */
int
rl_universal_argument (count, key)
int count, key;
{
rl_numeric_arg *= 4;
return (rl_digit_loop ());
}
/* **************************************************************** */
/* */
/* Insert and Delete */
/* */
/* **************************************************************** */
/* Insert a string of text into the line at point. This is the only
way that you should do insertion. rl_insert () calls this
function. */
int
rl_insert_text (string)
char *string;
{
register int i, l = strlen (string);
if (rl_end + l >= rl_line_buffer_len)
rl_extend_line_buffer (rl_end + l);
for (i = rl_end; i >= rl_point; i--)
the_line[i + l] = the_line[i];
strncpy (the_line + rl_point, string, l);
/* Remember how to undo this if we aren't undoing something. */
if (!_rl_doing_an_undo)
{
/* If possible and desirable, concatenate the undos. */
if ((l == 1) &&
rl_undo_list &&
(rl_undo_list->what == UNDO_INSERT) &&
(rl_undo_list->end == rl_point) &&
(rl_undo_list->end - rl_undo_list->start < 20))
rl_undo_list->end++;
else
rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
}
rl_point += l;
rl_end += l;
the_line[rl_end] = '\0';
return l;
}
/* Delete the string between FROM and TO. FROM is
inclusive, TO is not. */
int
rl_delete_text (from, to)
int from, to;
{
register char *text;
register int diff, i;
/* Fix it if the caller is confused. */
if (from > to)
SWAP (from, to);
/* fix boundaries */
if (to > rl_end)
{
to = rl_end;
if (from > to)
from = to;
}
text = rl_copy_text (from, to);
/* Some versions of strncpy() can't handle overlapping arguments. */
diff = to - from;
for (i = from; i < rl_end - diff; i++)
the_line[i] = the_line[i + diff];
/* Remember how to undo this delete. */
if (_rl_doing_an_undo == 0)
rl_add_undo (UNDO_DELETE, from, to, text);
else
free (text);
rl_end -= diff;
the_line[rl_end] = '\0';
return (diff);
}
/* Fix up point so that it is within the line boundaries after killing
text. If FIX_MARK_TOO is non-zero, the mark is forced within line
boundaries also. */
#define _RL_FIX_POINT(x) \
do { \
if (x > rl_end) \
x = rl_end; \
else if (x < 0) \
x = 0; \
} while (0)
void
_rl_fix_point (fix_mark_too)
int fix_mark_too;
{
_RL_FIX_POINT (rl_point);
if (fix_mark_too)
_RL_FIX_POINT (rl_mark);
}
#undef _RL_FIX_POINT
void
_rl_replace_text (text, start, end)
char *text;
int start, end;
{
rl_begin_undo_group ();
rl_delete_text (start, end + 1);
rl_point = start;
rl_insert_text (text);
rl_end_undo_group ();
}
/* **************************************************************** */
/* */
/* Readline character functions */
/* */
/* **************************************************************** */
/* This is not a gap editor, just a stupid line input routine. No hair
is involved in writing any of the functions, and none should be. */
/* Note that:
rl_end is the place in the string that we would place '\0';
i.e., it is always safe to place '\0' there.
rl_point is the place in the string where the cursor is. Sometimes
this is the same as rl_end.
Any command that is called interactively receives two arguments.
The first is a count: the numeric arg pased to this command.
The second is the key which invoked this command.
*/
/* **************************************************************** */
/* */
/* Movement Commands */
/* */
/* **************************************************************** */
/* Note that if you `optimize' the display for these functions, you cannot
use said functions in other functions which do not do optimizing display.
I.e., you will have to update the data base for rl_redisplay, and you
might as well let rl_redisplay do that job. */
/* Move forward COUNT characters. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -