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-2005 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 2, 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 59 Temple Place, Suite 330, Boston, MA 02111 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 "rlmbutil.h" 55 56#include "readline.h" 57#include "history.h" 58 59#include "rlprivate.h" 60#include "xmalloc.h" 61 62#ifndef member 63#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 64#endif 65 66int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ 67 68/* Non-zero means enter insertion mode. */ 69static int _rl_vi_doing_insert; 70 71/* Command keys which do movement for xxx_to commands. */ 72static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; 73 74/* Keymap used for vi replace characters. Created dynamically since 75 rarely used. */ 76static Keymap vi_replace_map; 77 78/* The number of characters inserted in the last replace operation. */ 79static int vi_replace_count; 80 81/* If non-zero, we have text inserted after a c[motion] command that put 82 us implicitly into insert mode. Some people want this text to be 83 attached to the command so that it is `redoable' with `.'. */ 84static int vi_continued_command; 85static char *vi_insert_buffer; 86static int vi_insert_buffer_size; 87 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]; 93static int _rl_vi_last_search_mblen; 94#else 95static int _rl_vi_last_search_char; 96#endif 97static int _rl_vi_last_replacement; 98 99static int _rl_vi_last_key_before_insert; 100 101static int vi_redoing; 102 103/* Text modification commands. These are the `redoable' commands. */ 104static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; 105 106/* Arrays for the saved marks. */ 107static int vi_mark_chars['z' - 'a' + 1]; 108 109static void _rl_vi_stuff_insert PARAMS((int)); 110static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); 111 112static void _rl_vi_backup PARAMS((void)); 113 114static int _rl_vi_arg_dispatch PARAMS((int)); 115static int rl_digit_loop1 PARAMS((void)); 116 117static int _rl_vi_set_mark PARAMS((void)); 118static int _rl_vi_goto_mark PARAMS((void)); 119 120static void _rl_vi_append_forward PARAMS((int)); 121 122static int _rl_vi_callback_getchar PARAMS((char *, int)); 123 124#if defined (READLINE_CALLBACKS) 125static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *)); 126static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *)); 127static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *)); 128static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); 129#endif 130 131void 132_rl_vi_initialize_line () 133{ 134 register int i; 135 136 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) 137 vi_mark_chars[i] = -1; 138 139 RL_UNSETSTATE(RL_STATE_VICMDONCE); 140} 141 142void 143_rl_vi_reset_last () 144{ 145 _rl_vi_last_command = 'i'; 146 _rl_vi_last_repeat = 1; 147 _rl_vi_last_arg_sign = 1; 148 _rl_vi_last_motion = 0; 149} 150 151void 152_rl_vi_set_last (key, repeat, sign) 153 int key, repeat, sign; 154{ 155 _rl_vi_last_command = key; 156 _rl_vi_last_repeat = repeat; 157 _rl_vi_last_arg_sign = sign; 158} 159 160/* A convenience function that calls _rl_vi_set_last to save the last command 161 information and enters insertion mode. */ 162void 163rl_vi_start_inserting (key, repeat, sign) 164 int key, repeat, sign; 165{ 166 _rl_vi_set_last (key, repeat, sign); 167 rl_vi_insertion_mode (1, key); 168} 169 170/* Is the command C a VI mode text modification command? */ 171int 172_rl_vi_textmod_command (c) 173 int c; 174{ 175 return (member (c, vi_textmod)); 176} 177 178static void 179_rl_vi_stuff_insert (count) 180 int count; 181{ 182 rl_begin_undo_group (); 183 while (count--) 184 rl_insert_text (vi_insert_buffer); 185 rl_end_undo_group (); 186} 187 188/* Bound to `.'. Called from command mode, so we know that we have to 189 redo a text modification command. The default for _rl_vi_last_command 190 puts you back into insert mode. */ 191int 192rl_vi_redo (count, c) 193 int count, c; 194{ 195 int r; 196 197 if (!rl_explicit_arg) 198 { 199 rl_numeric_arg = _rl_vi_last_repeat; 200 rl_arg_sign = _rl_vi_last_arg_sign; 201 } 202 203 r = 0; 204 vi_redoing = 1; 205 /* If we're redoing an insert with `i', stuff in the inserted text 206 and do not go into insertion mode. */ 207 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) 208 { 209 _rl_vi_stuff_insert (count); 210 /* And back up point over the last character inserted. */ 211 if (rl_point > 0) 212 _rl_vi_backup (); 213 } 214 /* Ditto for redoing an insert with `a', but move forward a character first 215 like the `a' command does. */ 216 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer) 217 { 218 _rl_vi_append_forward ('a'); 219 _rl_vi_stuff_insert (count); 220 if (rl_point > 0) 221 _rl_vi_backup (); 222 } 223 else 224 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); 225 vi_redoing = 0; 226 227 return (r); 228} 229 230/* A placeholder for further expansion. */ 231int 232rl_vi_undo (count, key) 233 int count, key; 234{ 235 return (rl_undo_command (count, key)); 236} 237 238/* Yank the nth arg from the previous line into this line at point. */ 239int 240rl_vi_yank_arg (count, key) 241 int count, key; 242{ 243 /* Readline thinks that the first word on a line is the 0th, while vi 244 thinks the first word on a line is the 1st. Compensate. */ 245 if (rl_explicit_arg) 246 rl_yank_nth_arg (count - 1, 0); 247 else 248 rl_yank_nth_arg ('$', 0); 249 250 return (0); 251} 252 253/* With an argument, move back that many history lines, else move to the 254 beginning of history. */ 255int 256rl_vi_fetch_history (count, c) 257 int count, c; 258{ 259 int wanted; 260 261 /* Giving an argument of n means we want the nth command in the history 262 file. The command number is interpreted the same way that the bash 263 `history' command does it -- that is, giving an argument count of 450 264 to this command would get the command listed as number 450 in the 265 output of `history'. */ 266 if (rl_explicit_arg) 267 { 268 wanted = history_base + where_history () - count; 269 if (wanted <= 0) 270 rl_beginning_of_history (0, 0); 271 else 272 rl_get_previous_history (wanted, c); 273 } 274 else 275 rl_beginning_of_history (count, 0); 276 return (0); 277} 278 279/* Search again for the last thing searched for. */ 280int 281rl_vi_search_again (count, key) 282 int count, key; 283{ 284 switch (key) 285 { 286 case 'n': 287 rl_noninc_reverse_search_again (count, key); 288 break; 289 290 case 'N': 291 rl_noninc_forward_search_again (count, key); 292 break; 293 } 294 return (0); 295} 296 297/* Do a vi style search. */ 298int 299rl_vi_search (count, key) 300 int count, key; 301{ 302 switch (key) 303 { 304 case '?': 305 _rl_free_saved_history_line (); 306 rl_noninc_forward_search (count, key); 307 break; 308 309 case '/': 310 _rl_free_saved_history_line (); 311 rl_noninc_reverse_search (count, key); 312 break; 313 314 default: 315 rl_ding (); 316 break; 317 } 318 return (0); 319} 320 321/* Completion, from vi's point of view. */ 322int 323rl_vi_complete (ignore, key) 324 int ignore, key; 325{ 326 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) 327 { 328 if (!whitespace (rl_line_buffer[rl_point + 1])) 329 rl_vi_end_word (1, 'E'); 330 rl_point++; 331 } 332 333 if (key == '*') 334 rl_complete_internal ('*'); /* Expansion and replacement. */ 335 else if (key == '=') 336 rl_complete_internal ('?'); /* List possible completions. */ 337 else if (key == '\\') 338 rl_complete_internal (TAB); /* Standard Readline completion. */ 339 else 340 rl_complete (0, key); 341 342 if (key == '*' || key == '\\') 343 rl_vi_start_inserting (key, 1, rl_arg_sign); 344 345 return (0); 346} 347 348/* Tilde expansion for vi mode. */ 349int 350rl_vi_tilde_expand (ignore, key) 351 int ignore, key; 352{ 353 rl_tilde_expand (0, key); 354 rl_vi_start_inserting (key, 1, rl_arg_sign); 355 return (0); 356} 357 358/* Previous word in vi mode. */ 359int 360rl_vi_prev_word (count, key) 361 int count, key; 362{ 363 if (count < 0) 364 return (rl_vi_next_word (-count, key)); 365 366 if (rl_point == 0) 367 { 368 rl_ding (); 369 return (0); 370 } 371 372 if (_rl_uppercase_p (key)) 373 rl_vi_bWord (count, key); 374 else 375 rl_vi_bword (count, key); 376 377 return (0); 378} 379 380/* Next word in vi mode. */ 381int 382rl_vi_next_word (count, key) 383 int count, key; 384{ 385 if (count < 0) 386 return (rl_vi_prev_word (-count, key)); 387 388 if (rl_point >= (rl_end - 1)) 389 { 390 rl_ding (); 391 return (0); 392 } 393 394 if (_rl_uppercase_p (key)) 395 rl_vi_fWord (count, key); 396 else 397 rl_vi_fword (count, key); 398 return (0); 399} 400 401/* Move to the end of the ?next? word. */ 402int 403rl_vi_end_word (count, key) 404 int count, key; 405{ 406 if (count < 0) 407 { 408 rl_ding (); 409 return -1; 410 } 411 412 if (_rl_uppercase_p (key)) 413 rl_vi_eWord (count, key); 414 else 415 rl_vi_eword (count, key); 416 return (0); 417} 418 419/* Move forward a word the way that 'W' does. */ 420int 421rl_vi_fWord (count, ignore) 422 int count, ignore; 423{ 424 while (count-- && rl_point < (rl_end - 1)) 425 { 426 /* Skip until whitespace. */ 427 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 428 rl_point++; 429 430 /* Now skip whitespace. */ 431 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 432 rl_point++; 433 } 434 return (0); 435} 436 437int 438rl_vi_bWord (count, ignore) 439 int count, ignore; 440{ 441 while (count-- && rl_point > 0) 442 { 443 /* If we are at the start of a word, move back to whitespace so 444 we will go back to the start of the previous word. */ 445 if (!whitespace (rl_line_buffer[rl_point]) && 446 whitespace (rl_line_buffer[rl_point - 1])) 447 rl_point--; 448 449 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 450 rl_point--; 451 452 if (rl_point > 0) 453 { 454 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); 455 rl_point++; 456 } 457 } 458 return (0); 459} 460 461int 462rl_vi_eWord (count, ignore) 463 int count, ignore; 464{ 465 while (count-- && rl_point < (rl_end - 1)) 466 { 467 if (!whitespace (rl_line_buffer[rl_point])) 468 rl_point++; 469 470 /* Move to the next non-whitespace character (to the start of the 471 next word). */ 472 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 473 rl_point++; 474 475 if (rl_point && rl_point < rl_end) 476 { 477 /* Skip whitespace. */ 478 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 479 rl_point++; 480 481 /* Skip until whitespace. */ 482 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) 483 rl_point++; 484 485 /* Move back to the last character of the word. */ 486 rl_point--; 487 } 488 } 489 return (0); 490} 491 492int 493rl_vi_fword (count, ignore) 494 int count, ignore; 495{ 496 while (count-- && rl_point < (rl_end - 1)) 497 { 498 /* Move to white space (really non-identifer). */ 499 if (_rl_isident (rl_line_buffer[rl_point])) 500 { 501 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) 502 rl_point++; 503 } 504 else /* if (!whitespace (rl_line_buffer[rl_point])) */ 505 { 506 while (!_rl_isident (rl_line_buffer[rl_point]) && 507 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 508 rl_point++; 509 } 510 511 /* Move past whitespace. */ 512 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 513 rl_point++; 514 } 515 return (0); 516} 517 518int 519rl_vi_bword (count, ignore) 520 int count, ignore; 521{ 522 while (count-- && rl_point > 0) 523 { 524 int last_is_ident; 525 526 /* If we are at the start of a word, move back to whitespace 527 so we will go back to the start of the previous word. */ 528 if (!whitespace (rl_line_buffer[rl_point]) && 529 whitespace (rl_line_buffer[rl_point - 1])) 530 rl_point--; 531 532 /* If this character and the previous character are `opposite', move 533 back so we don't get messed up by the rl_point++ down there in 534 the while loop. Without this code, words like `l;' screw up the 535 function. */ 536 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); 537 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || 538 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) 539 rl_point--; 540 541 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 542 rl_point--; 543 544 if (rl_point > 0) 545 { 546 if (_rl_isident (rl_line_buffer[rl_point])) 547 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); 548 else 549 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && 550 !whitespace (rl_line_buffer[rl_point])); 551 rl_point++; 552 } 553 } 554 return (0); 555} 556 557int 558rl_vi_eword (count, ignore) 559 int count, ignore; 560{ 561 while (count-- && rl_point < rl_end - 1) 562 { 563 if (!whitespace (rl_line_buffer[rl_point])) 564 rl_point++; 565 566 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 567 rl_point++; 568 569 if (rl_point < rl_end) 570 { 571 if (_rl_isident (rl_line_buffer[rl_point])) 572 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); 573 else 574 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) 575 && !whitespace (rl_line_buffer[rl_point])); 576 } 577 rl_point--; 578 } 579 return (0); 580} 581 582int 583rl_vi_insert_beg (count, key) 584 int count, key; 585{ 586 rl_beg_of_line (1, key); 587 rl_vi_insertion_mode (1, key); 588 return (0); 589} 590 591static void 592_rl_vi_append_forward (key) 593 int key; 594{ 595 int point; 596 597 if (rl_point < rl_end) 598 { 599 if (MB_CUR_MAX == 1 || rl_byte_oriented) 600 rl_point++; 601 else 602 { 603 point = rl_point; 604 rl_forward_char (1, key); 605 if (point == rl_point) 606 rl_point = rl_end; 607 } 608 } 609} 610 611int 612rl_vi_append_mode (count, key) 613 int count, key; 614{ 615 _rl_vi_append_forward (key); 616 rl_vi_start_inserting (key, 1, rl_arg_sign); 617 return (0); 618} 619 620int 621rl_vi_append_eol (count, key) 622 int count, key; 623{ 624 rl_end_of_line (1, key); 625 rl_vi_append_mode (1, key); 626 return (0); 627} 628 629/* What to do in the case of C-d. */ 630int 631rl_vi_eof_maybe (count, c) 632 int count, c; 633{ 634 return (rl_newline (1, '\n')); 635} 636 637/* Insertion mode stuff. */ 638 639/* Switching from one mode to the other really just involves 640 switching keymaps. */ 641int 642rl_vi_insertion_mode (count, key) 643 int count, key; 644{ 645 _rl_keymap = vi_insertion_keymap; 646 _rl_vi_last_key_before_insert = key; 647 return (0); 648} 649 650static void 651_rl_vi_save_insert (up) 652 UNDO_LIST *up; 653{ 654 int len, start, end; 655 656 if (up == 0 || up->what != UNDO_INSERT) 657 { 658 if (vi_insert_buffer_size >= 1) 659 vi_insert_buffer[0] = '\0'; 660 return; 661 } 662 663 start = up->start; 664 end = up->end; 665 len = end - start + 1; 666 if (len >= vi_insert_buffer_size) 667 { 668 vi_insert_buffer_size += (len + 32) - (len % 32); 669 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); 670 } 671 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); 672 vi_insert_buffer[len-1] = '\0'; 673} 674 675void 676_rl_vi_done_inserting () 677{ 678 if (_rl_vi_doing_insert) 679 { 680 /* The `C', `s', and `S' commands set this. */ 681 rl_end_undo_group (); 682 /* Now, the text between rl_undo_list->next->start and 683 rl_undo_list->next->end is what was inserted while in insert 684 mode. It gets copied to VI_INSERT_BUFFER because it depends 685 on absolute indices into the line which may change (though they 686 probably will not). */ 687 _rl_vi_doing_insert = 0; 688 _rl_vi_save_insert (rl_undo_list->next); 689 vi_continued_command = 1; 690 } 691 else 692 { 693 if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list) 694 _rl_vi_save_insert (rl_undo_list); 695 /* XXX - Other keys probably need to be checked. */ 696 else if (_rl_vi_last_key_before_insert == 'C') 697 rl_end_undo_group (); 698 while (_rl_undo_group_level > 0) 699 rl_end_undo_group (); 700 vi_continued_command = 0; 701 } 702} 703 704int 705rl_vi_movement_mode (count, key) 706 int count, key; 707{ 708 if (rl_point > 0) 709 rl_backward_char (1, key); 710 711 _rl_keymap = vi_movement_keymap; 712 _rl_vi_done_inserting (); 713 714 /* This is how POSIX.2 says `U' should behave -- everything up until the 715 first time you go into command mode should not be undone. */ 716 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0) 717 rl_free_undo_list (); 718 719 RL_SETSTATE (RL_STATE_VICMDONCE); 720 return (0); 721} 722 723int 724rl_vi_arg_digit (count, c) 725 int count, c; 726{ 727 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) 728 return (rl_beg_of_line (1, c)); 729 else 730 return (rl_digit_argument (count, c)); 731} 732 733/* Change the case of the next COUNT characters. */ 734#if defined (HANDLE_MULTIBYTE) 735static int 736_rl_vi_change_mbchar_case (count) 737 int count; 738{ 739 wchar_t wc; 740 char mb[MB_LEN_MAX+1]; 741 int mlen, p; 742 mbstate_t ps; 743 744 memset (&ps, 0, sizeof (mbstate_t)); 745 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) 746 count--; 747 while (count-- && rl_point < rl_end) 748 { 749 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); 750 if (iswupper (wc)) 751 wc = towlower (wc); 752 else if (iswlower (wc)) 753 wc = towupper (wc); 754 else 755 { 756 /* Just skip over chars neither upper nor lower case */ 757 rl_forward_char (1, 0); 758 continue; 759 } 760 761 /* Vi is kind of strange here. */ 762 if (wc) 763 { 764 p = rl_point; 765 mlen = wcrtomb (mb, wc, &ps); 766 if (mlen >= 0) 767 mb[mlen] = '\0'; 768 rl_begin_undo_group (); 769 rl_vi_delete (1, 0); 770 if (rl_point < p) /* Did we retreat at EOL? */ 771 rl_point++; /* XXX - should we advance more than 1 for mbchar? */ 772 rl_insert_text (mb); 773 rl_end_undo_group (); 774 rl_vi_check (); 775 } 776 else 777 rl_forward_char (1, 0); 778 } 779 780 return 0; 781} 782#endif 783 784int 785rl_vi_change_case (count, ignore) 786 int count, ignore; 787{ 788 int c, p; 789 790 /* Don't try this on an empty line. */ 791 if (rl_point >= rl_end) 792 return (0); 793 794 c = 0; 795#if defined (HANDLE_MULTIBYTE) 796 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 797 return (_rl_vi_change_mbchar_case (count)); 798#endif 799 800 while (count-- && rl_point < rl_end) 801 { 802 if (_rl_uppercase_p (rl_line_buffer[rl_point])) 803 c = _rl_to_lower (rl_line_buffer[rl_point]); 804 else if (_rl_lowercase_p (rl_line_buffer[rl_point])) 805 c = _rl_to_upper (rl_line_buffer[rl_point]); 806 else 807 { 808 /* Just skip over characters neither upper nor lower case. */ 809 rl_forward_char (1, c); 810 continue; 811 } 812 813 /* Vi is kind of strange here. */ 814 if (c) 815 { 816 p = rl_point; 817 rl_begin_undo_group (); 818 rl_vi_delete (1, c); 819 if (rl_point < p) /* Did we retreat at EOL? */ 820 rl_point++; 821 _rl_insert_char (1, c); 822 rl_end_undo_group (); 823 rl_vi_check (); 824 } 825 else 826 rl_forward_char (1, c); 827 } 828 return (0); 829} 830 831int 832rl_vi_put (count, key) 833 int count, key; 834{ 835 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 836 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 837 838 while (count--) 839 rl_yank (1, key); 840 841 rl_backward_char (1, key); 842 return (0); 843} 844 845static void 846_rl_vi_backup () 847{ 848 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 849 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 850 else 851 rl_point--; 852} 853 854int 855rl_vi_check () 856{ 857 if (rl_point && rl_point == rl_end) 858 { 859 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 860 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 861 else 862 rl_point--; 863 } 864 return (0); 865} 866 867int 868rl_vi_column (count, key) 869 int count, key; 870{ 871 if (count > rl_end) 872 rl_end_of_line (1, key); 873 else 874 rl_point = count - 1; 875 return (0); 876} 877 878int 879rl_vi_domove (key, nextkey) 880 int key, *nextkey; 881{ 882 int c, save; 883 int old_end; 884 885 rl_mark = rl_point; 886 RL_SETSTATE(RL_STATE_MOREINPUT); 887 c = rl_read_key (); 888 RL_UNSETSTATE(RL_STATE_MOREINPUT); 889 890 if (c < 0) 891 { 892 *nextkey = 0; 893 return -1; 894 } 895 896 *nextkey = c; 897 898 if (!member (c, vi_motion)) 899 { 900 if (_rl_digit_p (c)) 901 { 902 save = rl_numeric_arg; 903 rl_numeric_arg = _rl_digit_value (c); 904 rl_explicit_arg = 1; 905 RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION); 906 rl_digit_loop1 (); 907 RL_UNSETSTATE (RL_STATE_VIMOTION); 908 rl_numeric_arg *= save; 909 RL_SETSTATE(RL_STATE_MOREINPUT); 910 c = rl_read_key (); /* real command */ 911 RL_UNSETSTATE(RL_STATE_MOREINPUT); 912 if (c < 0) 913 { 914 *nextkey = 0; 915 return -1; 916 } 917 *nextkey = c; 918 } 919 else if (key == c && (key == 'd' || key == 'y' || key == 'c')) 920 { 921 rl_mark = rl_end; 922 rl_beg_of_line (1, c); 923 _rl_vi_last_motion = c; 924 return (0); 925 } 926 else 927 return (-1); 928 } 929 930 _rl_vi_last_motion = c; 931 932 /* Append a blank character temporarily so that the motion routines 933 work right at the end of the line. */ 934 old_end = rl_end; 935 rl_line_buffer[rl_end++] = ' '; 936 rl_line_buffer[rl_end] = '\0'; 937 938 _rl_dispatch (c, _rl_keymap); 939 940 /* Remove the blank that we added. */ 941 rl_end = old_end; 942 rl_line_buffer[rl_end] = '\0'; 943 if (rl_point > rl_end) 944 rl_point = rl_end; 945 946 /* No change in position means the command failed. */ 947 if (rl_mark == rl_point) 948 return (-1); 949 950 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next 951 word. If we are not at the end of the line, and we are on a 952 non-whitespace character, move back one (presumably to whitespace). */ 953 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && 954 !whitespace (rl_line_buffer[rl_point])) 955 rl_point--; 956 957 /* If cw or cW, back up to the end of a word, so the behaviour of ce 958 or cE is the actual result. Brute-force, no subtlety. */ 959 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) 960 { 961 /* Don't move farther back than where we started. */ 962 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) 963 rl_point--; 964 965 /* Posix.2 says that if cw or cW moves the cursor towards the end of 966 the line, the character under the cursor should be deleted. */ 967 if (rl_point == rl_mark) 968 rl_point++; 969 else 970 { 971 /* Move past the end of the word so that the kill doesn't 972 remove the last letter of the previous word. Only do this 973 if we are not at the end of the line. */ 974 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) 975 rl_point++; 976 } 977 } 978 979 if (rl_mark < rl_point) 980 SWAP (rl_point, rl_mark); 981 982 return (0); 983} 984 985/* Process C as part of the current numeric argument. Return -1 if the 986 argument should be aborted, 0 if we should not read any more chars, and 987 1 if we should continue to read chars. */ 988static int 989_rl_vi_arg_dispatch (c) 990 int c; 991{ 992 int key; 993 994 key = c; 995 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) 996 { 997 rl_numeric_arg *= 4; 998 return 1; 999 } 1000 1001 c = UNMETA (c); 1002 1003 if (_rl_digit_p (c)) 1004 { 1005 if (rl_explicit_arg) 1006 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); 1007 else 1008 rl_numeric_arg = _rl_digit_value (c); 1009 rl_explicit_arg = 1; 1010 return 1; 1011 } 1012 else 1013 { 1014 rl_clear_message (); 1015 rl_stuff_char (key); 1016 return 0; 1017 } 1018} 1019 1020/* A simplified loop for vi. Don't dispatch key at end. 1021 Don't recognize minus sign? 1022 Should this do rl_save_prompt/rl_restore_prompt? */ 1023static int 1024rl_digit_loop1 () 1025{ 1026 int c, r; 1027 1028 while (1) 1029 { 1030 if (_rl_arg_overflow ()) 1031 return 1; 1032 1033 c = _rl_arg_getchar (); 1034 1035 r = _rl_vi_arg_dispatch (c); 1036 if (r <= 0) 1037 break; 1038 } 1039 1040 RL_UNSETSTATE(RL_STATE_NUMERICARG); 1041 return (0); 1042} 1043 1044int 1045rl_vi_delete_to (count, key) 1046 int count, key; 1047{ 1048 int c; 1049 1050 if (_rl_uppercase_p (key)) 1051 rl_stuff_char ('$'); 1052 else if (vi_redoing) 1053 rl_stuff_char (_rl_vi_last_motion); 1054 1055 if (rl_vi_domove (key, &c)) 1056 { 1057 rl_ding (); 1058 return -1; 1059 } 1060 1061 /* These are the motion commands that do not require adjusting the 1062 mark. */ 1063 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) 1064 rl_mark++; 1065 1066 rl_kill_text (rl_point, rl_mark); 1067 return (0); 1068} 1069 1070int 1071rl_vi_change_to (count, key) 1072 int count, key; 1073{ 1074 int c, start_pos; 1075 1076 if (_rl_uppercase_p (key)) 1077 rl_stuff_char ('$'); 1078 else if (vi_redoing) 1079 rl_stuff_char (_rl_vi_last_motion); 1080 1081 start_pos = rl_point; 1082 1083 if (rl_vi_domove (key, &c)) 1084 { 1085 rl_ding (); 1086 return -1; 1087 } 1088 1089 /* These are the motion commands that do not require adjusting the 1090 mark. c[wW] are handled by special-case code in rl_vi_domove(), 1091 and already leave the mark at the correct location. */ 1092 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) 1093 rl_mark++; 1094 1095 /* The cursor never moves with c[wW]. */ 1096 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) 1097 rl_point = start_pos; 1098 1099 if (vi_redoing) 1100 { 1101 if (vi_insert_buffer && *vi_insert_buffer) 1102 rl_begin_undo_group (); 1103 rl_delete_text (rl_point, rl_mark); 1104 if (vi_insert_buffer && *vi_insert_buffer) 1105 { 1106 rl_insert_text (vi_insert_buffer); 1107 rl_end_undo_group (); 1108 } 1109 } 1110 else 1111 { 1112 rl_begin_undo_group (); /* to make the `u' command work */ 1113 rl_kill_text (rl_point, rl_mark); 1114 /* `C' does not save the text inserted for undoing or redoing. */ 1115 if (_rl_uppercase_p (key) == 0) 1116 _rl_vi_doing_insert = 1; 1117 rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign); 1118 } 1119 1120 return (0); 1121} 1122 1123int 1124rl_vi_yank_to (count, key) 1125 int count, key; 1126{ 1127 int c, save; 1128 1129 save = rl_point; 1130 if (_rl_uppercase_p (key)) 1131 rl_stuff_char ('$'); 1132 1133 if (rl_vi_domove (key, &c)) 1134 { 1135 rl_ding (); 1136 return -1; 1137 } 1138 1139 /* These are the motion commands that do not require adjusting the 1140 mark. */ 1141 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) 1142 rl_mark++; 1143 1144 rl_begin_undo_group (); 1145 rl_kill_text (rl_point, rl_mark); 1146 rl_end_undo_group (); 1147 rl_do_undo (); 1148 rl_point = save; 1149 1150 return (0); 1151} 1152 1153int 1154rl_vi_rubout (count, key) 1155 int count, key; 1156{ 1157 int opoint; 1158 1159 if (count < 0) 1160 return (rl_vi_delete (-count, key)); 1161 1162 if (rl_point == 0) 1163 { 1164 rl_ding (); 1165 return -1; 1166 } 1167 1168 opoint = rl_point; 1169 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1170 rl_backward_char (count, key); 1171 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1172 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1173 else 1174 rl_point -= count; 1175 1176 if (rl_point < 0) 1177 rl_point = 0; 1178 1179 rl_kill_text (rl_point, opoint); 1180 1181 return (0); 1182} 1183 1184int 1185rl_vi_delete (count, key) 1186 int count, key; 1187{ 1188 int end; 1189 1190 if (count < 0) 1191 return (rl_vi_rubout (-count, key)); 1192 1193 if (rl_end == 0) 1194 { 1195 rl_ding (); 1196 return -1; 1197 } 1198 1199 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1200 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 1201 else 1202 end = rl_point + count; 1203 1204 if (end >= rl_end) 1205 end = rl_end; 1206 1207 rl_kill_text (rl_point, end); 1208 1209 if (rl_point > 0 && rl_point == rl_end) 1210 rl_backward_char (1, key); 1211 1212 return (0); 1213} 1214 1215int 1216rl_vi_back_to_indent (count, key) 1217 int count, key; 1218{ 1219 rl_beg_of_line (1, key); 1220 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1221 rl_point++; 1222 return (0); 1223} 1224 1225int 1226rl_vi_first_print (count, key) 1227 int count, key; 1228{ 1229 return (rl_vi_back_to_indent (1, key)); 1230} 1231 1232static int _rl_cs_dir, _rl_cs_orig_dir; 1233 1234#if defined (READLINE_CALLBACKS) 1235static int 1236_rl_vi_callback_char_search (data) 1237 _rl_callback_generic_arg *data; 1238{ 1239 int c; 1240#if defined (HANDLE_MULTIBYTE) 1241 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); 1242#else 1243 RL_SETSTATE(RL_STATE_MOREINPUT); 1244 c = rl_read_key (); 1245 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1246#endif 1247 1248 if (c <= 0) 1249 return -1; 1250 1251#if !defined (HANDLE_MULTIBYTE) 1252 _rl_vi_last_search_char = c; 1253#endif 1254 1255 _rl_callback_func = 0; 1256 _rl_want_redisplay = 1; 1257 1258#if defined (HANDLE_MULTIBYTE) 1259 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen)); 1260#else 1261 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char)); 1262#endif 1263} 1264#endif 1265 1266int 1267rl_vi_char_search (count, key) 1268 int count, key; 1269{ 1270 int c; 1271#if defined (HANDLE_MULTIBYTE) 1272 static char *target; 1273 static int tlen; 1274#else 1275 static char target; 1276#endif 1277 1278 if (key == ';' || key == ',') 1279 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; 1280 else 1281 { 1282 switch (key) 1283 { 1284 case 't': 1285 _rl_cs_orig_dir = _rl_cs_dir = FTO; 1286 break; 1287 1288 case 'T': 1289 _rl_cs_orig_dir = _rl_cs_dir = BTO; 1290 break; 1291 1292 case 'f': 1293 _rl_cs_orig_dir = _rl_cs_dir = FFIND; 1294 break; 1295 1296 case 'F': 1297 _rl_cs_orig_dir = _rl_cs_dir = BFIND; 1298 break; 1299 } 1300 1301 if (vi_redoing) 1302 { 1303 /* set target and tlen below */ 1304 } 1305#if defined (READLINE_CALLBACKS) 1306 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1307 { 1308 _rl_callback_data = _rl_callback_data_alloc (count); 1309 _rl_callback_data->i1 = _rl_cs_dir; 1310 _rl_callback_func = _rl_vi_callback_char_search; 1311 return (0); 1312 } 1313#endif 1314 else 1315 { 1316#if defined (HANDLE_MULTIBYTE) 1317 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); 1318 if (c <= 0) 1319 return -1; 1320 _rl_vi_last_search_mblen = c; 1321#else 1322 RL_SETSTATE(RL_STATE_MOREINPUT); 1323 c = rl_read_key (); 1324 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1325 if (c < 0) 1326 return -1; 1327 _rl_vi_last_search_char = c; 1328#endif 1329 } 1330 } 1331 1332#if defined (HANDLE_MULTIBYTE) 1333 target = _rl_vi_last_search_mbchar; 1334 tlen = _rl_vi_last_search_mblen; 1335#else 1336 target = _rl_vi_last_search_char; 1337#endif 1338 1339#if defined (HANDLE_MULTIBYTE) 1340 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen)); 1341#else 1342 return (_rl_char_search_internal (count, _rl_cs_dir, target)); 1343#endif 1344} 1345 1346/* Match brackets */ 1347int 1348rl_vi_match (ignore, key) 1349 int ignore, key; 1350{ 1351 int count = 1, brack, pos, tmp, pre; 1352 1353 pos = rl_point; 1354 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 1355 { 1356 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1357 { 1358 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 1359 { 1360 pre = rl_point; 1361 rl_forward_char (1, key); 1362 if (pre == rl_point) 1363 break; 1364 } 1365 } 1366 else 1367 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && 1368 rl_point < rl_end - 1) 1369 rl_forward_char (1, key); 1370 1371 if (brack <= 0) 1372 { 1373 rl_point = pos; 1374 rl_ding (); 1375 return -1; 1376 } 1377 } 1378 1379 pos = rl_point; 1380 1381 if (brack < 0) 1382 { 1383 while (count) 1384 { 1385 tmp = pos; 1386 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1387 pos--; 1388 else 1389 { 1390 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); 1391 if (tmp == pos) 1392 pos--; 1393 } 1394 if (pos >= 0) 1395 { 1396 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1397 if (b == -brack) 1398 count--; 1399 else if (b == brack) 1400 count++; 1401 } 1402 else 1403 { 1404 rl_ding (); 1405 return -1; 1406 } 1407 } 1408 } 1409 else 1410 { /* brack > 0 */ 1411 while (count) 1412 { 1413 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1414 pos++; 1415 else 1416 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); 1417 1418 if (pos < rl_end) 1419 { 1420 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1421 if (b == -brack) 1422 count--; 1423 else if (b == brack) 1424 count++; 1425 } 1426 else 1427 { 1428 rl_ding (); 1429 return -1; 1430 } 1431 } 1432 } 1433 rl_point = pos; 1434 return (0); 1435} 1436 1437int 1438rl_vi_bracktype (c) 1439 int c; 1440{ 1441 switch (c) 1442 { 1443 case '(': return 1; 1444 case ')': return -1; 1445 case '[': return 2; 1446 case ']': return -2; 1447 case '{': return 3; 1448 case '}': return -3; 1449 default: return 0; 1450 } 1451} 1452 1453static int 1454_rl_vi_change_char (count, c, mb) 1455 int count, c; 1456 char *mb; 1457{ 1458 int p; 1459 1460 if (c == '\033' || c == CTRL ('C')) 1461 return -1; 1462 1463 rl_begin_undo_group (); 1464 while (count-- && rl_point < rl_end) 1465 { 1466 p = rl_point; 1467 rl_vi_delete (1, c); 1468 if (rl_point < p) /* Did we retreat at EOL? */ 1469 rl_point++; 1470#if defined (HANDLE_MULTIBYTE) 1471 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1472 rl_insert_text (mb); 1473 else 1474#endif 1475 _rl_insert_char (1, c); 1476 } 1477 1478 /* The cursor shall be left on the last character changed. */ 1479 rl_backward_char (1, c); 1480 1481 rl_end_undo_group (); 1482 1483 return (0); 1484} 1485 1486static int 1487_rl_vi_callback_getchar (mb, mlen) 1488 char *mb; 1489 int mlen; 1490{ 1491 int c; 1492 1493 RL_SETSTATE(RL_STATE_MOREINPUT); 1494 c = rl_read_key (); 1495 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1496 1497 if (c < 0) 1498 return -1; 1499 1500#if defined (HANDLE_MULTIBYTE) 1501 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1502 c = _rl_read_mbstring (c, mb, mlen); 1503#endif 1504 1505 return c; 1506} 1507 1508#if defined (READLINE_CALLBACKS) 1509static int 1510_rl_vi_callback_change_char (data) 1511 _rl_callback_generic_arg *data; 1512{ 1513 int c; 1514 char mb[MB_LEN_MAX]; 1515 1516 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); 1517 1518 if (c < 0) 1519 return -1; 1520 1521 _rl_callback_func = 0; 1522 _rl_want_redisplay = 1; 1523 1524 return (_rl_vi_change_char (data->count, c, mb)); 1525} 1526#endif 1527 1528int 1529rl_vi_change_char (count, key) 1530 int count, key; 1531{ 1532 int c; 1533 char mb[MB_LEN_MAX]; 1534 1535 if (vi_redoing) 1536 { 1537 c = _rl_vi_last_replacement; 1538 mb[0] = c; 1539 mb[1] = '\0'; 1540 } 1541#if defined (READLINE_CALLBACKS) 1542 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1543 { 1544 _rl_callback_data = _rl_callback_data_alloc (count); 1545 _rl_callback_func = _rl_vi_callback_change_char; 1546 return (0); 1547 } 1548#endif 1549 else 1550 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); 1551 1552 if (c < 0) 1553 return -1; 1554 1555 return (_rl_vi_change_char (count, c, mb)); 1556} 1557 1558int 1559rl_vi_subst (count, key) 1560 int count, key; 1561{ 1562 /* If we are redoing, rl_vi_change_to will stuff the last motion char */ 1563 if (vi_redoing == 0) 1564 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ 1565 1566 return (rl_vi_change_to (count, 'c')); 1567} 1568 1569int 1570rl_vi_overstrike (count, key) 1571 int count, key; 1572{ 1573 if (_rl_vi_doing_insert == 0) 1574 { 1575 _rl_vi_doing_insert = 1; 1576 rl_begin_undo_group (); 1577 } 1578 1579 if (count > 0) 1580 { 1581 _rl_overwrite_char (count, key); 1582 vi_replace_count += count; 1583 } 1584 1585 return (0); 1586} 1587 1588int 1589rl_vi_overstrike_delete (count, key) 1590 int count, key; 1591{ 1592 int i, s; 1593 1594 for (i = 0; i < count; i++) 1595 { 1596 if (vi_replace_count == 0) 1597 { 1598 rl_ding (); 1599 break; 1600 } 1601 s = rl_point; 1602 1603 if (rl_do_undo ()) 1604 vi_replace_count--; 1605 1606 if (rl_point == s) 1607 rl_backward_char (1, key); 1608 } 1609 1610 if (vi_replace_count == 0 && _rl_vi_doing_insert) 1611 { 1612 rl_end_undo_group (); 1613 rl_do_undo (); 1614 _rl_vi_doing_insert = 0; 1615 } 1616 return (0); 1617} 1618 1619int 1620rl_vi_replace (count, key) 1621 int count, key; 1622{ 1623 int i; 1624 1625 vi_replace_count = 0; 1626 1627 if (!vi_replace_map) 1628 { 1629 vi_replace_map = rl_make_bare_keymap (); 1630 1631 for (i = ' '; i < KEYMAP_SIZE; i++) 1632 vi_replace_map[i].function = rl_vi_overstrike; 1633 1634 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; 1635 vi_replace_map[ESC].function = rl_vi_movement_mode; 1636 vi_replace_map[RETURN].function = rl_newline; 1637 vi_replace_map[NEWLINE].function = rl_newline; 1638 1639 /* If the normal vi insertion keymap has ^H bound to erase, do the 1640 same here. Probably should remove the assignment to RUBOUT up 1641 there, but I don't think it will make a difference in real life. */ 1642 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && 1643 vi_insertion_keymap[CTRL ('H')].function == rl_rubout) 1644 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; 1645 1646 } 1647 _rl_keymap = vi_replace_map; 1648 return (0); 1649} 1650 1651#if 0 1652/* Try to complete the word we are standing on or the word that ends with 1653 the previous character. A space matches everything. Word delimiters are 1654 space and ;. */ 1655int 1656rl_vi_possible_completions() 1657{ 1658 int save_pos = rl_point; 1659 1660 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') 1661 { 1662 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && 1663 rl_line_buffer[rl_point] != ';') 1664 rl_point++; 1665 } 1666 else if (rl_line_buffer[rl_point - 1] == ';') 1667 { 1668 rl_ding (); 1669 return (0); 1670 } 1671 1672 rl_possible_completions (); 1673 rl_point = save_pos; 1674 1675 return (0); 1676} 1677#endif 1678 1679/* Functions to save and restore marks. */ 1680static int 1681_rl_vi_set_mark () 1682{ 1683 int ch; 1684 1685 RL_SETSTATE(RL_STATE_MOREINPUT); 1686 ch = rl_read_key (); 1687 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1688 1689 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ 1690 { 1691 rl_ding (); 1692 return -1; 1693 } 1694 ch -= 'a'; 1695 vi_mark_chars[ch] = rl_point; 1696 return 0; 1697} 1698 1699#if defined (READLINE_CALLBACKS) 1700static int 1701_rl_vi_callback_set_mark (data) 1702 _rl_callback_generic_arg *data; 1703{ 1704 _rl_callback_func = 0; 1705 _rl_want_redisplay = 1; 1706 1707 return (_rl_vi_set_mark ()); 1708} 1709#endif 1710 1711int 1712rl_vi_set_mark (count, key) 1713 int count, key; 1714{ 1715#if defined (READLINE_CALLBACKS) 1716 if (RL_ISSTATE (RL_STATE_CALLBACK)) 1717 { 1718 _rl_callback_data = 0; 1719 _rl_callback_func = _rl_vi_callback_set_mark; 1720 return (0); 1721 } 1722#endif 1723 1724 return (_rl_vi_set_mark ()); 1725} 1726 1727static int 1728_rl_vi_goto_mark () 1729{ 1730 int ch; 1731 1732 RL_SETSTATE(RL_STATE_MOREINPUT); 1733 ch = rl_read_key (); 1734 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1735 1736 if (ch == '`') 1737 { 1738 rl_point = rl_mark; 1739 return 0; 1740 } 1741 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ 1742 { 1743 rl_ding (); 1744 return -1; 1745 } 1746 1747 ch -= 'a'; 1748 if (vi_mark_chars[ch] == -1) 1749 { 1750 rl_ding (); 1751 return -1; 1752 } 1753 rl_point = vi_mark_chars[ch]; 1754 return 0; 1755} 1756 1757#if defined (READLINE_CALLBACKS) 1758static int 1759_rl_vi_callback_goto_mark (data) 1760 _rl_callback_generic_arg *data; 1761{ 1762 _rl_callback_func = 0; 1763 _rl_want_redisplay = 1; 1764 1765 return (_rl_vi_goto_mark ()); 1766} 1767#endif 1768 1769int 1770rl_vi_goto_mark (count, key) 1771 int count, key; 1772{ 1773#if defined (READLINE_CALLBACKS) 1774 if (RL_ISSTATE (RL_STATE_CALLBACK)) 1775 { 1776 _rl_callback_data = 0; 1777 _rl_callback_func = _rl_vi_callback_goto_mark; 1778 return (0); 1779 } 1780#endif 1781 1782 return (_rl_vi_goto_mark ()); 1783} 1784#endif /* VI_MODE */ 1785