vi_mode.c (125665) | vi_mode.c (136759) |
---|---|
1/* $FreeBSD: head/contrib/libreadline/vi_mode.c 125665 2004-02-10 20:17:58Z ache $ */ | 1/* $FreeBSD: head/contrib/libreadline/vi_mode.c 136759 2004-10-21 20:10:14Z peter $ */ 2 |
2/* vi_mode.c -- A vi emulation mode for Bash. 3 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ 4 | 3/* vi_mode.c -- A vi emulation mode for Bash. 4 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ 5 |
5/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. | 6/* Copyright (C) 1987-2004 Free Software Foundation, Inc. |
6 7 This file is part of the GNU Readline Library, a library for 8 reading lines of text with interactive input and history editing. 9 10 The GNU Readline Library is free software; you can redistribute it 11 and/or modify it under the terms of the GNU General Public License 12 as published by the Free Software Foundation; either version 2, or 13 (at your option) any later version. --- 45 unchanged lines hidden (view full) --- 59 60#include "rlprivate.h" 61#include "xmalloc.h" 62 63#ifndef member 64#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 65#endif 66 | 7 8 This file is part of the GNU Readline Library, a library for 9 reading lines of text with interactive input and history editing. 10 11 The GNU Readline Library is free software; you can redistribute it 12 and/or modify it under the terms of the GNU General Public License 13 as published by the Free Software Foundation; either version 2, or 14 (at your option) any later version. --- 45 unchanged lines hidden (view full) --- 60 61#include "rlprivate.h" 62#include "xmalloc.h" 63 64#ifndef member 65#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 66#endif 67 |
68int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ 69 |
|
67/* Non-zero means enter insertion mode. */ 68static int _rl_vi_doing_insert; 69 70/* Command keys which do movement for xxx_to commands. */ 71static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; 72 73/* Keymap used for vi replace characters. Created dynamically since 74 rarely used. */ --- 4 unchanged lines hidden (view full) --- 79 80/* If non-zero, we have text inserted after a c[motion] command that put 81 us implicitly into insert mode. Some people want this text to be 82 attached to the command so that it is `redoable' with `.'. */ 83static int vi_continued_command; 84static char *vi_insert_buffer; 85static int vi_insert_buffer_size; 86 | 70/* Non-zero means enter insertion mode. */ 71static int _rl_vi_doing_insert; 72 73/* Command keys which do movement for xxx_to commands. */ 74static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; 75 76/* Keymap used for vi replace characters. Created dynamically since 77 rarely used. */ --- 4 unchanged lines hidden (view full) --- 82 83/* If non-zero, we have text inserted after a c[motion] command that put 84 us implicitly into insert mode. Some people want this text to be 85 attached to the command so that it is `redoable' with `.'. */ 86static int vi_continued_command; 87static char *vi_insert_buffer; 88static int vi_insert_buffer_size; 89 |
87static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ | |
88static int _rl_vi_last_repeat = 1; 89static int _rl_vi_last_arg_sign = 1; 90static int _rl_vi_last_motion; 91#if defined (HANDLE_MULTIBYTE) 92static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; 93#else 94static int _rl_vi_last_search_char; 95#endif --- 35 unchanged lines hidden (view full) --- 131_rl_vi_set_last (key, repeat, sign) 132 int key, repeat, sign; 133{ 134 _rl_vi_last_command = key; 135 _rl_vi_last_repeat = repeat; 136 _rl_vi_last_arg_sign = sign; 137} 138 | 90static int _rl_vi_last_repeat = 1; 91static int _rl_vi_last_arg_sign = 1; 92static int _rl_vi_last_motion; 93#if defined (HANDLE_MULTIBYTE) 94static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; 95#else 96static int _rl_vi_last_search_char; 97#endif --- 35 unchanged lines hidden (view full) --- 133_rl_vi_set_last (key, repeat, sign) 134 int key, repeat, sign; 135{ 136 _rl_vi_last_command = key; 137 _rl_vi_last_repeat = repeat; 138 _rl_vi_last_arg_sign = sign; 139} 140 |
141/* A convenience function that calls _rl_vi_set_last to save the last command 142 information and enters insertion mode. */ 143void 144rl_vi_start_inserting (key, repeat, sign) 145 int key, repeat, sign; 146{ 147 _rl_vi_set_last (key, repeat, sign); 148 rl_vi_insertion_mode (1, key); 149} 150 |
|
139/* Is the command C a VI mode text modification command? */ 140int 141_rl_vi_textmod_command (c) 142 int c; 143{ 144 return (member (c, vi_textmod)); 145} 146 --- 110 unchanged lines hidden (view full) --- 257/* Do a vi style search. */ 258int 259rl_vi_search (count, key) 260 int count, key; 261{ 262 switch (key) 263 { 264 case '?': | 151/* Is the command C a VI mode text modification command? */ 152int 153_rl_vi_textmod_command (c) 154 int c; 155{ 156 return (member (c, vi_textmod)); 157} 158 --- 110 unchanged lines hidden (view full) --- 269/* Do a vi style search. */ 270int 271rl_vi_search (count, key) 272 int count, key; 273{ 274 switch (key) 275 { 276 case '?': |
277 _rl_free_saved_history_line (); |
|
265 rl_noninc_forward_search (count, key); 266 break; 267 268 case '/': | 278 rl_noninc_forward_search (count, key); 279 break; 280 281 case '/': |
282 _rl_free_saved_history_line (); |
|
269 rl_noninc_reverse_search (count, key); 270 break; 271 272 default: 273 rl_ding (); 274 break; 275 } 276 return (0); --- 16 unchanged lines hidden (view full) --- 293 else if (key == '=') 294 rl_complete_internal ('?'); /* List possible completions. */ 295 else if (key == '\\') 296 rl_complete_internal (TAB); /* Standard Readline completion. */ 297 else 298 rl_complete (0, key); 299 300 if (key == '*' || key == '\\') | 283 rl_noninc_reverse_search (count, key); 284 break; 285 286 default: 287 rl_ding (); 288 break; 289 } 290 return (0); --- 16 unchanged lines hidden (view full) --- 307 else if (key == '=') 308 rl_complete_internal ('?'); /* List possible completions. */ 309 else if (key == '\\') 310 rl_complete_internal (TAB); /* Standard Readline completion. */ 311 else 312 rl_complete (0, key); 313 314 if (key == '*' || key == '\\') |
301 { 302 _rl_vi_set_last (key, 1, rl_arg_sign); 303 rl_vi_insertion_mode (1, key); 304 } | 315 rl_vi_start_inserting (key, 1, rl_arg_sign); 316 |
305 return (0); 306} 307 308/* Tilde expansion for vi mode. */ 309int 310rl_vi_tilde_expand (ignore, key) 311 int ignore, key; 312{ 313 rl_tilde_expand (0, key); | 317 return (0); 318} 319 320/* Tilde expansion for vi mode. */ 321int 322rl_vi_tilde_expand (ignore, key) 323 int ignore, key; 324{ 325 rl_tilde_expand (0, key); |
314 _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ 315 rl_vi_insertion_mode (1, key); | 326 rl_vi_start_inserting (key, 1, rl_arg_sign); |
316 return (0); 317} 318 319/* Previous word in vi mode. */ 320int 321rl_vi_prev_word (count, key) 322 int count, key; 323{ --- 101 unchanged lines hidden (view full) --- 425{ 426 while (count-- && rl_point < (rl_end - 1)) 427 { 428 if (!whitespace (rl_line_buffer[rl_point])) 429 rl_point++; 430 431 /* Move to the next non-whitespace character (to the start of the 432 next word). */ | 327 return (0); 328} 329 330/* Previous word in vi mode. */ 331int 332rl_vi_prev_word (count, key) 333 int count, key; 334{ --- 101 unchanged lines hidden (view full) --- 436{ 437 while (count-- && rl_point < (rl_end - 1)) 438 { 439 if (!whitespace (rl_line_buffer[rl_point])) 440 rl_point++; 441 442 /* Move to the next non-whitespace character (to the start of the 443 next word). */ |
433 while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])); | 444 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 445 rl_point++; |
434 435 if (rl_point && rl_point < rl_end) 436 { 437 /* Skip whitespace. */ 438 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 439 rl_point++; 440 441 /* Skip until whitespace. */ --- 194 unchanged lines hidden (view full) --- 636 on absolute indices into the line which may change (though they 637 probably will not). */ 638 _rl_vi_doing_insert = 0; 639 _rl_vi_save_insert (rl_undo_list->next); 640 vi_continued_command = 1; 641 } 642 else 643 { | 446 447 if (rl_point && rl_point < rl_end) 448 { 449 /* Skip whitespace. */ 450 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 451 rl_point++; 452 453 /* Skip until whitespace. */ --- 194 unchanged lines hidden (view full) --- 648 on absolute indices into the line which may change (though they 649 probably will not). */ 650 _rl_vi_doing_insert = 0; 651 _rl_vi_save_insert (rl_undo_list->next); 652 vi_continued_command = 1; 653 } 654 else 655 { |
644 if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list) | 656 if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list) |
645 _rl_vi_save_insert (rl_undo_list); 646 /* XXX - Other keys probably need to be checked. */ 647 else if (_rl_vi_last_key_before_insert == 'C') 648 rl_end_undo_group (); 649 while (_rl_undo_group_level > 0) 650 rl_end_undo_group (); 651 vi_continued_command = 0; 652 } --- 24 unchanged lines hidden (view full) --- 677/* Change the case of the next COUNT characters. */ 678#if defined (HANDLE_MULTIBYTE) 679static int 680_rl_vi_change_mbchar_case (count) 681 int count; 682{ 683 wchar_t wc; 684 char mb[MB_LEN_MAX+1]; | 657 _rl_vi_save_insert (rl_undo_list); 658 /* XXX - Other keys probably need to be checked. */ 659 else if (_rl_vi_last_key_before_insert == 'C') 660 rl_end_undo_group (); 661 while (_rl_undo_group_level > 0) 662 rl_end_undo_group (); 663 vi_continued_command = 0; 664 } --- 24 unchanged lines hidden (view full) --- 689/* Change the case of the next COUNT characters. */ 690#if defined (HANDLE_MULTIBYTE) 691static int 692_rl_vi_change_mbchar_case (count) 693 int count; 694{ 695 wchar_t wc; 696 char mb[MB_LEN_MAX+1]; |
685 int mblen; | 697 int mblen, p; |
686 mbstate_t ps; 687 688 memset (&ps, 0, sizeof (mbstate_t)); 689 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) 690 count--; 691 while (count-- && rl_point < rl_end) 692 { 693 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); --- 6 unchanged lines hidden (view full) --- 700 /* Just skip over chars neither upper nor lower case */ 701 rl_forward_char (1, 0); 702 continue; 703 } 704 705 /* Vi is kind of strange here. */ 706 if (wc) 707 { | 698 mbstate_t ps; 699 700 memset (&ps, 0, sizeof (mbstate_t)); 701 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) 702 count--; 703 while (count-- && rl_point < rl_end) 704 { 705 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); --- 6 unchanged lines hidden (view full) --- 712 /* Just skip over chars neither upper nor lower case */ 713 rl_forward_char (1, 0); 714 continue; 715 } 716 717 /* Vi is kind of strange here. */ 718 if (wc) 719 { |
708 mblen = wctomb (mb, wc); | 720 p = rl_point; 721 mblen = wcrtomb (mb, wc, &ps); |
709 if (mblen >= 0) 710 mb[mblen] = '\0'; 711 rl_begin_undo_group (); | 722 if (mblen >= 0) 723 mb[mblen] = '\0'; 724 rl_begin_undo_group (); |
712 rl_delete (1, 0); | 725 rl_vi_delete (1, 0); 726 if (rl_point < p) /* Did we retreat at EOL? */ 727 rl_point++; /* XXX - should we advance more than 1 for mbchar? */ |
713 rl_insert_text (mb); 714 rl_end_undo_group (); 715 rl_vi_check (); 716 } 717 else 718 rl_forward_char (1, 0); 719 } 720 721 return 0; 722} 723#endif 724 725int 726rl_vi_change_case (count, ignore) 727 int count, ignore; 728{ | 728 rl_insert_text (mb); 729 rl_end_undo_group (); 730 rl_vi_check (); 731 } 732 else 733 rl_forward_char (1, 0); 734 } 735 736 return 0; 737} 738#endif 739 740int 741rl_vi_change_case (count, ignore) 742 int count, ignore; 743{ |
729 char c = 0; | 744 int c, p; |
730 731 /* Don't try this on an empty line. */ 732 if (rl_point >= rl_end) 733 return (0); 734 | 745 746 /* Don't try this on an empty line. */ 747 if (rl_point >= rl_end) 748 return (0); 749 |
750 c = 0; |
|
735#if defined (HANDLE_MULTIBYTE) 736 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 737 return (_rl_vi_change_mbchar_case (count)); 738#endif 739 740 while (count-- && rl_point < rl_end) 741 { 742 if (_rl_uppercase_p (rl_line_buffer[rl_point])) --- 5 unchanged lines hidden (view full) --- 748 /* Just skip over characters neither upper nor lower case. */ 749 rl_forward_char (1, c); 750 continue; 751 } 752 753 /* Vi is kind of strange here. */ 754 if (c) 755 { | 751#if defined (HANDLE_MULTIBYTE) 752 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 753 return (_rl_vi_change_mbchar_case (count)); 754#endif 755 756 while (count-- && rl_point < rl_end) 757 { 758 if (_rl_uppercase_p (rl_line_buffer[rl_point])) --- 5 unchanged lines hidden (view full) --- 764 /* Just skip over characters neither upper nor lower case. */ 765 rl_forward_char (1, c); 766 continue; 767 } 768 769 /* Vi is kind of strange here. */ 770 if (c) 771 { |
772 p = rl_point; |
|
756 rl_begin_undo_group (); | 773 rl_begin_undo_group (); |
757 rl_delete (1, c); | 774 rl_vi_delete (1, c); 775 if (rl_point < p) /* Did we retreat at EOL? */ 776 rl_point++; |
758 _rl_insert_char (1, c); 759 rl_end_undo_group (); 760 rl_vi_check (); 761 } 762 else 763 rl_forward_char (1, c); 764 } 765 return (0); 766} 767 768int 769rl_vi_put (count, key) 770 int count, key; 771{ 772 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 773 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 774 | 777 _rl_insert_char (1, c); 778 rl_end_undo_group (); 779 rl_vi_check (); 780 } 781 else 782 rl_forward_char (1, c); 783 } 784 return (0); 785} 786 787int 788rl_vi_put (count, key) 789 int count, key; 790{ 791 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 792 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 793 |
775 rl_yank (1, key); | 794 while (count--) 795 rl_yank (1, key); 796 |
776 rl_backward_char (1, key); 777 return (0); 778} 779 780int 781rl_vi_check () 782{ 783 if (rl_point && rl_point == rl_end) --- 31 unchanged lines hidden (view full) --- 815 *nextkey = c; 816 817 if (!member (c, vi_motion)) 818 { 819 if (_rl_digit_p (c)) 820 { 821 save = rl_numeric_arg; 822 rl_numeric_arg = _rl_digit_value (c); | 797 rl_backward_char (1, key); 798 return (0); 799} 800 801int 802rl_vi_check () 803{ 804 if (rl_point && rl_point == rl_end) --- 31 unchanged lines hidden (view full) --- 836 *nextkey = c; 837 838 if (!member (c, vi_motion)) 839 { 840 if (_rl_digit_p (c)) 841 { 842 save = rl_numeric_arg; 843 rl_numeric_arg = _rl_digit_value (c); |
844 rl_explicit_arg = 1; |
|
823 rl_digit_loop1 (); 824 rl_numeric_arg *= save; 825 RL_SETSTATE(RL_STATE_MOREINPUT); 826 c = rl_read_key (); /* real command */ 827 RL_UNSETSTATE(RL_STATE_MOREINPUT); 828 *nextkey = c; 829 } 830 else if (key == c && (key == 'd' || key == 'y' || key == 'c')) --- 182 unchanged lines hidden (view full) --- 1013 } 1014 else 1015 { 1016 rl_begin_undo_group (); /* to make the `u' command work */ 1017 rl_kill_text (rl_point, rl_mark); 1018 /* `C' does not save the text inserted for undoing or redoing. */ 1019 if (_rl_uppercase_p (key) == 0) 1020 _rl_vi_doing_insert = 1; | 845 rl_digit_loop1 (); 846 rl_numeric_arg *= save; 847 RL_SETSTATE(RL_STATE_MOREINPUT); 848 c = rl_read_key (); /* real command */ 849 RL_UNSETSTATE(RL_STATE_MOREINPUT); 850 *nextkey = c; 851 } 852 else if (key == c && (key == 'd' || key == 'y' || key == 'c')) --- 182 unchanged lines hidden (view full) --- 1035 } 1036 else 1037 { 1038 rl_begin_undo_group (); /* to make the `u' command work */ 1039 rl_kill_text (rl_point, rl_mark); 1040 /* `C' does not save the text inserted for undoing or redoing. */ 1041 if (_rl_uppercase_p (key) == 0) 1042 _rl_vi_doing_insert = 1; |
1021 _rl_vi_set_last (key, count, rl_arg_sign); 1022 rl_vi_insertion_mode (1, key); | 1043 rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign); |
1023 } 1024 1025 return (0); 1026} 1027 1028int 1029rl_vi_yank_to (count, key) 1030 int count, key; --- 232 unchanged lines hidden (view full) --- 1263 case '{': return 3; 1264 case '}': return -3; 1265 default: return 0; 1266 } 1267} 1268 1269/* XXX - think about reading an entire mbchar with _rl_read_mbchar and 1270 inserting it in one bunch instead of the loop below (like in | 1044 } 1045 1046 return (0); 1047} 1048 1049int 1050rl_vi_yank_to (count, key) 1051 int count, key; --- 232 unchanged lines hidden (view full) --- 1284 case '{': return 3; 1285 case '}': return -3; 1286 default: return 0; 1287 } 1288} 1289 1290/* XXX - think about reading an entire mbchar with _rl_read_mbchar and 1291 inserting it in one bunch instead of the loop below (like in |
1271 rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0] | 1292 rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0] |
1272 for test against 033 or ^C. Make sure that _rl_read_mbchar does 1273 this right. */ 1274int 1275rl_vi_change_char (count, key) 1276 int count, key; 1277{ | 1293 for test against 033 or ^C. Make sure that _rl_read_mbchar does 1294 this right. */ 1295int 1296rl_vi_change_char (count, key) 1297 int count, key; 1298{ |
1278 int c; | 1299 int c, p; |
1279 1280 if (vi_redoing) 1281 c = _rl_vi_last_replacement; 1282 else 1283 { 1284 RL_SETSTATE(RL_STATE_MOREINPUT); 1285 _rl_vi_last_replacement = c = rl_read_key (); 1286 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1287 } 1288 1289 if (c == '\033' || c == CTRL ('C')) 1290 return -1; 1291 | 1300 1301 if (vi_redoing) 1302 c = _rl_vi_last_replacement; 1303 else 1304 { 1305 RL_SETSTATE(RL_STATE_MOREINPUT); 1306 _rl_vi_last_replacement = c = rl_read_key (); 1307 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1308 } 1309 1310 if (c == '\033' || c == CTRL ('C')) 1311 return -1; 1312 |
1313 rl_begin_undo_group (); |
|
1292 while (count-- && rl_point < rl_end) 1293 { | 1314 while (count-- && rl_point < rl_end) 1315 { |
1294 rl_begin_undo_group (); 1295 1296 rl_delete (1, c); | 1316 p = rl_point; 1317 rl_vi_delete (1, c); |
1297#if defined (HANDLE_MULTIBYTE) 1298 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) | 1318#if defined (HANDLE_MULTIBYTE) 1319 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) |
1299 while (_rl_insert_char (1, c)) 1300 { 1301 RL_SETSTATE (RL_STATE_MOREINPUT); 1302 c = rl_read_key (); 1303 RL_UNSETSTATE (RL_STATE_MOREINPUT); 1304 } | 1320 { 1321 if (rl_point < p) /* Did we retreat at EOL? */ 1322 rl_point++; 1323 while (_rl_insert_char (1, c)) 1324 { 1325 RL_SETSTATE (RL_STATE_MOREINPUT); 1326 c = rl_read_key (); 1327 RL_UNSETSTATE (RL_STATE_MOREINPUT); 1328 } 1329 } |
1305 else 1306#endif | 1330 else 1331#endif |
1307 _rl_insert_char (1, c); 1308 if (count == 0) 1309 rl_backward_char (1, c); 1310 1311 rl_end_undo_group (); | 1332 { 1333 if (rl_point < p) /* Did we retreat at EOL? */ 1334 rl_point++; 1335 _rl_insert_char (1, c); 1336 } |
1312 } | 1337 } |
1338 rl_end_undo_group (); 1339 |
|
1313 return (0); 1314} 1315 1316int 1317rl_vi_subst (count, key) 1318 int count, key; 1319{ 1320 /* If we are redoing, rl_vi_change_to will stuff the last motion char */ 1321 if (vi_redoing == 0) | 1340 return (0); 1341} 1342 1343int 1344rl_vi_subst (count, key) 1345 int count, key; 1346{ 1347 /* If we are redoing, rl_vi_change_to will stuff the last motion char */ 1348 if (vi_redoing == 0) |
1322 rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */ | 1349 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ |
1323 1324 return (rl_vi_change_to (count, 'c')); 1325} 1326 1327int 1328rl_vi_overstrike (count, key) 1329 int count, key; 1330{ --- 159 unchanged lines hidden --- | 1350 1351 return (rl_vi_change_to (count, 'c')); 1352} 1353 1354int 1355rl_vi_overstrike (count, key) 1356 int count, key; 1357{ --- 159 unchanged lines hidden --- |