📄 vi_mode.c
字号:
else { /* Just skip over characters neither upper nor lower case. */ rl_forward (1, c); continue; } /* Vi is kind of strange here. */ if (c) { rl_begin_undo_group (); rl_delete (1, c); rl_insert (1, c); rl_end_undo_group (); rl_vi_check (); } else rl_forward (1, c); } return (0);}intrl_vi_put (count, key) int count, key;{ if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) rl_point++; rl_yank (1, key); rl_backward (1, key); return (0);}intrl_vi_check (){ if (rl_point && rl_point == rl_end) rl_point--; return (0);}intrl_vi_column (count, key) int count, key;{ if (count > rl_end) rl_end_of_line (1, key); else rl_point = count - 1; return (0);}intrl_vi_domove (key, nextkey) int key, *nextkey;{ int c, save; int old_end; rl_mark = rl_point; c = rl_read_key (); *nextkey = c; if (!member (c, vi_motion)) { if (_rl_digit_p (c)) { save = rl_numeric_arg; rl_numeric_arg = _rl_digit_value (c); rl_digit_loop1 (); rl_numeric_arg *= save; c = rl_read_key (); /* real command */ *nextkey = c; } else if (key == c && (key == 'd' || key == 'y' || key == 'c')) { rl_mark = rl_end; rl_beg_of_line (1, c); _rl_vi_last_motion = c; return (0); } else return (-1); } _rl_vi_last_motion = c; /* Append a blank character temporarily so that the motion routines work right at the end of the line. */ old_end = rl_end; rl_line_buffer[rl_end++] = ' '; rl_line_buffer[rl_end] = '\0'; _rl_dispatch (c, _rl_keymap); /* Remove the blank that we added. */ rl_end = old_end; rl_line_buffer[rl_end] = '\0'; if (rl_point > rl_end) rl_point = rl_end; /* No change in position means the command failed. */ if (rl_mark == rl_point) return (-1); /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next word. If we are not at the end of the line, and we are on a non-whitespace character, move back one (presumably to whitespace). */ if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && !whitespace (rl_line_buffer[rl_point])) rl_point--; /* If cw or cW, back up to the end of a word, so the behaviour of ce or cE is the actual result. Brute-force, no subtlety. */ if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) { /* Don't move farther back than where we started. */ while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) rl_point--; /* Posix.2 says that if cw or cW moves the cursor towards the end of the line, the character under the cursor should be deleted. */ if (rl_point == rl_mark) rl_point++; else { /* Move past the end of the word so that the kill doesn't remove the last letter of the previous word. Only do this if we are not at the end of the line. */ if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) rl_point++; } } if (rl_mark < rl_point) exchange (rl_point, rl_mark); return (0);}/* A simplified loop for vi. Don't dispatch key at end. Don't recognize minus sign? */static intrl_digit_loop1 (){ int key, c; while (1) { rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); 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 (_rl_digit_p (c)) { if (rl_explicit_arg) rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); else rl_numeric_arg = _rl_digit_value (c); rl_explicit_arg = 1; } else { rl_clear_message (); rl_stuff_char (key); break; } } return (0);}intrl_vi_delete_to (count, key) int count, key;{ int c; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); else if (vi_redoing) rl_stuff_char (_rl_vi_last_motion); if (rl_vi_domove (key, &c)) { ding (); return -1; } /* These are the motion commands that do not require adjusting the mark. */ if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) rl_mark++; rl_kill_text (rl_point, rl_mark); return (0);}intrl_vi_change_to (count, key) int count, key;{ int c, start_pos; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); else if (vi_redoing) rl_stuff_char (_rl_vi_last_motion); start_pos = rl_point; if (rl_vi_domove (key, &c)) { ding (); return -1; } /* These are the motion commands that do not require adjusting the mark. c[wW] are handled by special-case code in rl_vi_domove(), and already leave the mark at the correct location. */ if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) rl_mark++; /* The cursor never moves with c[wW]. */ if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) rl_point = start_pos; if (vi_redoing) { if (vi_insert_buffer && *vi_insert_buffer) rl_begin_undo_group (); rl_delete_text (rl_point, rl_mark); if (vi_insert_buffer && *vi_insert_buffer) { rl_insert_text (vi_insert_buffer); rl_end_undo_group (); } } else { rl_begin_undo_group (); /* to make the `u' command work */ rl_kill_text (rl_point, rl_mark); /* `C' does not save the text inserted for undoing or redoing. */ if (_rl_uppercase_p (key) == 0) _rl_vi_doing_insert = 1; _rl_vi_set_last (key, count, rl_arg_sign); rl_vi_insertion_mode (1, key); } return (0);}intrl_vi_yank_to (count, key) int count, key;{ int c, save = rl_point; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); if (rl_vi_domove (key, &c)) { ding (); return -1; } /* These are the motion commands that do not require adjusting the mark. */ if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) rl_mark++; rl_begin_undo_group (); rl_kill_text (rl_point, rl_mark); rl_end_undo_group (); rl_do_undo (); rl_point = save; return (0);}intrl_vi_delete (count, key) int count, key;{ int end; if (rl_end == 0) { ding (); return -1; } end = rl_point + count; if (end >= rl_end) end = rl_end; rl_kill_text (rl_point, end); if (rl_point > 0 && rl_point == rl_end) rl_backward (1, key); return (0);}intrl_vi_back_to_indent (count, key) int count, key;{ rl_beg_of_line (1, key); while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) rl_point++; return (0);}intrl_vi_first_print (count, key) int count, key;{ return (rl_vi_back_to_indent (1, key));}intrl_vi_char_search (count, key) int count, key;{ static char target; static int orig_dir, dir; if (key == ';' || key == ',') dir = key == ';' ? orig_dir : -orig_dir; else { if (vi_redoing) target = _rl_vi_last_search_char; else _rl_vi_last_search_char = target = (*rl_getc_function) (rl_instream); switch (key) { case 't': orig_dir = dir = FTO; break; case 'T': orig_dir = dir = BTO; break; case 'f': orig_dir = dir = FFIND; break; case 'F': orig_dir = dir = BFIND; break; } } return (_rl_char_search_internal (count, dir, target));}/* Match brackets */intrl_vi_match (ignore, key) int ignore, key;{ int count = 1, brack, pos; pos = rl_point; if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) { while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && rl_point < rl_end - 1) rl_forward (1, key); if (brack <= 0) { rl_point = pos; ding (); return -1; } } pos = rl_point; if (brack < 0) { while (count) { if (--pos >= 0) { int b = rl_vi_bracktype (rl_line_buffer[pos]); if (b == -brack) count--; else if (b == brack) count++; } else { ding (); return -1; } } } else { /* brack > 0 */ while (count) { if (++pos < rl_end) { int b = rl_vi_bracktype (rl_line_buffer[pos]); if (b == -brack) count--; else if (b == brack) count++; } else { ding (); return -1; } } } rl_point = pos; return (0);}intrl_vi_bracktype (c) int c;{ switch (c) { case '(': return 1; case ')': return -1; case '[': return 2; case ']': return -2; case '{': return 3; case '}': return -3; default: return 0; }}intrl_vi_change_char (count, key) int count, key;{ int c; if (vi_redoing) c = _rl_vi_last_replacement; else _rl_vi_last_replacement = c = (*rl_getc_function) (rl_instream); if (c == '\033' || c == CTRL ('C')) return -1; while (count-- && rl_point < rl_end) { rl_begin_undo_group (); rl_delete (1, c); rl_insert (1, c); if (count == 0) rl_backward (1, c); rl_end_undo_group (); } return (0);}intrl_vi_subst (count, key) int count, key;{ rl_begin_undo_group (); if (_rl_uppercase_p (key)) { rl_beg_of_line (1, key); rl_kill_line (1, key); } else rl_delete_text (rl_point, rl_point+count); rl_end_undo_group (); _rl_vi_set_last (key, count, rl_arg_sign); if (vi_redoing) { int o = _rl_doing_an_undo; _rl_doing_an_undo = 1; if (vi_insert_buffer && *vi_insert_buffer) rl_insert_text (vi_insert_buffer); _rl_doing_an_undo = o; } else { rl_begin_undo_group (); _rl_vi_doing_insert = 1; rl_vi_insertion_mode (1, key); } return (0);}intrl_vi_overstrike (count, key) int count, key;{ int i; if (_rl_vi_doing_insert == 0) { _rl_vi_doing_insert = 1; rl_begin_undo_group (); } for (i = 0; i < count; i++) { vi_replace_count++; rl_begin_undo_group (); if (rl_point < rl_end) { rl_delete (1, key); rl_insert (1, key); } else rl_insert (1, key); rl_end_undo_group (); } return (0);}intrl_vi_overstrike_delete (count, key) int count, key;{ int i, s; for (i = 0; i < count; i++) { if (vi_replace_count == 0) { ding (); break; } s = rl_point; if (rl_do_undo ()) vi_replace_count--; if (rl_point == s) rl_backward (1, key); } if (vi_replace_count == 0 && _rl_vi_doing_insert) { rl_end_undo_group (); rl_do_undo (); _rl_vi_doing_insert = 0; } return (0);}intrl_vi_replace (count, key) int count, key;{ int i; vi_replace_count = 0; if (!vi_replace_map) { vi_replace_map = rl_make_bare_keymap (); for (i = ' '; i < KEYMAP_SIZE; i++) vi_replace_map[i].function = rl_vi_overstrike; vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; vi_replace_map[ESC].function = rl_vi_movement_mode; vi_replace_map[RETURN].function = rl_newline; vi_replace_map[NEWLINE].function = rl_newline; /* If the normal vi insertion keymap has ^H bound to erase, do the same here. Probably should remove the assignment to RUBOUT up there, but I don't think it will make a difference in real life. */ if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && vi_insertion_keymap[CTRL ('H')].function == rl_rubout) vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; } _rl_keymap = vi_replace_map; return (0);}#if 0/* Try to complete the word we are standing on or the word that ends with the previous character. A space matches everything. Word delimiters are space and ;. */intrl_vi_possible_completions(){ int save_pos = rl_point; if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') { while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') rl_point++; } else if (rl_line_buffer[rl_point - 1] == ';') { ding (); return (0); } rl_possible_completions (); rl_point = save_pos; return (0);}#endif/* Functions to save and restore marks. */intrl_vi_set_mark (count, key) int count, key;{ int ch; ch = rl_read_key (); if (_rl_lowercase_p (ch) == 0) { ding (); return -1; } ch -= 'a'; vi_mark_chars[ch] = rl_point; return 0;}intrl_vi_goto_mark (count, key) int count, key;{ int ch; ch = rl_read_key (); if (ch == '`') { rl_point = rl_mark; return 0; } else if (_rl_lowercase_p (ch) == 0) { ding (); return -1; } ch -= 'a'; if (vi_mark_chars[ch] == -1) { ding (); return -1; } rl_point = vi_mark_chars[ch]; return 0;}#endif /* VI_MODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -