📄 readline.c
字号:
/* Upcase the first letter, downcase the rest. */
int
rl_capitalize_word (count, key)
int count, key;
{
return (rl_change_case (count, CapCase));
}
/* The meaty function.
Change the case of COUNT words, performing OP on them.
OP is one of UpCase, DownCase, or CapCase.
If a negative argument is given, leave point where it started,
otherwise, leave it where it moves to. */
static int
rl_change_case (count, op)
int count, op;
{
register int start, end;
int inword, c;
start = rl_point;
rl_forward_word (count, 0);
end = rl_point;
if (count < 0)
SWAP (start, end);
/* We are going to modify some text, so let's prepare to undo it. */
rl_modifying (start, end);
for (inword = 0; start < end; start++)
{
c = the_line[start];
switch (op)
{
case UpCase:
the_line[start] = _rl_to_upper (c);
break;
case DownCase:
the_line[start] = _rl_to_lower (c);
break;
case CapCase:
the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
inword = alphabetic (the_line[start]);
break;
default:
ding ();
return -1;
}
}
rl_point = end;
return 0;
}
/* **************************************************************** */
/* */
/* Transposition */
/* */
/* **************************************************************** */
/* Transpose the words at point. */
int
rl_transpose_words (count, key)
int count, key;
{
char *word1, *word2;
int w1_beg, w1_end, w2_beg, w2_end;
int orig_point = rl_point;
if (!count)
return 0;
/* Find the two words. */
rl_forward_word (count, key);
w2_end = rl_point;
rl_backward_word (1, key);
w2_beg = rl_point;
rl_backward_word (count, key);
w1_beg = rl_point;
rl_forward_word (1, key);
w1_end = rl_point;
/* Do some check to make sure that there really are two words. */
if ((w1_beg == w2_beg) || (w2_beg < w1_end))
{
ding ();
rl_point = orig_point;
return -1;
}
/* Get the text of the words. */
word1 = rl_copy_text (w1_beg, w1_end);
word2 = rl_copy_text (w2_beg, w2_end);
/* We are about to do many insertions and deletions. Remember them
as one operation. */
rl_begin_undo_group ();
/* Do the stuff at word2 first, so that we don't have to worry
about word1 moving. */
rl_point = w2_beg;
rl_delete_text (w2_beg, w2_end);
rl_insert_text (word1);
rl_point = w1_beg;
rl_delete_text (w1_beg, w1_end);
rl_insert_text (word2);
/* This is exactly correct since the text before this point has not
changed in length. */
rl_point = w2_end;
/* I think that does it. */
rl_end_undo_group ();
free (word1);
free (word2);
return 0;
}
/* Transpose the characters at point. If point is at the end of the line,
then transpose the characters before point. */
int
rl_transpose_chars (count, key)
int count, key;
{
char dummy[2];
if (!count)
return 0;
if (!rl_point || rl_end < 2)
{
ding ();
return -1;
}
rl_begin_undo_group ();
if (rl_point == rl_end)
{
--rl_point;
count = 1;
}
rl_point--;
dummy[0] = the_line[rl_point];
dummy[1] = '\0';
rl_delete_text (rl_point, rl_point + 1);
rl_point += count;
_rl_fix_point (0);
rl_insert_text (dummy);
rl_end_undo_group ();
return 0;
}
/* **************************************************************** */
/* */
/* Character Searching */
/* */
/* **************************************************************** */
int
_rl_char_search_internal (count, dir, schar)
int count, dir, schar;
{
int pos, inc;
pos = rl_point;
inc = (dir < 0) ? -1 : 1;
while (count)
{
if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
{
ding ();
return -1;
}
pos += inc;
do
{
if (rl_line_buffer[pos] == schar)
{
count--;
if (dir < 0)
rl_point = (dir == BTO) ? pos + 1 : pos;
else
rl_point = (dir == FTO) ? pos - 1 : pos;
break;
}
}
while ((dir < 0) ? pos-- : ++pos < rl_end);
}
return (0);
}
/* Search COUNT times for a character read from the current input stream.
FDIR is the direction to search if COUNT is non-negative; otherwise
the search goes in BDIR. */
static int
_rl_char_search (count, fdir, bdir)
int count, fdir, bdir;
{
int c;
c = rl_read_key ();
if (count < 0)
return (_rl_char_search_internal (-count, bdir, c));
else
return (_rl_char_search_internal (count, fdir, c));
}
int
rl_char_search (count, key)
int count, key;
{
return (_rl_char_search (count, FFIND, BFIND));
}
int
rl_backward_char_search (count, key)
int count, key;
{
return (_rl_char_search (count, BFIND, FFIND));
}
/* **************************************************************** */
/* */
/* History Utilities */
/* */
/* **************************************************************** */
/* We already have a history library, and that is what we use to control
the history features of readline. This is our local interface to
the history mechanism. */
/* While we are editing the history, this is the saved
version of the original line. */
HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL;
/* Set the history pointer back to the last entry in the history. */
static void
start_using_history ()
{
using_history ();
if (saved_line_for_history)
_rl_free_history_entry (saved_line_for_history);
saved_line_for_history = (HIST_ENTRY *)NULL;
}
/* Free the contents (and containing structure) of a HIST_ENTRY. */
void
_rl_free_history_entry (entry)
HIST_ENTRY *entry;
{
if (entry == 0)
return;
if (entry->line)
free (entry->line);
free (entry);
}
/* Perhaps put back the current line if it has changed. */
int
maybe_replace_line ()
{
HIST_ENTRY *temp;
temp = current_history ();
/* If the current line has changed, save the changes. */
if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
{
temp = replace_history_entry (where_history (), the_line, (histdata_t)rl_undo_list);
free (temp->line);
free (temp);
}
return 0;
}
/* Put back the saved_line_for_history if there is one. */
int
maybe_unsave_line ()
{
int line_len;
if (saved_line_for_history)
{
line_len = strlen (saved_line_for_history->line);
if (line_len >= rl_line_buffer_len)
rl_extend_line_buffer (line_len);
strcpy (the_line, saved_line_for_history->line);
rl_undo_list = (UNDO_LIST *)saved_line_for_history->data;
_rl_free_history_entry (saved_line_for_history);
saved_line_for_history = (HIST_ENTRY *)NULL;
rl_end = rl_point = strlen (the_line);
}
else
ding ();
return 0;
}
/* Save the current line in saved_line_for_history. */
int
maybe_save_line ()
{
if (saved_line_for_history == 0)
{
saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
saved_line_for_history->line = savestring (the_line);
saved_line_for_history->data = (char *)rl_undo_list;
}
return 0;
}
/* **************************************************************** */
/* */
/* History Commands */
/* */
/* **************************************************************** */
/* Meta-< goes to the start of the history. */
int
rl_beginning_of_history (count, key)
int count, key;
{
return (rl_get_previous_history (1 + where_history (), key));
}
/* Meta-> goes to the end of the history. (The current line). */
int
rl_end_of_history (count, key)
int count, key;
{
maybe_replace_line ();
using_history ();
maybe_unsave_line ();
return 0;
}
/* Move down to the next history line. */
int
rl_get_next_history (count, key)
int count, key;
{
HIST_ENTRY *temp;
int line_len;
if (count < 0)
return (rl_get_previous_history (-count, key));
if (count == 0)
return 0;
maybe_replace_line ();
temp = (HIST_ENTRY *)NULL;
while (count)
{
temp = next_history ();
if (!temp)
break;
--count;
}
if (temp == 0)
maybe_unsave_line ();
else
{
line_len = strlen (temp->line);
if (line_len >= rl_line_buffer_len)
rl_extend_line_buffer (line_len);
strcpy (the_line, temp->line);
rl_undo_list = (UNDO_LIST *)temp->data;
rl_end = rl_point = strlen (the_line);
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
rl_point = 0;
#endif /* VI_MODE */
}
return 0;
}
/* Get the previous item out of our interactive history, making it the current
line. If there is no previous history, just ding. */
int
rl_get_previous_history (count, key)
int count, key;
{
HIST_ENTRY *old_temp, *temp;
int line_len;
if (count < 0)
return (rl_get_next_history (-count, key));
if (count == 0)
return 0;
/* If we don't have a line saved, then save this one. */
maybe_save_line ();
/* If the current line has changed, save the changes. */
maybe_replace_line ();
temp = old_temp = (HIST_ENTRY *)NULL;
while (count)
{
temp = previous_history ();
if (temp == 0)
break;
old_temp = temp;
--count;
}
/* If there was a large argument, and we moved back to the start of the
history, that is not an error. So use the last value found. */
if (!temp && old_temp)
temp = old_temp;
if (temp == 0)
ding ();
else
{
line_len = strlen (temp->line);
if (line_len >= rl_line_buffer_len)
rl_extend_line_buffer (line_len);
strcpy (the_line, temp->line);
rl_undo_list = (UNDO_LIST *)temp->data;
rl_end = rl_point = line_len;
#if defined (VI_MODE)
if (rl_editing_mode == vi_mode)
rl_point = 0;
#endif /* VI_MODE */
}
return 0;
}
/* **************************************************************** */
/* */
/* The Mark and the Region. */
/* */
/* **************************************************************** */
/* Set the mark at POSITION. */
int
_rl_set_mark_at_pos (position)
int position;
{
if (position > rl_end)
return -1;
rl_mark = position;
return 0;
}
/* A bindable command to set the mark. */
int
rl_set_mark (count, key)
int count, key;
{
return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
}
/* Exchange the position of mark and point. */
int
rl_exchange_point_and_mark (count, key)
int count, key;
{
if (rl_mark > rl_end)
rl_mark = -1;
if (rl_mark == -1)
{
ding ();
return -1;
}
else
SWAP (rl_point, rl_mark);
return 0;
}
/* **************************************************************** */
/* */
/* Editing Modes */
/* */
/* **************************************************************** */
/* How to toggle back and forth between editing modes. */
int
rl_vi_editing_mode (count, key)
int count, key;
{
#if defined (VI_MODE)
rl_editing_mode = vi_mode;
rl_vi_insertion_mode (1, key);
#endif /* VI_MODE */
return 0;
}
int
rl_emacs_editing_mode (count, key)
int count, key;
{
rl_editing_mode = emacs_mode;
_rl_keymap = emacs_standard_keymap;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -