📄 readline.c
字号:
int orig_point = rl_point; if (count <= 0) count = 1; while (count--) { while (rl_point && whitespace (the_line[rl_point - 1])) rl_point--; while (rl_point && !whitespace (the_line[rl_point - 1])) rl_point--; } rl_kill_text (orig_point, rl_point); } return 0;}/* Here is C-u doing what Unix does. You don't *have* to use these key-bindings. We have a choice of killing the entire line, or killing from where we are to the start of the line. We choose the latter, because if you are a Unix weenie, then you haven't backspaced into the line at all, and if you aren't, then you know what you are doing. */rl_unix_line_discard (count, key) int count, key;{ if (!rl_point) ding (); else { rl_kill_text (rl_point, 0); rl_point = 0; } return 0;}/* **************************************************************** *//* *//* Commands For Typos *//* *//* **************************************************************** *//* Random and interesting things in here. *//* **************************************************************** *//* *//* Changing Case *//* *//* **************************************************************** *//* The three kinds of things that we know how to do. */#define UpCase 1#define DownCase 2#define CapCase 3static int rl_change_case ();/* Uppercase the word at point. */rl_upcase_word (count, key) int count, key;{ return (rl_change_case (count, UpCase));}/* Lowercase the word at point. */rl_downcase_word (count, key) int count, key;{ return (rl_change_case (count, DownCase));}/* Upcase the first letter, downcase the rest. */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 intrl_change_case (count, op) int count, op;{ register int start = rl_point, end; int state = 0; rl_forward_word (count); end = rl_point; if (count < 0) { int temp = start; start = end; end = temp; } /* We are going to modify some text, so let's prepare to undo it. */ rl_modifying (start, end); for (; start < end; start++) { switch (op) { case UpCase: the_line[start] = to_upper (the_line[start]); break; case DownCase: the_line[start] = to_lower (the_line[start]); break; case CapCase: if (state == 0) { the_line[start] = to_upper (the_line[start]); state = 1; } else { the_line[start] = to_lower (the_line[start]); } if (!pure_alphabetic (the_line[start])) state = 0; break; default: ding (); return -1; } } rl_point = end; return 0;}/* **************************************************************** *//* *//* Transposition *//* *//* **************************************************************** *//* Transpose the words at point. */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); w2_end = rl_point; rl_backward_word (1); w2_beg = rl_point; rl_backward_word (count); w1_beg = rl_point; rl_forward_word (1); 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. */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; if (rl_point > rl_end) rl_point = rl_end; else if (rl_point < 0) rl_point = 0; rl_insert_text (dummy); rl_end_undo_group (); return 0;}/* **************************************************************** *//* *//* Undo, and Undoing *//* *//* **************************************************************** *//* The current undo list for THE_LINE. */UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;/* Remember how to undo something. Concatenate some undos if that seems right. */voidrl_add_undo (what, start, end, text) enum undo_code what; int start, end; char *text;{ UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); temp->what = what; temp->start = start; temp->end = end; temp->text = text; temp->next = rl_undo_list; rl_undo_list = temp;}/* Free the existing undo list. */voidfree_undo_list (){ while (rl_undo_list) { UNDO_LIST *release = rl_undo_list; rl_undo_list = rl_undo_list->next; if (release->what == UNDO_DELETE) free (release->text); free (release); } rl_undo_list = (UNDO_LIST *)NULL;}/* Undo the next thing in the list. Return 0 if there is nothing to undo, or non-zero if there was. */intrl_do_undo (){ UNDO_LIST *release; int waiting_for_begin = 0;undo_thing: if (!rl_undo_list) return (0); doing_an_undo = 1; switch (rl_undo_list->what) { /* Undoing deletes means inserting some text. */ case UNDO_DELETE: rl_point = rl_undo_list->start; rl_insert_text (rl_undo_list->text); free (rl_undo_list->text); break; /* Undoing inserts means deleting some text. */ case UNDO_INSERT: rl_delete_text (rl_undo_list->start, rl_undo_list->end); rl_point = rl_undo_list->start; break; /* Undoing an END means undoing everything 'til we get to a BEGIN. */ case UNDO_END: waiting_for_begin++; break; /* Undoing a BEGIN means that we are done with this group. */ case UNDO_BEGIN: if (waiting_for_begin) waiting_for_begin--; else ding (); break; } doing_an_undo = 0; release = rl_undo_list; rl_undo_list = rl_undo_list->next; free (release); if (waiting_for_begin) goto undo_thing; return (1);}/* Begin a group. Subsequent undos are undone as an atomic operation. */intrl_begin_undo_group (){ rl_add_undo (UNDO_BEGIN, 0, 0, 0); return 0;}/* End an undo group started with rl_begin_undo_group (). */intrl_end_undo_group (){ rl_add_undo (UNDO_END, 0, 0, 0); return 0;}/* Save an undo entry for the text from START to END. */rl_modifying (start, end) int start, end;{ if (start > end) { int t = start; start = end; end = t; } if (start != end) { char *temp = rl_copy_text (start, end); rl_begin_undo_group (); rl_add_undo (UNDO_DELETE, start, end, temp); rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); rl_end_undo_group (); } return 0;}/* Revert the current line to its previous state. */intrl_revert_line (count, key) int count, key;{ if (!rl_undo_list) ding (); else { while (rl_undo_list) rl_do_undo (); } return 0;}/* Do some undoing of things that were done. */intrl_undo_command (count, key) int count, key;{ if (count < 0) return 0; /* Nothing to do. */ while (count) { if (rl_do_undo ()) count--; else { ding (); break; } } return 0;}/* **************************************************************** *//* *//* History Utilities *//* *//* **************************************************************** *//* We already have a history library, and that is what we use to control the history features of readline. However, 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 voidstart_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) return; if (entry->line) free (entry->line); free (entry);}/* Perhaps put back the current line if it has changed. */maybe_replace_line (){ HIST_ENTRY *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, rl_undo_list); free (temp->line); free (temp); } return 0;}/* Put back the saved_line_for_history if there is one. */maybe_unsave_line (){ if (saved_line_for_history) { int line_len; 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. */maybe_save_line (){ if (!saved_line_for_history) { 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. */rl_beginning_of_history (count, key) int count, key;{ return (rl_get_previous_history (1 + where_history ()));}/* Meta-> goes to the end of the history. (The current line). */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. */rl_get_next_history (count, key) int count, key;{ HIST_ENTRY *temp = (HIST_ENTRY *)NULL; if (count < 0) return (rl_get_previous_history (-count)); if (!count) return 0; maybe_replace_line (); while (count) { temp = next_history (); if (!temp) break; --count; } if (!temp) maybe_unsave_line (); else { int line_len; 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);#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -