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