vi_mode.c revision 21308
1/* vi_mode.c -- A vi emulation mode for Bash. 2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ 3 4/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 5 6 This file is part of the GNU Readline Library, a library for 7 reading lines of text with interactive input and history editing. 8 9 The GNU Readline Library is free software; you can redistribute it 10 and/or modify it under the terms of the GNU General Public License 11 as published by the Free Software Foundation; either version 1, or 12 (at your option) any later version. 13 14 The GNU Readline Library is distributed in the hope that it will be 15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 The GNU General Public License is often shipped with GNU software, and 20 is generally kept in a file called COPYING or LICENSE. If you do not 21 have a copy of the license, write to the Free Software Foundation, 22 675 Mass Ave, Cambridge, MA 02139, USA. */ 23#define READLINE_LIBRARY 24 25/* **************************************************************** */ 26/* */ 27/* VI Emulation Mode */ 28/* */ 29/* **************************************************************** */ 30#include "rlconf.h" 31 32#if defined (VI_MODE) 33 34#if defined (HAVE_CONFIG_H) 35# include <config.h> 36#endif 37 38#include <sys/types.h> 39 40#if defined (HAVE_STDLIB_H) 41# include <stdlib.h> 42#else 43# include "ansi_stdlib.h" 44#endif /* HAVE_STDLIB_H */ 45 46#if defined (HAVE_UNISTD_H) 47# include <unistd.h> 48#endif 49 50#include <stdio.h> 51 52/* Some standard library routines. */ 53#include "rldefs.h" 54#include "readline.h" 55#include "history.h" 56 57#ifndef _rl_digit_p 58#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') 59#endif 60 61#ifndef _rl_digit_value 62#define _rl_digit_value(c) ((c) - '0') 63#endif 64 65#ifndef member 66#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 67#endif 68 69#ifndef isident 70#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_')) 71#endif 72 73#ifndef exchange 74#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0) 75#endif 76 77extern char *xmalloc (), *xrealloc (); 78 79/* Variables imported from readline.c */ 80extern int rl_point, rl_end, rl_mark, rl_done; 81extern FILE *rl_instream; 82extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg; 83extern Keymap _rl_keymap; 84extern char *rl_prompt; 85extern char *rl_line_buffer; 86extern int rl_arg_sign; 87 88extern int _rl_doing_an_undo; 89extern int _rl_undo_group_level; 90 91extern void _rl_dispatch (); 92extern int _rl_char_search_internal (); 93 94extern void rl_extend_line_buffer (); 95extern int rl_vi_check (); 96 97/* Non-zero means enter insertion mode. */ 98static int _rl_vi_doing_insert; 99 100/* Command keys which do movement for xxx_to commands. */ 101static char *vi_motion = " hl^$0ftFt;,%wbeWBE|"; 102 103/* Keymap used for vi replace characters. Created dynamically since 104 rarely used. */ 105static Keymap vi_replace_map; 106 107/* The number of characters inserted in the last replace operation. */ 108static int vi_replace_count; 109 110/* If non-zero, we have text inserted after a c[motion] command that put 111 us implicitly into insert mode. Some people want this text to be 112 attached to the command so that it is `redoable' with `.'. */ 113static int vi_continued_command; 114static char *vi_insert_buffer; 115static int vi_insert_buffer_size; 116 117static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ 118static int _rl_vi_last_repeat = 1; 119static int _rl_vi_last_arg_sign = 1; 120static int _rl_vi_last_motion; 121static int _rl_vi_last_search_char; 122static int _rl_vi_last_replacement; 123 124static int _rl_vi_last_key_before_insert; 125 126static int vi_redoing; 127 128/* Text modification commands. These are the `redoable' commands. */ 129static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; 130 131/* Arrays for the saved marks. */ 132static int vi_mark_chars[27]; 133 134static int rl_digit_loop1 (); 135 136void 137_rl_vi_initialize_line () 138{ 139 register int i; 140 141 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) 142 vi_mark_chars[i] = -1; 143} 144 145void 146_rl_vi_reset_last () 147{ 148 _rl_vi_last_command = 'i'; 149 _rl_vi_last_repeat = 1; 150 _rl_vi_last_arg_sign = 1; 151 _rl_vi_last_motion = 0; 152} 153 154void 155_rl_vi_set_last (key, repeat, sign) 156 int key, repeat, sign; 157{ 158 _rl_vi_last_command = key; 159 _rl_vi_last_repeat = repeat; 160 _rl_vi_last_arg_sign = sign; 161} 162 163/* Is the command C a VI mode text modification command? */ 164int 165_rl_vi_textmod_command (c) 166 int c; 167{ 168 return (member (c, vi_textmod)); 169} 170 171static void 172_rl_vi_stuff_insert (count) 173 int count; 174{ 175 rl_begin_undo_group (); 176 while (count--) 177 rl_insert_text (vi_insert_buffer); 178 rl_end_undo_group (); 179} 180 181/* Bound to `.'. Called from command mode, so we know that we have to 182 redo a text modification command. The default for _rl_vi_last_command 183 puts you back into insert mode. */ 184int 185rl_vi_redo (count, c) 186 int count, c; 187{ 188 if (!rl_explicit_arg) 189 { 190 rl_numeric_arg = _rl_vi_last_repeat; 191 rl_arg_sign = _rl_vi_last_arg_sign; 192 } 193 194 vi_redoing = 1; 195 /* If we're redoing an insert with `i', stuff in the inserted text 196 and do not go into insertion mode. */ 197 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) 198 { 199 _rl_vi_stuff_insert (count); 200 /* And back up point over the last character inserted. */ 201 if (rl_point > 0) 202 rl_point--; 203 } 204 else 205 _rl_dispatch (_rl_vi_last_command, _rl_keymap); 206 vi_redoing = 0; 207 208 return (0); 209} 210 211/* A placeholder for further expansion. */ 212int 213rl_vi_undo (count, key) 214 int count, key; 215{ 216 return (rl_undo_command (count, key)); 217} 218 219/* Yank the nth arg from the previous line into this line at point. */ 220int 221rl_vi_yank_arg (count, key) 222 int count, key; 223{ 224 /* Readline thinks that the first word on a line is the 0th, while vi 225 thinks the first word on a line is the 1st. Compensate. */ 226 if (rl_explicit_arg) 227 rl_yank_nth_arg (count - 1, 0); 228 else 229 rl_yank_nth_arg ('$', 0); 230 231 return (0); 232} 233 234/* With an argument, move back that many history lines, else move to the 235 beginning of history. */ 236int 237rl_vi_fetch_history (count, c) 238 int count, c; 239{ 240 int wanted; 241 242 /* Giving an argument of n means we want the nth command in the history 243 file. The command number is interpreted the same way that the bash 244 `history' command does it -- that is, giving an argument count of 450 245 to this command would get the command listed as number 450 in the 246 output of `history'. */ 247 if (rl_explicit_arg) 248 { 249 wanted = history_base + where_history () - count; 250 if (wanted <= 0) 251 rl_beginning_of_history (0, 0); 252 else 253 rl_get_previous_history (wanted, c); 254 } 255 else 256 rl_beginning_of_history (count, 0); 257 return (0); 258} 259 260/* Search again for the last thing searched for. */ 261int 262rl_vi_search_again (count, key) 263 int count, key; 264{ 265 switch (key) 266 { 267 case 'n': 268 rl_noninc_reverse_search_again (count, key); 269 break; 270 271 case 'N': 272 rl_noninc_forward_search_again (count, key); 273 break; 274 } 275 return (0); 276} 277 278/* Do a vi style search. */ 279int 280rl_vi_search (count, key) 281 int count, key; 282{ 283 switch (key) 284 { 285 case '?': 286 rl_noninc_forward_search (count, key); 287 break; 288 289 case '/': 290 rl_noninc_reverse_search (count, key); 291 break; 292 293 default: 294 ding (); 295 break; 296 } 297 return (0); 298} 299 300/* Completion, from vi's point of view. */ 301int 302rl_vi_complete (ignore, key) 303 int ignore, key; 304{ 305 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) 306 { 307 if (!whitespace (rl_line_buffer[rl_point + 1])) 308 rl_vi_end_word (1, 'E'); 309 rl_point++; 310 } 311 312 if (key == '*') 313 rl_complete_internal ('*'); /* Expansion and replacement. */ 314 else if (key == '=') 315 rl_complete_internal ('?'); /* List possible completions. */ 316 else if (key == '\\') 317 rl_complete_internal (TAB); /* Standard Readline completion. */ 318 else 319 rl_complete (0, key); 320 321 if (key == '*' || key == '\\') 322 { 323 _rl_vi_set_last (key, 1, rl_arg_sign); 324 rl_vi_insertion_mode (1, key); 325 } 326 return (0); 327} 328 329/* Tilde expansion for vi mode. */ 330int 331rl_vi_tilde_expand (ignore, key) 332 int ignore, key; 333{ 334 rl_tilde_expand (0, key); 335 _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ 336 rl_vi_insertion_mode (1, key); 337 return (0); 338} 339 340/* Previous word in vi mode. */ 341int 342rl_vi_prev_word (count, key) 343 int count, key; 344{ 345 if (count < 0) 346 return (rl_vi_next_word (-count, key)); 347 348 if (rl_point == 0) 349 { 350 ding (); 351 return (0); 352 } 353 354 if (_rl_uppercase_p (key)) 355 rl_vi_bWord (count); 356 else 357 rl_vi_bword (count); 358 359 return (0); 360} 361 362/* Next word in vi mode. */ 363int 364rl_vi_next_word (count, key) 365 int count, key; 366{ 367 if (count < 0) 368 return (rl_vi_prev_word (-count, key)); 369 370 if (rl_point >= (rl_end - 1)) 371 { 372 ding (); 373 return (0); 374 } 375 376 if (_rl_uppercase_p (key)) 377 rl_vi_fWord (count); 378 else 379 rl_vi_fword (count); 380 return (0); 381} 382 383/* Move to the end of the ?next? word. */ 384int 385rl_vi_end_word (count, key) 386 int count, key; 387{ 388 if (count < 0) 389 { 390 ding (); 391 return -1; 392 } 393 394 if (_rl_uppercase_p (key)) 395 rl_vi_eWord (count); 396 else 397 rl_vi_eword (count); 398 return (0); 399} 400 401/* Move forward a word the way that 'W' does. */ 402int 403rl_vi_fWord (count) 404 int count; 405{ 406 while (count-- && rl_point < (rl_end - 1)) 407 { 408 /* Skip until whitespace. */ 409 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 410 rl_point++; 411 412 /* Now skip whitespace. */ 413 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 414 rl_point++; 415 } 416 return (0); 417} 418 419int 420rl_vi_bWord (count) 421 int count; 422{ 423 while (count-- && rl_point > 0) 424 { 425 /* If we are at the start of a word, move back to whitespace so 426 we will go back to the start of the previous word. */ 427 if (!whitespace (rl_line_buffer[rl_point]) && 428 whitespace (rl_line_buffer[rl_point - 1])) 429 rl_point--; 430 431 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 432 rl_point--; 433 434 if (rl_point > 0) 435 { 436 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); 437 rl_point++; 438 } 439 } 440 return (0); 441} 442 443int 444rl_vi_eWord (count) 445 int count; 446{ 447 while (count-- && rl_point < (rl_end - 1)) 448 { 449 if (!whitespace (rl_line_buffer[rl_point])) 450 rl_point++; 451 452 /* Move to the next non-whitespace character (to the start of the 453 next word). */ 454 while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])); 455 456 if (rl_point && rl_point < rl_end) 457 { 458 /* Skip whitespace. */ 459 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 460 rl_point++; 461 462 /* Skip until whitespace. */ 463 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) 464 rl_point++; 465 466 /* Move back to the last character of the word. */ 467 rl_point--; 468 } 469 } 470 return (0); 471} 472 473int 474rl_vi_fword (count) 475 int count; 476{ 477 while (count-- && rl_point < (rl_end - 1)) 478 { 479 /* Move to white space (really non-identifer). */ 480 if (isident (rl_line_buffer[rl_point])) 481 { 482 while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) 483 rl_point++; 484 } 485 else /* if (!whitespace (rl_line_buffer[rl_point])) */ 486 { 487 while (!isident (rl_line_buffer[rl_point]) && 488 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 489 rl_point++; 490 } 491 492 /* Move past whitespace. */ 493 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 494 rl_point++; 495 } 496 return (0); 497} 498 499int 500rl_vi_bword (count) 501 int count; 502{ 503 while (count-- && rl_point > 0) 504 { 505 int last_is_ident; 506 507 /* If we are at the start of a word, move back to whitespace 508 so we will go back to the start of the previous word. */ 509 if (!whitespace (rl_line_buffer[rl_point]) && 510 whitespace (rl_line_buffer[rl_point - 1])) 511 rl_point--; 512 513 /* If this character and the previous character are `opposite', move 514 back so we don't get messed up by the rl_point++ down there in 515 the while loop. Without this code, words like `l;' screw up the 516 function. */ 517 last_is_ident = isident (rl_line_buffer[rl_point - 1]); 518 if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || 519 (!isident (rl_line_buffer[rl_point]) && last_is_ident)) 520 rl_point--; 521 522 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 523 rl_point--; 524 525 if (rl_point > 0) 526 { 527 if (isident (rl_line_buffer[rl_point])) 528 while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); 529 else 530 while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && 531 !whitespace (rl_line_buffer[rl_point])); 532 rl_point++; 533 } 534 } 535 return (0); 536} 537 538int 539rl_vi_eword (count) 540 int count; 541{ 542 while (count-- && rl_point < rl_end - 1) 543 { 544 if (!whitespace (rl_line_buffer[rl_point])) 545 rl_point++; 546 547 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 548 rl_point++; 549 550 if (rl_point < rl_end) 551 { 552 if (isident (rl_line_buffer[rl_point])) 553 while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); 554 else 555 while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) 556 && !whitespace (rl_line_buffer[rl_point])); 557 } 558 rl_point--; 559 } 560 return (0); 561} 562 563int 564rl_vi_insert_beg (count, key) 565 int count, key; 566{ 567 rl_beg_of_line (1, key); 568 rl_vi_insertion_mode (1, key); 569 return (0); 570} 571 572int 573rl_vi_append_mode (count, key) 574 int count, key; 575{ 576 if (rl_point < rl_end) 577 rl_point++; 578 rl_vi_insertion_mode (1, key); 579 return (0); 580} 581 582int 583rl_vi_append_eol (count, key) 584 int count, key; 585{ 586 rl_end_of_line (1, key); 587 rl_vi_append_mode (1, key); 588 return (0); 589} 590 591/* What to do in the case of C-d. */ 592int 593rl_vi_eof_maybe (count, c) 594 int count, c; 595{ 596 return (rl_newline (1, '\n')); 597} 598 599/* Insertion mode stuff. */ 600 601/* Switching from one mode to the other really just involves 602 switching keymaps. */ 603int 604rl_vi_insertion_mode (count, key) 605 int count, key; 606{ 607 _rl_keymap = vi_insertion_keymap; 608 _rl_vi_last_key_before_insert = key; 609 return (0); 610} 611 612static void 613_rl_vi_save_insert (up) 614 UNDO_LIST *up; 615{ 616 int len, start, end; 617 618 start = up->start; 619 end = up->end; 620 len = end - start + 1; 621 if (len >= vi_insert_buffer_size) 622 { 623 vi_insert_buffer_size += (len + 32) - (len % 32); 624 vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size); 625 } 626 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); 627 vi_insert_buffer[len-1] = '\0'; 628} 629 630void 631_rl_vi_done_inserting () 632{ 633 if (_rl_vi_doing_insert) 634 { 635 rl_end_undo_group (); 636 /* Now, the text between rl_undo_list->next->start and 637 rl_undo_list->next->end is what was inserted while in insert 638 mode. It gets copied to VI_INSERT_BUFFER because it depends 639 on absolute indices into the line which may change (though they 640 probably will not). */ 641 _rl_vi_doing_insert = 0; 642 _rl_vi_save_insert (rl_undo_list->next); 643 vi_continued_command = 1; 644 } 645 else 646 { 647 if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list) 648 _rl_vi_save_insert (rl_undo_list); 649 /* XXX - Other keys probably need to be checked. */ 650 else if (_rl_vi_last_key_before_insert == 'C') 651 rl_end_undo_group (); 652 while (_rl_undo_group_level > 0) 653 rl_end_undo_group (); 654 vi_continued_command = 0; 655 } 656} 657 658int 659rl_vi_movement_mode (count, key) 660 int count, key; 661{ 662 if (rl_point > 0) 663 rl_backward (1, key); 664 665 _rl_keymap = vi_movement_keymap; 666 _rl_vi_done_inserting (); 667 return (0); 668} 669 670int 671rl_vi_arg_digit (count, c) 672 int count, c; 673{ 674 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) 675 return (rl_beg_of_line (1, c)); 676 else 677 return (rl_digit_argument (count, c)); 678} 679 680int 681rl_vi_change_case (count, ignore) 682 int count, ignore; 683{ 684 char c = 0; 685 686 /* Don't try this on an empty line. */ 687 if (rl_point >= rl_end) 688 return (0); 689 690 while (count-- && rl_point < rl_end) 691 { 692 if (_rl_uppercase_p (rl_line_buffer[rl_point])) 693 c = _rl_to_lower (rl_line_buffer[rl_point]); 694 else if (_rl_lowercase_p (rl_line_buffer[rl_point])) 695 c = _rl_to_upper (rl_line_buffer[rl_point]); 696 else 697 { 698 /* Just skip over characters neither upper nor lower case. */ 699 rl_forward (1, c); 700 continue; 701 } 702 703 /* Vi is kind of strange here. */ 704 if (c) 705 { 706 rl_begin_undo_group (); 707 rl_delete (1, c); 708 rl_insert (1, c); 709 rl_end_undo_group (); 710 rl_vi_check (); 711 } 712 else 713 rl_forward (1, c); 714 } 715 return (0); 716} 717 718int 719rl_vi_put (count, key) 720 int count, key; 721{ 722 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 723 rl_point++; 724 725 rl_yank (); 726 rl_backward (1, key); 727 return (0); 728} 729 730int 731rl_vi_check () 732{ 733 if (rl_point && rl_point == rl_end) 734 rl_point--; 735 return (0); 736} 737 738int 739rl_vi_column (count, key) 740 int count, key; 741{ 742 if (count > rl_end) 743 rl_end_of_line (1, key); 744 else 745 rl_point = count - 1; 746 return (0); 747} 748 749int 750rl_vi_domove (key, nextkey) 751 int key, *nextkey; 752{ 753 int c, save; 754 int old_end; 755 756 rl_mark = rl_point; 757 c = rl_read_key (); 758 *nextkey = c; 759 760 if (!member (c, vi_motion)) 761 { 762 if (_rl_digit_p (c)) 763 { 764 save = rl_numeric_arg; 765 rl_numeric_arg = _rl_digit_value (c); 766 rl_digit_loop1 (); 767 rl_numeric_arg *= save; 768 c = rl_read_key (); /* real command */ 769 *nextkey = c; 770 } 771 else if (key == c && (key == 'd' || key == 'y' || key == 'c')) 772 { 773 rl_mark = rl_end; 774 rl_beg_of_line (1, c); 775 _rl_vi_last_motion = c; 776 return (0); 777 } 778 else 779 return (-1); 780 } 781 782 _rl_vi_last_motion = c; 783 784 /* Append a blank character temporarily so that the motion routines 785 work right at the end of the line. */ 786 old_end = rl_end; 787 rl_line_buffer[rl_end++] = ' '; 788 rl_line_buffer[rl_end] = '\0'; 789 790 _rl_dispatch (c, _rl_keymap); 791 792 /* Remove the blank that we added. */ 793 rl_end = old_end; 794 rl_line_buffer[rl_end] = '\0'; 795 if (rl_point > rl_end) 796 rl_point = rl_end; 797 798 /* No change in position means the command failed. */ 799 if (rl_mark == rl_point) 800 return (-1); 801 802 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next 803 word. If we are not at the end of the line, and we are on a 804 non-whitespace character, move back one (presumably to whitespace). */ 805 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && 806 !whitespace (rl_line_buffer[rl_point])) 807 rl_point--; 808 809 /* If cw or cW, back up to the end of a word, so the behaviour of ce 810 or cE is the actual result. Brute-force, no subtlety. */ 811 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) 812 { 813 /* Don't move farther back than where we started. */ 814 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) 815 rl_point--; 816 817 /* Posix.2 says that if cw or cW moves the cursor towards the end of 818 the line, the character under the cursor should be deleted. */ 819 if (rl_point == rl_mark) 820 rl_point++; 821 else 822 { 823 /* Move past the end of the word so that the kill doesn't 824 remove the last letter of the previous word. Only do this 825 if we are not at the end of the line. */ 826 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) 827 rl_point++; 828 } 829 } 830 831 if (rl_mark < rl_point) 832 exchange (rl_point, rl_mark); 833 834 return (0); 835} 836 837/* A simplified loop for vi. Don't dispatch key at end. 838 Don't recognize minus sign? */ 839static int 840rl_digit_loop1 () 841{ 842 int key, c; 843 844 while (1) 845 { 846 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); 847 key = c = rl_read_key (); 848 849 if (_rl_keymap[c].type == ISFUNC && 850 _rl_keymap[c].function == rl_universal_argument) 851 { 852 rl_numeric_arg *= 4; 853 continue; 854 } 855 856 c = UNMETA (c); 857 if (_rl_digit_p (c)) 858 { 859 if (rl_explicit_arg) 860 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); 861 else 862 rl_numeric_arg = _rl_digit_value (c); 863 rl_explicit_arg = 1; 864 } 865 else 866 { 867 rl_clear_message (); 868 rl_stuff_char (key); 869 break; 870 } 871 } 872 return (0); 873} 874 875int 876rl_vi_delete_to (count, key) 877 int count, key; 878{ 879 int c; 880 881 if (_rl_uppercase_p (key)) 882 rl_stuff_char ('$'); 883 else if (vi_redoing) 884 rl_stuff_char (_rl_vi_last_motion); 885 886 if (rl_vi_domove (key, &c)) 887 { 888 ding (); 889 return -1; 890 } 891 892 /* These are the motion commands that do not require adjusting the 893 mark. */ 894 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) 895 rl_mark++; 896 897 rl_kill_text (rl_point, rl_mark); 898 return (0); 899} 900 901int 902rl_vi_change_to (count, key) 903 int count, key; 904{ 905 int c, start_pos; 906 907 if (_rl_uppercase_p (key)) 908 rl_stuff_char ('$'); 909 else if (vi_redoing) 910 rl_stuff_char (_rl_vi_last_motion); 911 912 start_pos = rl_point; 913 914 if (rl_vi_domove (key, &c)) 915 { 916 ding (); 917 return -1; 918 } 919 920 /* These are the motion commands that do not require adjusting the 921 mark. c[wW] are handled by special-case code in rl_vi_domove(), 922 and already leave the mark at the correct location. */ 923 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) 924 rl_mark++; 925 926 /* The cursor never moves with c[wW]. */ 927 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) 928 rl_point = start_pos; 929 930 if (vi_redoing) 931 { 932 if (vi_insert_buffer && *vi_insert_buffer) 933 rl_begin_undo_group (); 934 rl_delete_text (rl_point, rl_mark); 935 if (vi_insert_buffer && *vi_insert_buffer) 936 { 937 rl_insert_text (vi_insert_buffer); 938 rl_end_undo_group (); 939 } 940 } 941 else 942 { 943 rl_begin_undo_group (); /* to make the `u' command work */ 944 rl_kill_text (rl_point, rl_mark); 945 /* `C' does not save the text inserted for undoing or redoing. */ 946 if (_rl_uppercase_p (key) == 0) 947 _rl_vi_doing_insert = 1; 948 _rl_vi_set_last (key, count, rl_arg_sign); 949 rl_vi_insertion_mode (1, key); 950 } 951 952 return (0); 953} 954 955int 956rl_vi_yank_to (count, key) 957 int count, key; 958{ 959 int c, save = rl_point; 960 961 if (_rl_uppercase_p (key)) 962 rl_stuff_char ('$'); 963 964 if (rl_vi_domove (key, &c)) 965 { 966 ding (); 967 return -1; 968 } 969 970 /* These are the motion commands that do not require adjusting the 971 mark. */ 972 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) 973 rl_mark++; 974 975 rl_begin_undo_group (); 976 rl_kill_text (rl_point, rl_mark); 977 rl_end_undo_group (); 978 rl_do_undo (); 979 rl_point = save; 980 981 return (0); 982} 983 984int 985rl_vi_delete (count, key) 986 int count, key; 987{ 988 int end; 989 990 if (rl_end == 0) 991 { 992 ding (); 993 return -1; 994 } 995 996 end = rl_point + count; 997 998 if (end >= rl_end) 999 end = rl_end; 1000 1001 rl_kill_text (rl_point, end); 1002 1003 if (rl_point > 0 && rl_point == rl_end) 1004 rl_backward (1, key); 1005 return (0); 1006} 1007 1008int 1009rl_vi_back_to_indent (count, key) 1010 int count, key; 1011{ 1012 rl_beg_of_line (1, key); 1013 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1014 rl_point++; 1015 return (0); 1016} 1017 1018int 1019rl_vi_first_print (count, key) 1020 int count, key; 1021{ 1022 return (rl_vi_back_to_indent (1, key)); 1023} 1024 1025int 1026rl_vi_char_search (count, key) 1027 int count, key; 1028{ 1029 static char target; 1030 static int orig_dir, dir; 1031 1032 if (key == ';' || key == ',') 1033 dir = key == ';' ? orig_dir : -orig_dir; 1034 else 1035 { 1036 if (vi_redoing) 1037 target = _rl_vi_last_search_char; 1038 else 1039 _rl_vi_last_search_char = target = rl_getc (rl_instream); 1040 1041 switch (key) 1042 { 1043 case 't': 1044 orig_dir = dir = FTO; 1045 break; 1046 1047 case 'T': 1048 orig_dir = dir = BTO; 1049 break; 1050 1051 case 'f': 1052 orig_dir = dir = FFIND; 1053 break; 1054 1055 case 'F': 1056 orig_dir = dir = BFIND; 1057 break; 1058 } 1059 } 1060 1061 return (_rl_char_search_internal (count, dir, target)); 1062} 1063 1064/* Match brackets */ 1065int 1066rl_vi_match (ignore, key) 1067 int ignore, key; 1068{ 1069 int count = 1, brack, pos; 1070 1071 pos = rl_point; 1072 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 1073 { 1074 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && 1075 rl_point < rl_end - 1) 1076 rl_forward (1, key); 1077 1078 if (brack <= 0) 1079 { 1080 rl_point = pos; 1081 ding (); 1082 return -1; 1083 } 1084 } 1085 1086 pos = rl_point; 1087 1088 if (brack < 0) 1089 { 1090 while (count) 1091 { 1092 if (--pos >= 0) 1093 { 1094 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1095 if (b == -brack) 1096 count--; 1097 else if (b == brack) 1098 count++; 1099 } 1100 else 1101 { 1102 ding (); 1103 return -1; 1104 } 1105 } 1106 } 1107 else 1108 { /* brack > 0 */ 1109 while (count) 1110 { 1111 if (++pos < rl_end) 1112 { 1113 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1114 if (b == -brack) 1115 count--; 1116 else if (b == brack) 1117 count++; 1118 } 1119 else 1120 { 1121 ding (); 1122 return -1; 1123 } 1124 } 1125 } 1126 rl_point = pos; 1127 return (0); 1128} 1129 1130int 1131rl_vi_bracktype (c) 1132 int c; 1133{ 1134 switch (c) 1135 { 1136 case '(': return 1; 1137 case ')': return -1; 1138 case '[': return 2; 1139 case ']': return -2; 1140 case '{': return 3; 1141 case '}': return -3; 1142 default: return 0; 1143 } 1144} 1145 1146int 1147rl_vi_change_char (count, key) 1148 int count, key; 1149{ 1150 int c; 1151 1152 if (vi_redoing) 1153 c = _rl_vi_last_replacement; 1154 else 1155 _rl_vi_last_replacement = c = rl_getc (rl_instream); 1156 1157 if (c == '\033' || c == CTRL ('C')) 1158 return -1; 1159 1160 while (count-- && rl_point < rl_end) 1161 { 1162 rl_begin_undo_group (); 1163 1164 rl_delete (1, c); 1165 rl_insert (1, c); 1166 if (count == 0) 1167 rl_backward (1, c); 1168 1169 rl_end_undo_group (); 1170 } 1171 return (0); 1172} 1173 1174int 1175rl_vi_subst (count, key) 1176 int count, key; 1177{ 1178 rl_begin_undo_group (); 1179 1180 if (_rl_uppercase_p (key)) 1181 { 1182 rl_beg_of_line (1, key); 1183 rl_kill_line (1, key); 1184 } 1185 else 1186 rl_delete_text (rl_point, rl_point+count); 1187 1188 rl_end_undo_group (); 1189 1190 _rl_vi_set_last (key, count, rl_arg_sign); 1191 1192 if (vi_redoing) 1193 { 1194 int o = _rl_doing_an_undo; 1195 1196 _rl_doing_an_undo = 1; 1197 if (vi_insert_buffer && *vi_insert_buffer) 1198 rl_insert_text (vi_insert_buffer); 1199 _rl_doing_an_undo = o; 1200 } 1201 else 1202 { 1203 rl_begin_undo_group (); 1204 _rl_vi_doing_insert = 1; 1205 rl_vi_insertion_mode (1, key); 1206 } 1207 1208 return (0); 1209} 1210 1211int 1212rl_vi_overstrike (count, key) 1213 int count, key; 1214{ 1215 int i; 1216 1217 if (_rl_vi_doing_insert == 0) 1218 { 1219 _rl_vi_doing_insert = 1; 1220 rl_begin_undo_group (); 1221 } 1222 1223 for (i = 0; i < count; i++) 1224 { 1225 vi_replace_count++; 1226 rl_begin_undo_group (); 1227 1228 if (rl_point < rl_end) 1229 { 1230 rl_delete (1, key); 1231 rl_insert (1, key); 1232 } 1233 else 1234 rl_insert (1, key); 1235 1236 rl_end_undo_group (); 1237 } 1238 return (0); 1239} 1240 1241int 1242rl_vi_overstrike_delete (count, key) 1243 int count, key; 1244{ 1245 int i, s; 1246 1247 for (i = 0; i < count; i++) 1248 { 1249 if (vi_replace_count == 0) 1250 { 1251 ding (); 1252 break; 1253 } 1254 s = rl_point; 1255 1256 if (rl_do_undo ()) 1257 vi_replace_count--; 1258 1259 if (rl_point == s) 1260 rl_backward (1, key); 1261 } 1262 1263 if (vi_replace_count == 0 && _rl_vi_doing_insert) 1264 { 1265 rl_end_undo_group (); 1266 rl_do_undo (); 1267 _rl_vi_doing_insert = 0; 1268 } 1269 return (0); 1270} 1271 1272int 1273rl_vi_replace (count, key) 1274 int count, key; 1275{ 1276 int i; 1277 1278 vi_replace_count = 0; 1279 1280 if (!vi_replace_map) 1281 { 1282 vi_replace_map = rl_make_bare_keymap (); 1283 1284 for (i = ' '; i < KEYMAP_SIZE; i++) 1285 vi_replace_map[i].function = rl_vi_overstrike; 1286 1287 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; 1288 vi_replace_map[ESC].function = rl_vi_movement_mode; 1289 vi_replace_map[RETURN].function = rl_newline; 1290 vi_replace_map[NEWLINE].function = rl_newline; 1291 1292 /* If the normal vi insertion keymap has ^H bound to erase, do the 1293 same here. Probably should remove the assignment to RUBOUT up 1294 there, but I don't think it will make a difference in real life. */ 1295 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && 1296 vi_insertion_keymap[CTRL ('H')].function == rl_rubout) 1297 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; 1298 1299 } 1300 _rl_keymap = vi_replace_map; 1301 return (0); 1302} 1303 1304#if 0 1305/* Try to complete the word we are standing on or the word that ends with 1306 the previous character. A space matches everything. Word delimiters are 1307 space and ;. */ 1308int 1309rl_vi_possible_completions() 1310{ 1311 int save_pos = rl_point; 1312 1313 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') 1314 { 1315 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && 1316 rl_line_buffer[rl_point] != ';') 1317 rl_point++; 1318 } 1319 else if (rl_line_buffer[rl_point - 1] == ';') 1320 { 1321 ding (); 1322 return (0); 1323 } 1324 1325 rl_possible_completions (); 1326 rl_point = save_pos; 1327 1328 return (0); 1329} 1330#endif 1331 1332/* Functions to save and restore marks. */ 1333int 1334rl_vi_set_mark (count, key) 1335 int count, key; 1336{ 1337 int ch; 1338 1339 ch = rl_read_key (); 1340 if (_rl_lowercase_p (ch) == 0) 1341 { 1342 ding (); 1343 return -1; 1344 } 1345 ch -= 'a'; 1346 vi_mark_chars[ch] = rl_point; 1347 return 0; 1348} 1349 1350int 1351rl_vi_goto_mark (count, key) 1352 int count, key; 1353{ 1354 int ch; 1355 1356 ch = rl_read_key (); 1357 if (ch == '`') 1358 { 1359 rl_point = rl_mark; 1360 return 0; 1361 } 1362 else if (_rl_lowercase_p (ch) == 0) 1363 { 1364 ding (); 1365 return -1; 1366 } 1367 1368 ch -= 'a'; 1369 if (vi_mark_chars[ch] == -1) 1370 { 1371 ding (); 1372 return -1; 1373 } 1374 rl_point = vi_mark_chars[ch]; 1375 return 0; 1376} 1377 1378#endif /* VI_MODE */ 1379