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