vi_mode.c revision 75406
121308Sache/* vi_mode.c -- A vi emulation mode for Bash. 221308Sache Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ 321308Sache 421308Sache/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 521308Sache 621308Sache This file is part of the GNU Readline Library, a library for 721308Sache reading lines of text with interactive input and history editing. 821308Sache 921308Sache The GNU Readline Library is free software; you can redistribute it 1021308Sache and/or modify it under the terms of the GNU General Public License 1158310Sache as published by the Free Software Foundation; either version 2, or 1221308Sache (at your option) any later version. 1321308Sache 1421308Sache The GNU Readline Library is distributed in the hope that it will be 1521308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1621308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1721308Sache GNU General Public License for more details. 1821308Sache 1921308Sache The GNU General Public License is often shipped with GNU software, and 2021308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2121308Sache have a copy of the license, write to the Free Software Foundation, 2258310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2321308Sache#define READLINE_LIBRARY 2421308Sache 2521308Sache/* **************************************************************** */ 2621308Sache/* */ 2721308Sache/* VI Emulation Mode */ 2821308Sache/* */ 2921308Sache/* **************************************************************** */ 3021308Sache#include "rlconf.h" 3121308Sache 3221308Sache#if defined (VI_MODE) 3321308Sache 3421308Sache#if defined (HAVE_CONFIG_H) 3521308Sache# include <config.h> 3621308Sache#endif 3721308Sache 3821308Sache#include <sys/types.h> 3921308Sache 4021308Sache#if defined (HAVE_STDLIB_H) 4121308Sache# include <stdlib.h> 4221308Sache#else 4321308Sache# include "ansi_stdlib.h" 4421308Sache#endif /* HAVE_STDLIB_H */ 4521308Sache 4621308Sache#if defined (HAVE_UNISTD_H) 4721308Sache# include <unistd.h> 4821308Sache#endif 4921308Sache 5021308Sache#include <stdio.h> 5121308Sache 5221308Sache/* Some standard library routines. */ 5321308Sache#include "rldefs.h" 5421308Sache#include "readline.h" 5521308Sache#include "history.h" 5621308Sache 5758310Sache#include "rlprivate.h" 5858310Sache#include "xmalloc.h" 5958310Sache 6021308Sache#ifndef _rl_digit_p 6121308Sache#define _rl_digit_p(c) ((c) >= '0' && (c) <= '9') 6221308Sache#endif 6321308Sache 6421308Sache#ifndef _rl_digit_value 6521308Sache#define _rl_digit_value(c) ((c) - '0') 6621308Sache#endif 6721308Sache 6821308Sache#ifndef member 6921308Sache#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 7021308Sache#endif 7121308Sache 7221308Sache#ifndef isident 7321308Sache#define isident(c) ((_rl_pure_alphabetic (c) || _rl_digit_p (c) || c == '_')) 7421308Sache#endif 7521308Sache 7621308Sache#ifndef exchange 7721308Sache#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0) 7821308Sache#endif 7921308Sache 8021308Sache/* Non-zero means enter insertion mode. */ 8121308Sachestatic int _rl_vi_doing_insert; 8221308Sache 8321308Sache/* Command keys which do movement for xxx_to commands. */ 8475406Sachestatic const char *vi_motion = " hl^$0ftFt;,%wbeWBE|"; 8521308Sache 8621308Sache/* Keymap used for vi replace characters. Created dynamically since 8721308Sache rarely used. */ 8821308Sachestatic Keymap vi_replace_map; 8921308Sache 9021308Sache/* The number of characters inserted in the last replace operation. */ 9121308Sachestatic int vi_replace_count; 9221308Sache 9321308Sache/* If non-zero, we have text inserted after a c[motion] command that put 9421308Sache us implicitly into insert mode. Some people want this text to be 9521308Sache attached to the command so that it is `redoable' with `.'. */ 9621308Sachestatic int vi_continued_command; 9721308Sachestatic char *vi_insert_buffer; 9821308Sachestatic int vi_insert_buffer_size; 9921308Sache 10021308Sachestatic int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ 10121308Sachestatic int _rl_vi_last_repeat = 1; 10221308Sachestatic int _rl_vi_last_arg_sign = 1; 10321308Sachestatic int _rl_vi_last_motion; 10421308Sachestatic int _rl_vi_last_search_char; 10521308Sachestatic int _rl_vi_last_replacement; 10621308Sache 10721308Sachestatic int _rl_vi_last_key_before_insert; 10821308Sache 10921308Sachestatic int vi_redoing; 11021308Sache 11121308Sache/* Text modification commands. These are the `redoable' commands. */ 11275406Sachestatic const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; 11321308Sache 11421308Sache/* Arrays for the saved marks. */ 11521308Sachestatic int vi_mark_chars[27]; 11621308Sache 11758310Sachestatic int rl_digit_loop1 __P((void)); 11821308Sache 11921308Sachevoid 12021308Sache_rl_vi_initialize_line () 12121308Sache{ 12221308Sache register int i; 12321308Sache 12421308Sache for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) 12521308Sache vi_mark_chars[i] = -1; 12621308Sache} 12721308Sache 12821308Sachevoid 12921308Sache_rl_vi_reset_last () 13021308Sache{ 13121308Sache _rl_vi_last_command = 'i'; 13221308Sache _rl_vi_last_repeat = 1; 13321308Sache _rl_vi_last_arg_sign = 1; 13421308Sache _rl_vi_last_motion = 0; 13521308Sache} 13621308Sache 13721308Sachevoid 13821308Sache_rl_vi_set_last (key, repeat, sign) 13921308Sache int key, repeat, sign; 14021308Sache{ 14121308Sache _rl_vi_last_command = key; 14221308Sache _rl_vi_last_repeat = repeat; 14321308Sache _rl_vi_last_arg_sign = sign; 14421308Sache} 14521308Sache 14621308Sache/* Is the command C a VI mode text modification command? */ 14721308Sacheint 14821308Sache_rl_vi_textmod_command (c) 14921308Sache int c; 15021308Sache{ 15121308Sache return (member (c, vi_textmod)); 15221308Sache} 15321308Sache 15421308Sachestatic void 15521308Sache_rl_vi_stuff_insert (count) 15621308Sache int count; 15721308Sache{ 15821308Sache rl_begin_undo_group (); 15921308Sache while (count--) 16021308Sache rl_insert_text (vi_insert_buffer); 16121308Sache rl_end_undo_group (); 16221308Sache} 16321308Sache 16421308Sache/* Bound to `.'. Called from command mode, so we know that we have to 16521308Sache redo a text modification command. The default for _rl_vi_last_command 16621308Sache puts you back into insert mode. */ 16721308Sacheint 16821308Sacherl_vi_redo (count, c) 16921308Sache int count, c; 17021308Sache{ 17121308Sache if (!rl_explicit_arg) 17221308Sache { 17321308Sache rl_numeric_arg = _rl_vi_last_repeat; 17421308Sache rl_arg_sign = _rl_vi_last_arg_sign; 17521308Sache } 17621308Sache 17721308Sache vi_redoing = 1; 17821308Sache /* If we're redoing an insert with `i', stuff in the inserted text 17921308Sache and do not go into insertion mode. */ 18021308Sache if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) 18121308Sache { 18221308Sache _rl_vi_stuff_insert (count); 18321308Sache /* And back up point over the last character inserted. */ 18421308Sache if (rl_point > 0) 18521308Sache rl_point--; 18621308Sache } 18721308Sache else 18821308Sache _rl_dispatch (_rl_vi_last_command, _rl_keymap); 18921308Sache vi_redoing = 0; 19021308Sache 19121308Sache return (0); 19221308Sache} 19321308Sache 19421308Sache/* A placeholder for further expansion. */ 19521308Sacheint 19621308Sacherl_vi_undo (count, key) 19721308Sache int count, key; 19821308Sache{ 19921308Sache return (rl_undo_command (count, key)); 20021308Sache} 20121308Sache 20221308Sache/* Yank the nth arg from the previous line into this line at point. */ 20321308Sacheint 20421308Sacherl_vi_yank_arg (count, key) 20521308Sache int count, key; 20621308Sache{ 20721308Sache /* Readline thinks that the first word on a line is the 0th, while vi 20821308Sache thinks the first word on a line is the 1st. Compensate. */ 20921308Sache if (rl_explicit_arg) 21021308Sache rl_yank_nth_arg (count - 1, 0); 21121308Sache else 21221308Sache rl_yank_nth_arg ('$', 0); 21321308Sache 21421308Sache return (0); 21521308Sache} 21621308Sache 21721308Sache/* With an argument, move back that many history lines, else move to the 21821308Sache beginning of history. */ 21921308Sacheint 22021308Sacherl_vi_fetch_history (count, c) 22121308Sache int count, c; 22221308Sache{ 22321308Sache int wanted; 22421308Sache 22521308Sache /* Giving an argument of n means we want the nth command in the history 22621308Sache file. The command number is interpreted the same way that the bash 22721308Sache `history' command does it -- that is, giving an argument count of 450 22821308Sache to this command would get the command listed as number 450 in the 22921308Sache output of `history'. */ 23021308Sache if (rl_explicit_arg) 23121308Sache { 23221308Sache wanted = history_base + where_history () - count; 23321308Sache if (wanted <= 0) 23421308Sache rl_beginning_of_history (0, 0); 23521308Sache else 23621308Sache rl_get_previous_history (wanted, c); 23721308Sache } 23821308Sache else 23921308Sache rl_beginning_of_history (count, 0); 24021308Sache return (0); 24121308Sache} 24221308Sache 24321308Sache/* Search again for the last thing searched for. */ 24421308Sacheint 24521308Sacherl_vi_search_again (count, key) 24621308Sache int count, key; 24721308Sache{ 24821308Sache switch (key) 24921308Sache { 25021308Sache case 'n': 25121308Sache rl_noninc_reverse_search_again (count, key); 25221308Sache break; 25321308Sache 25421308Sache case 'N': 25521308Sache rl_noninc_forward_search_again (count, key); 25621308Sache break; 25721308Sache } 25821308Sache return (0); 25921308Sache} 26021308Sache 26121308Sache/* Do a vi style search. */ 26221308Sacheint 26321308Sacherl_vi_search (count, key) 26421308Sache int count, key; 26521308Sache{ 26621308Sache switch (key) 26721308Sache { 26821308Sache case '?': 26921308Sache rl_noninc_forward_search (count, key); 27021308Sache break; 27121308Sache 27221308Sache case '/': 27321308Sache rl_noninc_reverse_search (count, key); 27421308Sache break; 27521308Sache 27621308Sache default: 27775406Sache rl_ding (); 27821308Sache break; 27921308Sache } 28021308Sache return (0); 28121308Sache} 28221308Sache 28321308Sache/* Completion, from vi's point of view. */ 28421308Sacheint 28521308Sacherl_vi_complete (ignore, key) 28621308Sache int ignore, key; 28721308Sache{ 28821308Sache if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) 28921308Sache { 29021308Sache if (!whitespace (rl_line_buffer[rl_point + 1])) 29121308Sache rl_vi_end_word (1, 'E'); 29221308Sache rl_point++; 29321308Sache } 29421308Sache 29521308Sache if (key == '*') 29621308Sache rl_complete_internal ('*'); /* Expansion and replacement. */ 29721308Sache else if (key == '=') 29821308Sache rl_complete_internal ('?'); /* List possible completions. */ 29921308Sache else if (key == '\\') 30021308Sache rl_complete_internal (TAB); /* Standard Readline completion. */ 30121308Sache else 30221308Sache rl_complete (0, key); 30321308Sache 30421308Sache if (key == '*' || key == '\\') 30521308Sache { 30621308Sache _rl_vi_set_last (key, 1, rl_arg_sign); 30721308Sache rl_vi_insertion_mode (1, key); 30821308Sache } 30921308Sache return (0); 31021308Sache} 31121308Sache 31221308Sache/* Tilde expansion for vi mode. */ 31321308Sacheint 31421308Sacherl_vi_tilde_expand (ignore, key) 31521308Sache int ignore, key; 31621308Sache{ 31721308Sache rl_tilde_expand (0, key); 31821308Sache _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ 31921308Sache rl_vi_insertion_mode (1, key); 32021308Sache return (0); 32121308Sache} 32221308Sache 32321308Sache/* Previous word in vi mode. */ 32421308Sacheint 32521308Sacherl_vi_prev_word (count, key) 32621308Sache int count, key; 32721308Sache{ 32821308Sache if (count < 0) 32921308Sache return (rl_vi_next_word (-count, key)); 33021308Sache 33121308Sache if (rl_point == 0) 33221308Sache { 33375406Sache rl_ding (); 33421308Sache return (0); 33521308Sache } 33621308Sache 33721308Sache if (_rl_uppercase_p (key)) 33847558Sache rl_vi_bWord (count, key); 33921308Sache else 34047558Sache rl_vi_bword (count, key); 34121308Sache 34221308Sache return (0); 34321308Sache} 34421308Sache 34521308Sache/* Next word in vi mode. */ 34621308Sacheint 34721308Sacherl_vi_next_word (count, key) 34821308Sache int count, key; 34921308Sache{ 35021308Sache if (count < 0) 35121308Sache return (rl_vi_prev_word (-count, key)); 35221308Sache 35321308Sache if (rl_point >= (rl_end - 1)) 35421308Sache { 35575406Sache rl_ding (); 35621308Sache return (0); 35721308Sache } 35821308Sache 35921308Sache if (_rl_uppercase_p (key)) 36047558Sache rl_vi_fWord (count, key); 36121308Sache else 36247558Sache rl_vi_fword (count, key); 36321308Sache return (0); 36421308Sache} 36521308Sache 36621308Sache/* Move to the end of the ?next? word. */ 36721308Sacheint 36821308Sacherl_vi_end_word (count, key) 36921308Sache int count, key; 37021308Sache{ 37121308Sache if (count < 0) 37221308Sache { 37375406Sache rl_ding (); 37421308Sache return -1; 37521308Sache } 37621308Sache 37721308Sache if (_rl_uppercase_p (key)) 37847558Sache rl_vi_eWord (count, key); 37921308Sache else 38047558Sache rl_vi_eword (count, key); 38121308Sache return (0); 38221308Sache} 38321308Sache 38421308Sache/* Move forward a word the way that 'W' does. */ 38521308Sacheint 38647558Sacherl_vi_fWord (count, ignore) 38747558Sache int count, ignore; 38821308Sache{ 38921308Sache while (count-- && rl_point < (rl_end - 1)) 39021308Sache { 39121308Sache /* Skip until whitespace. */ 39221308Sache while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 39321308Sache rl_point++; 39421308Sache 39521308Sache /* Now skip whitespace. */ 39621308Sache while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 39721308Sache rl_point++; 39821308Sache } 39921308Sache return (0); 40021308Sache} 40121308Sache 40221308Sacheint 40347558Sacherl_vi_bWord (count, ignore) 40447558Sache int count, ignore; 40521308Sache{ 40621308Sache while (count-- && rl_point > 0) 40721308Sache { 40821308Sache /* If we are at the start of a word, move back to whitespace so 40921308Sache we will go back to the start of the previous word. */ 41021308Sache if (!whitespace (rl_line_buffer[rl_point]) && 41121308Sache whitespace (rl_line_buffer[rl_point - 1])) 41221308Sache rl_point--; 41321308Sache 41421308Sache while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 41521308Sache rl_point--; 41621308Sache 41721308Sache if (rl_point > 0) 41821308Sache { 41921308Sache while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); 42021308Sache rl_point++; 42121308Sache } 42221308Sache } 42321308Sache return (0); 42421308Sache} 42521308Sache 42621308Sacheint 42747558Sacherl_vi_eWord (count, ignore) 42847558Sache int count, ignore; 42921308Sache{ 43021308Sache while (count-- && rl_point < (rl_end - 1)) 43121308Sache { 43221308Sache if (!whitespace (rl_line_buffer[rl_point])) 43321308Sache rl_point++; 43421308Sache 43521308Sache /* Move to the next non-whitespace character (to the start of the 43621308Sache next word). */ 43721308Sache while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])); 43821308Sache 43921308Sache if (rl_point && rl_point < rl_end) 44021308Sache { 44121308Sache /* Skip whitespace. */ 44221308Sache while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 44321308Sache rl_point++; 44421308Sache 44521308Sache /* Skip until whitespace. */ 44621308Sache while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) 44721308Sache rl_point++; 44821308Sache 44921308Sache /* Move back to the last character of the word. */ 45021308Sache rl_point--; 45121308Sache } 45221308Sache } 45321308Sache return (0); 45421308Sache} 45521308Sache 45621308Sacheint 45747558Sacherl_vi_fword (count, ignore) 45847558Sache int count, ignore; 45921308Sache{ 46021308Sache while (count-- && rl_point < (rl_end - 1)) 46121308Sache { 46221308Sache /* Move to white space (really non-identifer). */ 46321308Sache if (isident (rl_line_buffer[rl_point])) 46421308Sache { 46521308Sache while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) 46621308Sache rl_point++; 46721308Sache } 46821308Sache else /* if (!whitespace (rl_line_buffer[rl_point])) */ 46921308Sache { 47021308Sache while (!isident (rl_line_buffer[rl_point]) && 47121308Sache !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 47221308Sache rl_point++; 47321308Sache } 47421308Sache 47521308Sache /* Move past whitespace. */ 47621308Sache while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 47721308Sache rl_point++; 47821308Sache } 47921308Sache return (0); 48021308Sache} 48121308Sache 48221308Sacheint 48347558Sacherl_vi_bword (count, ignore) 48447558Sache int count, ignore; 48521308Sache{ 48621308Sache while (count-- && rl_point > 0) 48721308Sache { 48821308Sache int last_is_ident; 48921308Sache 49021308Sache /* If we are at the start of a word, move back to whitespace 49121308Sache so we will go back to the start of the previous word. */ 49221308Sache if (!whitespace (rl_line_buffer[rl_point]) && 49321308Sache whitespace (rl_line_buffer[rl_point - 1])) 49421308Sache rl_point--; 49521308Sache 49621308Sache /* If this character and the previous character are `opposite', move 49721308Sache back so we don't get messed up by the rl_point++ down there in 49821308Sache the while loop. Without this code, words like `l;' screw up the 49921308Sache function. */ 50021308Sache last_is_ident = isident (rl_line_buffer[rl_point - 1]); 50121308Sache if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || 50221308Sache (!isident (rl_line_buffer[rl_point]) && last_is_ident)) 50321308Sache rl_point--; 50421308Sache 50521308Sache while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 50621308Sache rl_point--; 50721308Sache 50821308Sache if (rl_point > 0) 50921308Sache { 51021308Sache if (isident (rl_line_buffer[rl_point])) 51121308Sache while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); 51221308Sache else 51321308Sache while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && 51421308Sache !whitespace (rl_line_buffer[rl_point])); 51521308Sache rl_point++; 51621308Sache } 51721308Sache } 51821308Sache return (0); 51921308Sache} 52021308Sache 52121308Sacheint 52247558Sacherl_vi_eword (count, ignore) 52347558Sache int count, ignore; 52421308Sache{ 52521308Sache while (count-- && rl_point < rl_end - 1) 52621308Sache { 52721308Sache if (!whitespace (rl_line_buffer[rl_point])) 52821308Sache rl_point++; 52921308Sache 53021308Sache while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 53121308Sache rl_point++; 53221308Sache 53321308Sache if (rl_point < rl_end) 53421308Sache { 53521308Sache if (isident (rl_line_buffer[rl_point])) 53621308Sache while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); 53721308Sache else 53821308Sache while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) 53921308Sache && !whitespace (rl_line_buffer[rl_point])); 54021308Sache } 54121308Sache rl_point--; 54221308Sache } 54321308Sache return (0); 54421308Sache} 54521308Sache 54621308Sacheint 54721308Sacherl_vi_insert_beg (count, key) 54821308Sache int count, key; 54921308Sache{ 55021308Sache rl_beg_of_line (1, key); 55121308Sache rl_vi_insertion_mode (1, key); 55221308Sache return (0); 55321308Sache} 55421308Sache 55521308Sacheint 55621308Sacherl_vi_append_mode (count, key) 55721308Sache int count, key; 55821308Sache{ 55921308Sache if (rl_point < rl_end) 56021308Sache rl_point++; 56121308Sache rl_vi_insertion_mode (1, key); 56221308Sache return (0); 56321308Sache} 56421308Sache 56521308Sacheint 56621308Sacherl_vi_append_eol (count, key) 56721308Sache int count, key; 56821308Sache{ 56921308Sache rl_end_of_line (1, key); 57021308Sache rl_vi_append_mode (1, key); 57121308Sache return (0); 57221308Sache} 57321308Sache 57421308Sache/* What to do in the case of C-d. */ 57521308Sacheint 57621308Sacherl_vi_eof_maybe (count, c) 57721308Sache int count, c; 57821308Sache{ 57921308Sache return (rl_newline (1, '\n')); 58021308Sache} 58121308Sache 58221308Sache/* Insertion mode stuff. */ 58321308Sache 58421308Sache/* Switching from one mode to the other really just involves 58521308Sache switching keymaps. */ 58621308Sacheint 58721308Sacherl_vi_insertion_mode (count, key) 58821308Sache int count, key; 58921308Sache{ 59021308Sache _rl_keymap = vi_insertion_keymap; 59121308Sache _rl_vi_last_key_before_insert = key; 59221308Sache return (0); 59321308Sache} 59421308Sache 59521308Sachestatic void 59621308Sache_rl_vi_save_insert (up) 59721308Sache UNDO_LIST *up; 59821308Sache{ 59921308Sache int len, start, end; 60021308Sache 60135486Sache if (up == 0) 60235486Sache { 60335486Sache if (vi_insert_buffer_size >= 1) 60435486Sache vi_insert_buffer[0] = '\0'; 60535486Sache return; 60635486Sache } 60735486Sache 60821308Sache start = up->start; 60921308Sache end = up->end; 61021308Sache len = end - start + 1; 61121308Sache if (len >= vi_insert_buffer_size) 61221308Sache { 61321308Sache vi_insert_buffer_size += (len + 32) - (len % 32); 61421308Sache vi_insert_buffer = xrealloc (vi_insert_buffer, vi_insert_buffer_size); 61521308Sache } 61621308Sache strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); 61721308Sache vi_insert_buffer[len-1] = '\0'; 61821308Sache} 61921308Sache 62021308Sachevoid 62121308Sache_rl_vi_done_inserting () 62221308Sache{ 62321308Sache if (_rl_vi_doing_insert) 62421308Sache { 62521308Sache rl_end_undo_group (); 62621308Sache /* Now, the text between rl_undo_list->next->start and 62721308Sache rl_undo_list->next->end is what was inserted while in insert 62821308Sache mode. It gets copied to VI_INSERT_BUFFER because it depends 62921308Sache on absolute indices into the line which may change (though they 63021308Sache probably will not). */ 63121308Sache _rl_vi_doing_insert = 0; 63221308Sache _rl_vi_save_insert (rl_undo_list->next); 63321308Sache vi_continued_command = 1; 63421308Sache } 63521308Sache else 63621308Sache { 63721308Sache if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list) 63821308Sache _rl_vi_save_insert (rl_undo_list); 63921308Sache /* XXX - Other keys probably need to be checked. */ 64021308Sache else if (_rl_vi_last_key_before_insert == 'C') 64121308Sache rl_end_undo_group (); 64221308Sache while (_rl_undo_group_level > 0) 64321308Sache rl_end_undo_group (); 64421308Sache vi_continued_command = 0; 64521308Sache } 64621308Sache} 64721308Sache 64821308Sacheint 64921308Sacherl_vi_movement_mode (count, key) 65021308Sache int count, key; 65121308Sache{ 65221308Sache if (rl_point > 0) 65321308Sache rl_backward (1, key); 65421308Sache 65521308Sache _rl_keymap = vi_movement_keymap; 65621308Sache _rl_vi_done_inserting (); 65721308Sache return (0); 65821308Sache} 65921308Sache 66021308Sacheint 66121308Sacherl_vi_arg_digit (count, c) 66221308Sache int count, c; 66321308Sache{ 66421308Sache if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) 66521308Sache return (rl_beg_of_line (1, c)); 66621308Sache else 66721308Sache return (rl_digit_argument (count, c)); 66821308Sache} 66921308Sache 67021308Sacheint 67121308Sacherl_vi_change_case (count, ignore) 67221308Sache int count, ignore; 67321308Sache{ 67421308Sache char c = 0; 67521308Sache 67621308Sache /* Don't try this on an empty line. */ 67721308Sache if (rl_point >= rl_end) 67821308Sache return (0); 67921308Sache 68021308Sache while (count-- && rl_point < rl_end) 68121308Sache { 68221308Sache if (_rl_uppercase_p (rl_line_buffer[rl_point])) 68321308Sache c = _rl_to_lower (rl_line_buffer[rl_point]); 68421308Sache else if (_rl_lowercase_p (rl_line_buffer[rl_point])) 68521308Sache c = _rl_to_upper (rl_line_buffer[rl_point]); 68621308Sache else 68721308Sache { 68821308Sache /* Just skip over characters neither upper nor lower case. */ 68921308Sache rl_forward (1, c); 69021308Sache continue; 69121308Sache } 69221308Sache 69321308Sache /* Vi is kind of strange here. */ 69421308Sache if (c) 69521308Sache { 69621308Sache rl_begin_undo_group (); 69721308Sache rl_delete (1, c); 69821308Sache rl_insert (1, c); 69921308Sache rl_end_undo_group (); 70021308Sache rl_vi_check (); 70121308Sache } 70221308Sache else 70321308Sache rl_forward (1, c); 70421308Sache } 70521308Sache return (0); 70621308Sache} 70721308Sache 70821308Sacheint 70921308Sacherl_vi_put (count, key) 71021308Sache int count, key; 71121308Sache{ 71221308Sache if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 71321308Sache rl_point++; 71421308Sache 71547558Sache rl_yank (1, key); 71621308Sache rl_backward (1, key); 71721308Sache return (0); 71821308Sache} 71921308Sache 72021308Sacheint 72121308Sacherl_vi_check () 72221308Sache{ 72321308Sache if (rl_point && rl_point == rl_end) 72421308Sache rl_point--; 72521308Sache return (0); 72621308Sache} 72721308Sache 72821308Sacheint 72921308Sacherl_vi_column (count, key) 73021308Sache int count, key; 73121308Sache{ 73221308Sache if (count > rl_end) 73321308Sache rl_end_of_line (1, key); 73421308Sache else 73521308Sache rl_point = count - 1; 73621308Sache return (0); 73721308Sache} 73821308Sache 73921308Sacheint 74021308Sacherl_vi_domove (key, nextkey) 74121308Sache int key, *nextkey; 74221308Sache{ 74321308Sache int c, save; 74421308Sache int old_end; 74521308Sache 74621308Sache rl_mark = rl_point; 74775406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 74821308Sache c = rl_read_key (); 74975406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 75021308Sache *nextkey = c; 75121308Sache 75221308Sache if (!member (c, vi_motion)) 75321308Sache { 75421308Sache if (_rl_digit_p (c)) 75521308Sache { 75621308Sache save = rl_numeric_arg; 75721308Sache rl_numeric_arg = _rl_digit_value (c); 75821308Sache rl_digit_loop1 (); 75921308Sache rl_numeric_arg *= save; 76075406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 76121308Sache c = rl_read_key (); /* real command */ 76275406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 76321308Sache *nextkey = c; 76421308Sache } 76521308Sache else if (key == c && (key == 'd' || key == 'y' || key == 'c')) 76621308Sache { 76721308Sache rl_mark = rl_end; 76821308Sache rl_beg_of_line (1, c); 76921308Sache _rl_vi_last_motion = c; 77021308Sache return (0); 77121308Sache } 77221308Sache else 77321308Sache return (-1); 77421308Sache } 77521308Sache 77621308Sache _rl_vi_last_motion = c; 77721308Sache 77821308Sache /* Append a blank character temporarily so that the motion routines 77921308Sache work right at the end of the line. */ 78021308Sache old_end = rl_end; 78121308Sache rl_line_buffer[rl_end++] = ' '; 78221308Sache rl_line_buffer[rl_end] = '\0'; 78321308Sache 78421308Sache _rl_dispatch (c, _rl_keymap); 78521308Sache 78621308Sache /* Remove the blank that we added. */ 78721308Sache rl_end = old_end; 78821308Sache rl_line_buffer[rl_end] = '\0'; 78921308Sache if (rl_point > rl_end) 79021308Sache rl_point = rl_end; 79121308Sache 79221308Sache /* No change in position means the command failed. */ 79321308Sache if (rl_mark == rl_point) 79421308Sache return (-1); 79521308Sache 79621308Sache /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next 79721308Sache word. If we are not at the end of the line, and we are on a 79821308Sache non-whitespace character, move back one (presumably to whitespace). */ 79921308Sache if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && 80021308Sache !whitespace (rl_line_buffer[rl_point])) 80121308Sache rl_point--; 80221308Sache 80321308Sache /* If cw or cW, back up to the end of a word, so the behaviour of ce 80421308Sache or cE is the actual result. Brute-force, no subtlety. */ 80521308Sache if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) 80621308Sache { 80721308Sache /* Don't move farther back than where we started. */ 80821308Sache while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) 80921308Sache rl_point--; 81021308Sache 81121308Sache /* Posix.2 says that if cw or cW moves the cursor towards the end of 81221308Sache the line, the character under the cursor should be deleted. */ 81321308Sache if (rl_point == rl_mark) 81421308Sache rl_point++; 81521308Sache else 81621308Sache { 81721308Sache /* Move past the end of the word so that the kill doesn't 81821308Sache remove the last letter of the previous word. Only do this 81921308Sache if we are not at the end of the line. */ 82021308Sache if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) 82121308Sache rl_point++; 82221308Sache } 82321308Sache } 82421308Sache 82521308Sache if (rl_mark < rl_point) 82621308Sache exchange (rl_point, rl_mark); 82721308Sache 82821308Sache return (0); 82921308Sache} 83021308Sache 83121308Sache/* A simplified loop for vi. Don't dispatch key at end. 83275406Sache Don't recognize minus sign? 83375406Sache Should this do rl_save_prompt/rl_restore_prompt? */ 83421308Sachestatic int 83521308Sacherl_digit_loop1 () 83621308Sache{ 83721308Sache int key, c; 83821308Sache 83975406Sache RL_SETSTATE(RL_STATE_NUMERICARG); 84021308Sache while (1) 84121308Sache { 84275406Sache if (rl_numeric_arg > 1000000) 84375406Sache { 84475406Sache rl_explicit_arg = rl_numeric_arg = 0; 84575406Sache rl_ding (); 84675406Sache rl_clear_message (); 84775406Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 84875406Sache return 1; 84975406Sache } 85021308Sache rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); 85175406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 85221308Sache key = c = rl_read_key (); 85375406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 85421308Sache 85521308Sache if (_rl_keymap[c].type == ISFUNC && 85621308Sache _rl_keymap[c].function == rl_universal_argument) 85721308Sache { 85821308Sache rl_numeric_arg *= 4; 85921308Sache continue; 86021308Sache } 86121308Sache 86221308Sache c = UNMETA (c); 86321308Sache if (_rl_digit_p (c)) 86421308Sache { 86521308Sache if (rl_explicit_arg) 86621308Sache rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); 86721308Sache else 86821308Sache rl_numeric_arg = _rl_digit_value (c); 86921308Sache rl_explicit_arg = 1; 87021308Sache } 87121308Sache else 87221308Sache { 87321308Sache rl_clear_message (); 87421308Sache rl_stuff_char (key); 87521308Sache break; 87621308Sache } 87721308Sache } 87875406Sache 87975406Sache RL_UNSETSTATE(RL_STATE_NUMERICARG); 88021308Sache return (0); 88121308Sache} 88221308Sache 88321308Sacheint 88421308Sacherl_vi_delete_to (count, key) 88521308Sache int count, key; 88621308Sache{ 88721308Sache int c; 88821308Sache 88921308Sache if (_rl_uppercase_p (key)) 89021308Sache rl_stuff_char ('$'); 89121308Sache else if (vi_redoing) 89221308Sache rl_stuff_char (_rl_vi_last_motion); 89321308Sache 89421308Sache if (rl_vi_domove (key, &c)) 89521308Sache { 89675406Sache rl_ding (); 89721308Sache return -1; 89821308Sache } 89921308Sache 90021308Sache /* These are the motion commands that do not require adjusting the 90121308Sache mark. */ 90221308Sache if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) 90321308Sache rl_mark++; 90421308Sache 90521308Sache rl_kill_text (rl_point, rl_mark); 90621308Sache return (0); 90721308Sache} 90821308Sache 90921308Sacheint 91021308Sacherl_vi_change_to (count, key) 91121308Sache int count, key; 91221308Sache{ 91321308Sache int c, start_pos; 91421308Sache 91521308Sache if (_rl_uppercase_p (key)) 91621308Sache rl_stuff_char ('$'); 91721308Sache else if (vi_redoing) 91821308Sache rl_stuff_char (_rl_vi_last_motion); 91921308Sache 92021308Sache start_pos = rl_point; 92121308Sache 92221308Sache if (rl_vi_domove (key, &c)) 92321308Sache { 92475406Sache rl_ding (); 92521308Sache return -1; 92621308Sache } 92721308Sache 92821308Sache /* These are the motion commands that do not require adjusting the 92921308Sache mark. c[wW] are handled by special-case code in rl_vi_domove(), 93021308Sache and already leave the mark at the correct location. */ 93121308Sache if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) 93221308Sache rl_mark++; 93321308Sache 93421308Sache /* The cursor never moves with c[wW]. */ 93521308Sache if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) 93621308Sache rl_point = start_pos; 93721308Sache 93821308Sache if (vi_redoing) 93921308Sache { 94021308Sache if (vi_insert_buffer && *vi_insert_buffer) 94121308Sache rl_begin_undo_group (); 94221308Sache rl_delete_text (rl_point, rl_mark); 94321308Sache if (vi_insert_buffer && *vi_insert_buffer) 94421308Sache { 94521308Sache rl_insert_text (vi_insert_buffer); 94621308Sache rl_end_undo_group (); 94721308Sache } 94821308Sache } 94921308Sache else 95021308Sache { 95121308Sache rl_begin_undo_group (); /* to make the `u' command work */ 95221308Sache rl_kill_text (rl_point, rl_mark); 95321308Sache /* `C' does not save the text inserted for undoing or redoing. */ 95421308Sache if (_rl_uppercase_p (key) == 0) 95521308Sache _rl_vi_doing_insert = 1; 95621308Sache _rl_vi_set_last (key, count, rl_arg_sign); 95721308Sache rl_vi_insertion_mode (1, key); 95821308Sache } 95921308Sache 96021308Sache return (0); 96121308Sache} 96221308Sache 96321308Sacheint 96421308Sacherl_vi_yank_to (count, key) 96521308Sache int count, key; 96621308Sache{ 96721308Sache int c, save = rl_point; 96821308Sache 96921308Sache if (_rl_uppercase_p (key)) 97021308Sache rl_stuff_char ('$'); 97121308Sache 97221308Sache if (rl_vi_domove (key, &c)) 97321308Sache { 97475406Sache rl_ding (); 97521308Sache return -1; 97621308Sache } 97721308Sache 97821308Sache /* These are the motion commands that do not require adjusting the 97921308Sache mark. */ 98021308Sache if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) 98121308Sache rl_mark++; 98221308Sache 98321308Sache rl_begin_undo_group (); 98421308Sache rl_kill_text (rl_point, rl_mark); 98521308Sache rl_end_undo_group (); 98621308Sache rl_do_undo (); 98721308Sache rl_point = save; 98821308Sache 98921308Sache return (0); 99021308Sache} 99121308Sache 99221308Sacheint 99321308Sacherl_vi_delete (count, key) 99421308Sache int count, key; 99521308Sache{ 99621308Sache int end; 99721308Sache 99821308Sache if (rl_end == 0) 99921308Sache { 100075406Sache rl_ding (); 100121308Sache return -1; 100221308Sache } 100321308Sache 100421308Sache end = rl_point + count; 100521308Sache 100621308Sache if (end >= rl_end) 100721308Sache end = rl_end; 100821308Sache 100921308Sache rl_kill_text (rl_point, end); 101021308Sache 101121308Sache if (rl_point > 0 && rl_point == rl_end) 101221308Sache rl_backward (1, key); 101321308Sache return (0); 101421308Sache} 101521308Sache 101621308Sacheint 101721308Sacherl_vi_back_to_indent (count, key) 101821308Sache int count, key; 101921308Sache{ 102021308Sache rl_beg_of_line (1, key); 102121308Sache while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 102221308Sache rl_point++; 102321308Sache return (0); 102421308Sache} 102521308Sache 102621308Sacheint 102721308Sacherl_vi_first_print (count, key) 102821308Sache int count, key; 102921308Sache{ 103021308Sache return (rl_vi_back_to_indent (1, key)); 103121308Sache} 103221308Sache 103321308Sacheint 103421308Sacherl_vi_char_search (count, key) 103521308Sache int count, key; 103621308Sache{ 103721308Sache static char target; 103821308Sache static int orig_dir, dir; 103921308Sache 104021308Sache if (key == ';' || key == ',') 104121308Sache dir = key == ';' ? orig_dir : -orig_dir; 104221308Sache else 104321308Sache { 104421308Sache if (vi_redoing) 104521308Sache target = _rl_vi_last_search_char; 104621308Sache else 104775406Sache { 104875406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 104975406Sache _rl_vi_last_search_char = target = rl_read_key (); 105075406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 105175406Sache } 105221308Sache 105321308Sache switch (key) 105421308Sache { 105521308Sache case 't': 105621308Sache orig_dir = dir = FTO; 105721308Sache break; 105821308Sache 105921308Sache case 'T': 106021308Sache orig_dir = dir = BTO; 106121308Sache break; 106221308Sache 106321308Sache case 'f': 106421308Sache orig_dir = dir = FFIND; 106521308Sache break; 106621308Sache 106721308Sache case 'F': 106821308Sache orig_dir = dir = BFIND; 106921308Sache break; 107021308Sache } 107121308Sache } 107221308Sache 107321308Sache return (_rl_char_search_internal (count, dir, target)); 107421308Sache} 107521308Sache 107621308Sache/* Match brackets */ 107721308Sacheint 107821308Sacherl_vi_match (ignore, key) 107921308Sache int ignore, key; 108021308Sache{ 108121308Sache int count = 1, brack, pos; 108221308Sache 108321308Sache pos = rl_point; 108421308Sache if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 108521308Sache { 108621308Sache while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && 108721308Sache rl_point < rl_end - 1) 108821308Sache rl_forward (1, key); 108921308Sache 109021308Sache if (brack <= 0) 109121308Sache { 109221308Sache rl_point = pos; 109375406Sache rl_ding (); 109421308Sache return -1; 109521308Sache } 109621308Sache } 109721308Sache 109821308Sache pos = rl_point; 109921308Sache 110021308Sache if (brack < 0) 110121308Sache { 110221308Sache while (count) 110321308Sache { 110421308Sache if (--pos >= 0) 110521308Sache { 110621308Sache int b = rl_vi_bracktype (rl_line_buffer[pos]); 110721308Sache if (b == -brack) 110821308Sache count--; 110921308Sache else if (b == brack) 111021308Sache count++; 111121308Sache } 111221308Sache else 111321308Sache { 111475406Sache rl_ding (); 111521308Sache return -1; 111621308Sache } 111721308Sache } 111821308Sache } 111921308Sache else 112021308Sache { /* brack > 0 */ 112121308Sache while (count) 112221308Sache { 112321308Sache if (++pos < rl_end) 112421308Sache { 112521308Sache int b = rl_vi_bracktype (rl_line_buffer[pos]); 112621308Sache if (b == -brack) 112721308Sache count--; 112821308Sache else if (b == brack) 112921308Sache count++; 113021308Sache } 113121308Sache else 113221308Sache { 113375406Sache rl_ding (); 113421308Sache return -1; 113521308Sache } 113621308Sache } 113721308Sache } 113821308Sache rl_point = pos; 113921308Sache return (0); 114021308Sache} 114121308Sache 114221308Sacheint 114321308Sacherl_vi_bracktype (c) 114421308Sache int c; 114521308Sache{ 114621308Sache switch (c) 114721308Sache { 114821308Sache case '(': return 1; 114921308Sache case ')': return -1; 115021308Sache case '[': return 2; 115121308Sache case ']': return -2; 115221308Sache case '{': return 3; 115321308Sache case '}': return -3; 115421308Sache default: return 0; 115521308Sache } 115621308Sache} 115721308Sache 115821308Sacheint 115921308Sacherl_vi_change_char (count, key) 116021308Sache int count, key; 116121308Sache{ 116221308Sache int c; 116321308Sache 116421308Sache if (vi_redoing) 116521308Sache c = _rl_vi_last_replacement; 116621308Sache else 116775406Sache { 116875406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 116975406Sache _rl_vi_last_replacement = c = rl_read_key (); 117075406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 117175406Sache } 117221308Sache 117321308Sache if (c == '\033' || c == CTRL ('C')) 117421308Sache return -1; 117521308Sache 117621308Sache while (count-- && rl_point < rl_end) 117721308Sache { 117821308Sache rl_begin_undo_group (); 117921308Sache 118021308Sache rl_delete (1, c); 118121308Sache rl_insert (1, c); 118221308Sache if (count == 0) 118321308Sache rl_backward (1, c); 118421308Sache 118521308Sache rl_end_undo_group (); 118621308Sache } 118721308Sache return (0); 118821308Sache} 118921308Sache 119021308Sacheint 119121308Sacherl_vi_subst (count, key) 119221308Sache int count, key; 119321308Sache{ 119421308Sache rl_begin_undo_group (); 119521308Sache 119621308Sache if (_rl_uppercase_p (key)) 119721308Sache { 119821308Sache rl_beg_of_line (1, key); 119921308Sache rl_kill_line (1, key); 120021308Sache } 120121308Sache else 120221308Sache rl_delete_text (rl_point, rl_point+count); 120321308Sache 120421308Sache rl_end_undo_group (); 120521308Sache 120621308Sache _rl_vi_set_last (key, count, rl_arg_sign); 120721308Sache 120821308Sache if (vi_redoing) 120921308Sache { 121021308Sache int o = _rl_doing_an_undo; 121121308Sache 121221308Sache _rl_doing_an_undo = 1; 121321308Sache if (vi_insert_buffer && *vi_insert_buffer) 121421308Sache rl_insert_text (vi_insert_buffer); 121521308Sache _rl_doing_an_undo = o; 121621308Sache } 121721308Sache else 121821308Sache { 121921308Sache rl_begin_undo_group (); 122021308Sache _rl_vi_doing_insert = 1; 122121308Sache rl_vi_insertion_mode (1, key); 122221308Sache } 122321308Sache 122421308Sache return (0); 122521308Sache} 122621308Sache 122721308Sacheint 122821308Sacherl_vi_overstrike (count, key) 122921308Sache int count, key; 123021308Sache{ 123121308Sache int i; 123221308Sache 123321308Sache if (_rl_vi_doing_insert == 0) 123421308Sache { 123521308Sache _rl_vi_doing_insert = 1; 123621308Sache rl_begin_undo_group (); 123721308Sache } 123821308Sache 123921308Sache for (i = 0; i < count; i++) 124021308Sache { 124121308Sache vi_replace_count++; 124221308Sache rl_begin_undo_group (); 124321308Sache 124421308Sache if (rl_point < rl_end) 124521308Sache { 124621308Sache rl_delete (1, key); 124721308Sache rl_insert (1, key); 124821308Sache } 124921308Sache else 125021308Sache rl_insert (1, key); 125121308Sache 125221308Sache rl_end_undo_group (); 125321308Sache } 125421308Sache return (0); 125521308Sache} 125621308Sache 125721308Sacheint 125821308Sacherl_vi_overstrike_delete (count, key) 125921308Sache int count, key; 126021308Sache{ 126121308Sache int i, s; 126221308Sache 126321308Sache for (i = 0; i < count; i++) 126421308Sache { 126521308Sache if (vi_replace_count == 0) 126621308Sache { 126775406Sache rl_ding (); 126821308Sache break; 126921308Sache } 127021308Sache s = rl_point; 127121308Sache 127221308Sache if (rl_do_undo ()) 127321308Sache vi_replace_count--; 127421308Sache 127521308Sache if (rl_point == s) 127621308Sache rl_backward (1, key); 127721308Sache } 127821308Sache 127921308Sache if (vi_replace_count == 0 && _rl_vi_doing_insert) 128021308Sache { 128121308Sache rl_end_undo_group (); 128221308Sache rl_do_undo (); 128321308Sache _rl_vi_doing_insert = 0; 128421308Sache } 128521308Sache return (0); 128621308Sache} 128721308Sache 128821308Sacheint 128921308Sacherl_vi_replace (count, key) 129021308Sache int count, key; 129121308Sache{ 129221308Sache int i; 129321308Sache 129421308Sache vi_replace_count = 0; 129521308Sache 129621308Sache if (!vi_replace_map) 129721308Sache { 129821308Sache vi_replace_map = rl_make_bare_keymap (); 129921308Sache 130021308Sache for (i = ' '; i < KEYMAP_SIZE; i++) 130121308Sache vi_replace_map[i].function = rl_vi_overstrike; 130221308Sache 130321308Sache vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; 130421308Sache vi_replace_map[ESC].function = rl_vi_movement_mode; 130521308Sache vi_replace_map[RETURN].function = rl_newline; 130621308Sache vi_replace_map[NEWLINE].function = rl_newline; 130721308Sache 130821308Sache /* If the normal vi insertion keymap has ^H bound to erase, do the 130921308Sache same here. Probably should remove the assignment to RUBOUT up 131021308Sache there, but I don't think it will make a difference in real life. */ 131121308Sache if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && 131221308Sache vi_insertion_keymap[CTRL ('H')].function == rl_rubout) 131321308Sache vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; 131421308Sache 131521308Sache } 131621308Sache _rl_keymap = vi_replace_map; 131721308Sache return (0); 131821308Sache} 131921308Sache 132021308Sache#if 0 132121308Sache/* Try to complete the word we are standing on or the word that ends with 132221308Sache the previous character. A space matches everything. Word delimiters are 132321308Sache space and ;. */ 132421308Sacheint 132521308Sacherl_vi_possible_completions() 132621308Sache{ 132721308Sache int save_pos = rl_point; 132821308Sache 132921308Sache if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') 133021308Sache { 133121308Sache while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && 133221308Sache rl_line_buffer[rl_point] != ';') 133321308Sache rl_point++; 133421308Sache } 133521308Sache else if (rl_line_buffer[rl_point - 1] == ';') 133621308Sache { 133775406Sache rl_ding (); 133821308Sache return (0); 133921308Sache } 134021308Sache 134121308Sache rl_possible_completions (); 134221308Sache rl_point = save_pos; 134321308Sache 134421308Sache return (0); 134521308Sache} 134621308Sache#endif 134721308Sache 134821308Sache/* Functions to save and restore marks. */ 134921308Sacheint 135021308Sacherl_vi_set_mark (count, key) 135121308Sache int count, key; 135221308Sache{ 135321308Sache int ch; 135421308Sache 135575406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 135621308Sache ch = rl_read_key (); 135775406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 135875406Sache 135921308Sache if (_rl_lowercase_p (ch) == 0) 136021308Sache { 136175406Sache rl_ding (); 136221308Sache return -1; 136321308Sache } 136421308Sache ch -= 'a'; 136521308Sache vi_mark_chars[ch] = rl_point; 136621308Sache return 0; 136721308Sache} 136821308Sache 136921308Sacheint 137021308Sacherl_vi_goto_mark (count, key) 137121308Sache int count, key; 137221308Sache{ 137321308Sache int ch; 137421308Sache 137575406Sache RL_SETSTATE(RL_STATE_MOREINPUT); 137621308Sache ch = rl_read_key (); 137775406Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 137875406Sache 137921308Sache if (ch == '`') 138021308Sache { 138121308Sache rl_point = rl_mark; 138221308Sache return 0; 138321308Sache } 138421308Sache else if (_rl_lowercase_p (ch) == 0) 138521308Sache { 138675406Sache rl_ding (); 138721308Sache return -1; 138821308Sache } 138921308Sache 139021308Sache ch -= 'a'; 139121308Sache if (vi_mark_chars[ch] == -1) 139221308Sache { 139375406Sache rl_ding (); 139421308Sache return -1; 139521308Sache } 139621308Sache rl_point = vi_mark_chars[ch]; 139721308Sache return 0; 139821308Sache} 139921308Sache 140021308Sache#endif /* VI_MODE */ 1401