vi.c revision 290065
1290065Sjilles/* $NetBSD: vi.c,v 1.47 2015/10/21 21:45:30 christos Exp $ */ 2276881Sbapt 31573Srgrimes/*- 41573Srgrimes * Copyright (c) 1992, 1993 51573Srgrimes * The Regents of the University of California. All rights reserved. 61573Srgrimes * 71573Srgrimes * This code is derived from software contributed to Berkeley by 81573Srgrimes * Christos Zoulas of Cornell University. 91573Srgrimes * 101573Srgrimes * Redistribution and use in source and binary forms, with or without 111573Srgrimes * modification, are permitted provided that the following conditions 121573Srgrimes * are met: 131573Srgrimes * 1. Redistributions of source code must retain the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer. 151573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161573Srgrimes * notice, this list of conditions and the following disclaimer in the 171573Srgrimes * documentation and/or other materials provided with the distribution. 18148834Sstefanf * 3. Neither the name of the University nor the names of its contributors 191573Srgrimes * may be used to endorse or promote products derived from this software 201573Srgrimes * without specific prior written permission. 211573Srgrimes * 221573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321573Srgrimes * SUCH DAMAGE. 331573Srgrimes */ 341573Srgrimes 35276881Sbapt#include "config.h" 36276881Sbapt#include <stdlib.h> 37276881Sbapt#include <unistd.h> 38276881Sbapt#include <limits.h> 39276881Sbapt#include <sys/wait.h> 40276881Sbapt 411573Srgrimes#if !defined(lint) && !defined(SCCSID) 42276881Sbapt#if 0 431573Srgrimesstatic char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; 44276881Sbapt#else 45290065Sjilles__RCSID("$NetBSD: vi.c,v 1.47 2015/10/21 21:45:30 christos Exp $"); 46276881Sbapt#endif 471573Srgrimes#endif /* not lint && not SCCSID */ 4884260Sobrien#include <sys/cdefs.h> 4984260Sobrien__FBSDID("$FreeBSD: head/lib/libedit/vi.c 290065 2015-10-27 21:16:29Z jilles $"); 501573Srgrimes 511573Srgrimes/* 521573Srgrimes * vi.c: Vi mode commands. 531573Srgrimes */ 541573Srgrimes#include "el.h" 551573Srgrimes 56276881Sbaptprivate el_action_t cv_action(EditLine *, Int); 57276881Sbaptprivate el_action_t cv_paste(EditLine *, Int); 581573Srgrimes 591573Srgrimes/* cv_action(): 601573Srgrimes * Handle vi actions. 611573Srgrimes */ 621573Srgrimesprivate el_action_t 63276881Sbaptcv_action(EditLine *el, Int c) 641573Srgrimes{ 651573Srgrimes 66148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 67148834Sstefanf /* 'cc', 'dd' and (possibly) friends */ 68276881Sbapt if (c != (Int)el->el_chared.c_vcmd.action) 69148834Sstefanf return CC_ERROR; 70148834Sstefanf 71148834Sstefanf if (!(c & YANK)) 72148834Sstefanf cv_undo(el); 73148834Sstefanf cv_yank(el, el->el_line.buffer, 74237448Spfg (int)(el->el_line.lastchar - el->el_line.buffer)); 7584260Sobrien el->el_chared.c_vcmd.action = NOP; 7684260Sobrien el->el_chared.c_vcmd.pos = 0; 77148923Sstefanf if (!(c & YANK)) { 78148923Sstefanf el->el_line.lastchar = el->el_line.buffer; 79148923Sstefanf el->el_line.cursor = el->el_line.buffer; 80148923Sstefanf } 8184260Sobrien if (c & INSERT) 8284260Sobrien el->el_map.current = el->el_map.key; 838870Srgrimes 84276881Sbapt return CC_REFRESH; 8584260Sobrien } 8684260Sobrien el->el_chared.c_vcmd.pos = el->el_line.cursor; 8784260Sobrien el->el_chared.c_vcmd.action = c; 88276881Sbapt return CC_ARGHACK; 891573Srgrimes} 901573Srgrimes 911573Srgrimes/* cv_paste(): 921573Srgrimes * Paste previous deletion before or after the cursor 931573Srgrimes */ 9484260Sobrienprivate el_action_t 95276881Sbaptcv_paste(EditLine *el, Int c) 961573Srgrimes{ 97148834Sstefanf c_kill_t *k = &el->el_chared.c_kill; 98237448Spfg size_t len = (size_t)(k->last - k->buf); 9984260Sobrien 100148834Sstefanf if (k->buf == NULL || len == 0) 101276881Sbapt return CC_ERROR; 1021573Srgrimes#ifdef DEBUG_PASTE 103237448Spfg (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf); 1041573Srgrimes#endif 1051573Srgrimes 106148834Sstefanf cv_undo(el); 107148834Sstefanf 10884260Sobrien if (!c && el->el_line.cursor < el->el_line.lastchar) 10984260Sobrien el->el_line.cursor++; 1108870Srgrimes 111237448Spfg c_insert(el, (int)len); 112148834Sstefanf if (el->el_line.cursor + len > el->el_line.lastchar) 113276881Sbapt return CC_ERROR; 114276881Sbapt (void) memcpy(el->el_line.cursor, k->buf, len * 115276881Sbapt sizeof(*el->el_line.cursor)); 116148923Sstefanf 117276881Sbapt return CC_REFRESH; 1181573Srgrimes} 1191573Srgrimes 1201573Srgrimes 1218870Srgrimes/* vi_paste_next(): 1221573Srgrimes * Vi paste previous deletion to the right of the cursor 1231573Srgrimes * [p] 1241573Srgrimes */ 1251573Srgrimesprotected el_action_t 1261573Srgrimes/*ARGSUSED*/ 127276881Sbaptvi_paste_next(EditLine *el, Int c __attribute__((__unused__))) 1281573Srgrimes{ 12984260Sobrien 130276881Sbapt return cv_paste(el, 0); 1311573Srgrimes} 1321573Srgrimes 1331573Srgrimes 1348870Srgrimes/* vi_paste_prev(): 1351573Srgrimes * Vi paste previous deletion to the left of the cursor 1361573Srgrimes * [P] 1371573Srgrimes */ 1381573Srgrimesprotected el_action_t 1391573Srgrimes/*ARGSUSED*/ 140276881Sbaptvi_paste_prev(EditLine *el, Int c __attribute__((__unused__))) 1411573Srgrimes{ 14284260Sobrien 143276881Sbapt return cv_paste(el, 1); 1441573Srgrimes} 1451573Srgrimes 1461573Srgrimes 147148834Sstefanf/* vi_prev_big_word(): 1481573Srgrimes * Vi move to the previous space delimited word 1491573Srgrimes * [B] 1501573Srgrimes */ 1511573Srgrimesprotected el_action_t 1521573Srgrimes/*ARGSUSED*/ 153276881Sbaptvi_prev_big_word(EditLine *el, Int c __attribute__((__unused__))) 1541573Srgrimes{ 1551573Srgrimes 15684260Sobrien if (el->el_line.cursor == el->el_line.buffer) 157276881Sbapt return CC_ERROR; 1581573Srgrimes 159148834Sstefanf el->el_line.cursor = cv_prev_word(el->el_line.cursor, 16084260Sobrien el->el_line.buffer, 16184260Sobrien el->el_state.argument, 162148834Sstefanf cv__isWord); 1631573Srgrimes 164148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 16584260Sobrien cv_delfini(el); 166276881Sbapt return CC_REFRESH; 16784260Sobrien } 168276881Sbapt return CC_CURSOR; 1691573Srgrimes} 1701573Srgrimes 1711573Srgrimes 1728870Srgrimes/* vi_prev_word(): 1731573Srgrimes * Vi move to the previous word 17437199Sbrian * [b] 1751573Srgrimes */ 1761573Srgrimesprotected el_action_t 1771573Srgrimes/*ARGSUSED*/ 178276881Sbaptvi_prev_word(EditLine *el, Int c __attribute__((__unused__))) 1791573Srgrimes{ 1801573Srgrimes 18184260Sobrien if (el->el_line.cursor == el->el_line.buffer) 182276881Sbapt return CC_ERROR; 1831573Srgrimes 184148834Sstefanf el->el_line.cursor = cv_prev_word(el->el_line.cursor, 18584260Sobrien el->el_line.buffer, 18684260Sobrien el->el_state.argument, 18784260Sobrien cv__isword); 1881573Srgrimes 189148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 19084260Sobrien cv_delfini(el); 191276881Sbapt return CC_REFRESH; 19284260Sobrien } 193276881Sbapt return CC_CURSOR; 1941573Srgrimes} 1951573Srgrimes 1961573Srgrimes 197148834Sstefanf/* vi_next_big_word(): 1981573Srgrimes * Vi move to the next space delimited word 1991573Srgrimes * [W] 2001573Srgrimes */ 2011573Srgrimesprotected el_action_t 2021573Srgrimes/*ARGSUSED*/ 203276881Sbaptvi_next_big_word(EditLine *el, Int c __attribute__((__unused__))) 2041573Srgrimes{ 2051573Srgrimes 206148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar - 1) 207276881Sbapt return CC_ERROR; 2081573Srgrimes 20984260Sobrien el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 210148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isWord); 2111573Srgrimes 21284260Sobrien if (el->el_map.type == MAP_VI) 213148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 21484260Sobrien cv_delfini(el); 215276881Sbapt return CC_REFRESH; 21684260Sobrien } 217276881Sbapt return CC_CURSOR; 2181573Srgrimes} 2191573Srgrimes 22084260Sobrien 2218870Srgrimes/* vi_next_word(): 2221573Srgrimes * Vi move to the next word 2231573Srgrimes * [w] 2241573Srgrimes */ 2251573Srgrimesprotected el_action_t 2261573Srgrimes/*ARGSUSED*/ 227276881Sbaptvi_next_word(EditLine *el, Int c __attribute__((__unused__))) 2281573Srgrimes{ 2291573Srgrimes 230148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar - 1) 231276881Sbapt return CC_ERROR; 2321573Srgrimes 23384260Sobrien el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 234148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isword); 2351573Srgrimes 23684260Sobrien if (el->el_map.type == MAP_VI) 237148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 23884260Sobrien cv_delfini(el); 239276881Sbapt return CC_REFRESH; 24084260Sobrien } 241276881Sbapt return CC_CURSOR; 2421573Srgrimes} 2431573Srgrimes 2441573Srgrimes 2458870Srgrimes/* vi_change_case(): 2461573Srgrimes * Vi change case of character under the cursor and advance one character 2471573Srgrimes * [~] 2481573Srgrimes */ 2491573Srgrimesprotected el_action_t 250276881Sbaptvi_change_case(EditLine *el, Int c) 2511573Srgrimes{ 252148834Sstefanf int i; 25384260Sobrien 254148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar) 255276881Sbapt return CC_ERROR; 256148834Sstefanf cv_undo(el); 257148834Sstefanf for (i = 0; i < el->el_state.argument; i++) { 258148834Sstefanf 259276881Sbapt c = *el->el_line.cursor; 260276881Sbapt if (Isupper(c)) 261276881Sbapt *el->el_line.cursor = Tolower(c); 262276881Sbapt else if (Islower(c)) 263276881Sbapt *el->el_line.cursor = Toupper(c); 264148834Sstefanf 265148834Sstefanf if (++el->el_line.cursor >= el->el_line.lastchar) { 266148834Sstefanf el->el_line.cursor--; 267148834Sstefanf re_fastaddc(el); 268148834Sstefanf break; 269148834Sstefanf } 27084260Sobrien re_fastaddc(el); 27184260Sobrien } 272148834Sstefanf return CC_NORM; 2731573Srgrimes} 2741573Srgrimes 2751573Srgrimes 2768870Srgrimes/* vi_change_meta(): 2771573Srgrimes * Vi change prefix command 2781573Srgrimes * [c] 2791573Srgrimes */ 2801573Srgrimesprotected el_action_t 2811573Srgrimes/*ARGSUSED*/ 282276881Sbaptvi_change_meta(EditLine *el, Int c __attribute__((__unused__))) 2831573Srgrimes{ 28484260Sobrien 28584260Sobrien /* 28684260Sobrien * Delete with insert == change: first we delete and then we leave in 28784260Sobrien * insert mode. 28884260Sobrien */ 289276881Sbapt return cv_action(el, DELETE | INSERT); 2901573Srgrimes} 2911573Srgrimes 2921573Srgrimes 2938870Srgrimes/* vi_insert_at_bol(): 2941573Srgrimes * Vi enter insert mode at the beginning of line 2951573Srgrimes * [I] 2961573Srgrimes */ 2971573Srgrimesprotected el_action_t 2981573Srgrimes/*ARGSUSED*/ 299276881Sbaptvi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__))) 3001573Srgrimes{ 3011573Srgrimes 30284260Sobrien el->el_line.cursor = el->el_line.buffer; 303148834Sstefanf cv_undo(el); 30484260Sobrien el->el_map.current = el->el_map.key; 305276881Sbapt return CC_CURSOR; 3061573Srgrimes} 3071573Srgrimes 3081573Srgrimes 3098870Srgrimes/* vi_replace_char(): 3101573Srgrimes * Vi replace character under the cursor with the next character typed 3111573Srgrimes * [r] 3121573Srgrimes */ 3131573Srgrimesprotected el_action_t 3141573Srgrimes/*ARGSUSED*/ 315276881Sbaptvi_replace_char(EditLine *el, Int c __attribute__((__unused__))) 3161573Srgrimes{ 31784260Sobrien 318148834Sstefanf if (el->el_line.cursor >= el->el_line.lastchar) 319148834Sstefanf return CC_ERROR; 320148834Sstefanf 32184260Sobrien el->el_map.current = el->el_map.key; 32284260Sobrien el->el_state.inputmode = MODE_REPLACE_1; 323148834Sstefanf cv_undo(el); 324276881Sbapt return CC_ARGHACK; 3251573Srgrimes} 3261573Srgrimes 3271573Srgrimes 3288870Srgrimes/* vi_replace_mode(): 3291573Srgrimes * Vi enter replace mode 3301573Srgrimes * [R] 3311573Srgrimes */ 3321573Srgrimesprotected el_action_t 3331573Srgrimes/*ARGSUSED*/ 334276881Sbaptvi_replace_mode(EditLine *el, Int c __attribute__((__unused__))) 3351573Srgrimes{ 33684260Sobrien 33784260Sobrien el->el_map.current = el->el_map.key; 33884260Sobrien el->el_state.inputmode = MODE_REPLACE; 339148834Sstefanf cv_undo(el); 340276881Sbapt return CC_NORM; 3411573Srgrimes} 3421573Srgrimes 3431573Srgrimes 3448870Srgrimes/* vi_substitute_char(): 3451573Srgrimes * Vi replace character under the cursor and enter insert mode 34637199Sbrian * [s] 3471573Srgrimes */ 3481573Srgrimesprotected el_action_t 3491573Srgrimes/*ARGSUSED*/ 350276881Sbaptvi_substitute_char(EditLine *el, Int c __attribute__((__unused__))) 3511573Srgrimes{ 35284260Sobrien 35384260Sobrien c_delafter(el, el->el_state.argument); 35484260Sobrien el->el_map.current = el->el_map.key; 355276881Sbapt return CC_REFRESH; 3561573Srgrimes} 3571573Srgrimes 3581573Srgrimes 3598870Srgrimes/* vi_substitute_line(): 3601573Srgrimes * Vi substitute entire line 3611573Srgrimes * [S] 3621573Srgrimes */ 3631573Srgrimesprotected el_action_t 3641573Srgrimes/*ARGSUSED*/ 365276881Sbaptvi_substitute_line(EditLine *el, Int c __attribute__((__unused__))) 3661573Srgrimes{ 36784260Sobrien 368148834Sstefanf cv_undo(el); 369148834Sstefanf cv_yank(el, el->el_line.buffer, 370237448Spfg (int)(el->el_line.lastchar - el->el_line.buffer)); 37184260Sobrien (void) em_kill_line(el, 0); 37284260Sobrien el->el_map.current = el->el_map.key; 373276881Sbapt return CC_REFRESH; 3741573Srgrimes} 3751573Srgrimes 3761573Srgrimes 3778870Srgrimes/* vi_change_to_eol(): 3781573Srgrimes * Vi change to end of line 3791573Srgrimes * [C] 3801573Srgrimes */ 3811573Srgrimesprotected el_action_t 3821573Srgrimes/*ARGSUSED*/ 383276881Sbaptvi_change_to_eol(EditLine *el, Int c __attribute__((__unused__))) 3841573Srgrimes{ 38584260Sobrien 386148834Sstefanf cv_undo(el); 387148834Sstefanf cv_yank(el, el->el_line.cursor, 388237448Spfg (int)(el->el_line.lastchar - el->el_line.cursor)); 38984260Sobrien (void) ed_kill_line(el, 0); 39084260Sobrien el->el_map.current = el->el_map.key; 391276881Sbapt return CC_REFRESH; 3921573Srgrimes} 3931573Srgrimes 3941573Srgrimes 3951573Srgrimes/* vi_insert(): 3961573Srgrimes * Vi enter insert mode 3971573Srgrimes * [i] 3981573Srgrimes */ 3991573Srgrimesprotected el_action_t 4001573Srgrimes/*ARGSUSED*/ 401276881Sbaptvi_insert(EditLine *el, Int c __attribute__((__unused__))) 4021573Srgrimes{ 4031573Srgrimes 40484260Sobrien el->el_map.current = el->el_map.key; 405148834Sstefanf cv_undo(el); 406276881Sbapt return CC_NORM; 4071573Srgrimes} 4081573Srgrimes 4091573Srgrimes 4101573Srgrimes/* vi_add(): 4118870Srgrimes * Vi enter insert mode after the cursor 4121573Srgrimes * [a] 4131573Srgrimes */ 4141573Srgrimesprotected el_action_t 4151573Srgrimes/*ARGSUSED*/ 416276881Sbaptvi_add(EditLine *el, Int c __attribute__((__unused__))) 4171573Srgrimes{ 418148834Sstefanf int ret; 41937199Sbrian 42084260Sobrien el->el_map.current = el->el_map.key; 42184260Sobrien if (el->el_line.cursor < el->el_line.lastchar) { 42284260Sobrien el->el_line.cursor++; 42384260Sobrien if (el->el_line.cursor > el->el_line.lastchar) 42484260Sobrien el->el_line.cursor = el->el_line.lastchar; 42584260Sobrien ret = CC_CURSOR; 42684260Sobrien } else 42784260Sobrien ret = CC_NORM; 4281573Srgrimes 429148834Sstefanf cv_undo(el); 4301573Srgrimes 431276881Sbapt return (el_action_t)ret; 4321573Srgrimes} 4331573Srgrimes 4341573Srgrimes 4351573Srgrimes/* vi_add_at_eol(): 4361573Srgrimes * Vi enter insert mode at end of line 4371573Srgrimes * [A] 4381573Srgrimes */ 4391573Srgrimesprotected el_action_t 4401573Srgrimes/*ARGSUSED*/ 441276881Sbaptvi_add_at_eol(EditLine *el, Int c __attribute__((__unused__))) 4421573Srgrimes{ 4431573Srgrimes 44484260Sobrien el->el_map.current = el->el_map.key; 44584260Sobrien el->el_line.cursor = el->el_line.lastchar; 446148834Sstefanf cv_undo(el); 447276881Sbapt return CC_CURSOR; 4481573Srgrimes} 4491573Srgrimes 4501573Srgrimes 4511573Srgrimes/* vi_delete_meta(): 4528870Srgrimes * Vi delete prefix command 4531573Srgrimes * [d] 4541573Srgrimes */ 4551573Srgrimesprotected el_action_t 4561573Srgrimes/*ARGSUSED*/ 457276881Sbaptvi_delete_meta(EditLine *el, Int c __attribute__((__unused__))) 4581573Srgrimes{ 45984260Sobrien 460276881Sbapt return cv_action(el, DELETE); 4611573Srgrimes} 4621573Srgrimes 4631573Srgrimes 464148834Sstefanf/* vi_end_big_word(): 4658870Srgrimes * Vi move to the end of the current space delimited word 4668870Srgrimes * [E] 4671573Srgrimes */ 4681573Srgrimesprotected el_action_t 4691573Srgrimes/*ARGSUSED*/ 470276881Sbaptvi_end_big_word(EditLine *el, Int c __attribute__((__unused__))) 4711573Srgrimes{ 4721573Srgrimes 47384260Sobrien if (el->el_line.cursor == el->el_line.lastchar) 474276881Sbapt return CC_ERROR; 4751573Srgrimes 47684260Sobrien el->el_line.cursor = cv__endword(el->el_line.cursor, 477148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isWord); 4781573Srgrimes 479148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 48084260Sobrien el->el_line.cursor++; 48184260Sobrien cv_delfini(el); 482276881Sbapt return CC_REFRESH; 48384260Sobrien } 484276881Sbapt return CC_CURSOR; 4851573Srgrimes} 4861573Srgrimes 4871573Srgrimes 488148834Sstefanf/* vi_end_word(): 4891573Srgrimes * Vi move to the end of the current word 4901573Srgrimes * [e] 4911573Srgrimes */ 4921573Srgrimesprotected el_action_t 4931573Srgrimes/*ARGSUSED*/ 494276881Sbaptvi_end_word(EditLine *el, Int c __attribute__((__unused__))) 4951573Srgrimes{ 4961573Srgrimes 49784260Sobrien if (el->el_line.cursor == el->el_line.lastchar) 498276881Sbapt return CC_ERROR; 4991573Srgrimes 50084260Sobrien el->el_line.cursor = cv__endword(el->el_line.cursor, 501148834Sstefanf el->el_line.lastchar, el->el_state.argument, cv__isword); 5021573Srgrimes 503148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 50484260Sobrien el->el_line.cursor++; 50584260Sobrien cv_delfini(el); 506276881Sbapt return CC_REFRESH; 50784260Sobrien } 508276881Sbapt return CC_CURSOR; 5091573Srgrimes} 5101573Srgrimes 5111573Srgrimes 5121573Srgrimes/* vi_undo(): 5131573Srgrimes * Vi undo last change 5141573Srgrimes * [u] 5151573Srgrimes */ 5161573Srgrimesprotected el_action_t 5171573Srgrimes/*ARGSUSED*/ 518276881Sbaptvi_undo(EditLine *el, Int c __attribute__((__unused__))) 5191573Srgrimes{ 520148834Sstefanf c_undo_t un = el->el_chared.c_undo; 5211573Srgrimes 522148834Sstefanf if (un.len == -1) 523148834Sstefanf return CC_ERROR; 5241573Srgrimes 525148834Sstefanf /* switch line buffer and undo buffer */ 526148834Sstefanf el->el_chared.c_undo.buf = el->el_line.buffer; 527148834Sstefanf el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; 528237448Spfg el->el_chared.c_undo.cursor = 529237448Spfg (int)(el->el_line.cursor - el->el_line.buffer); 530148834Sstefanf el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); 531148834Sstefanf el->el_line.buffer = un.buf; 532148834Sstefanf el->el_line.cursor = un.buf + un.cursor; 533148834Sstefanf el->el_line.lastchar = un.buf + un.len; 5341573Srgrimes 535276881Sbapt return CC_REFRESH; 5361573Srgrimes} 5371573Srgrimes 5381573Srgrimes 5391573Srgrimes/* vi_command_mode(): 5401573Srgrimes * Vi enter command mode (use alternative key bindings) 5411573Srgrimes * [<ESC>] 5421573Srgrimes */ 5431573Srgrimesprotected el_action_t 5441573Srgrimes/*ARGSUSED*/ 545276881Sbaptvi_command_mode(EditLine *el, Int c __attribute__((__unused__))) 5461573Srgrimes{ 5471573Srgrimes 54884260Sobrien /* [Esc] cancels pending action */ 54984260Sobrien el->el_chared.c_vcmd.action = NOP; 55084260Sobrien el->el_chared.c_vcmd.pos = 0; 5511573Srgrimes 55284260Sobrien el->el_state.doingarg = 0; 55384260Sobrien 55484260Sobrien el->el_state.inputmode = MODE_INSERT; 55584260Sobrien el->el_map.current = el->el_map.alt; 5561573Srgrimes#ifdef VI_MOVE 55784260Sobrien if (el->el_line.cursor > el->el_line.buffer) 55884260Sobrien el->el_line.cursor--; 5591573Srgrimes#endif 560276881Sbapt return CC_CURSOR; 5611573Srgrimes} 5621573Srgrimes 56384260Sobrien 5641573Srgrimes/* vi_zero(): 5658870Srgrimes * Vi move to the beginning of line 5661573Srgrimes * [0] 5671573Srgrimes */ 5681573Srgrimesprotected el_action_t 569276881Sbaptvi_zero(EditLine *el, Int c) 5701573Srgrimes{ 57184260Sobrien 572148834Sstefanf if (el->el_state.doingarg) 573148834Sstefanf return ed_argument_digit(el, c); 574148834Sstefanf 575148834Sstefanf el->el_line.cursor = el->el_line.buffer; 576148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 577148834Sstefanf cv_delfini(el); 578276881Sbapt return CC_REFRESH; 57984260Sobrien } 580276881Sbapt return CC_CURSOR; 5811573Srgrimes} 5821573Srgrimes 5831573Srgrimes 5841573Srgrimes/* vi_delete_prev_char(): 5858870Srgrimes * Vi move to previous character (backspace) 586148834Sstefanf * [^H] in insert mode only 5878870Srgrimes */ 5881573Srgrimesprotected el_action_t 5891573Srgrimes/*ARGSUSED*/ 590276881Sbaptvi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__))) 5911573Srgrimes{ 5921573Srgrimes 593148834Sstefanf if (el->el_line.cursor <= el->el_line.buffer) 594276881Sbapt return CC_ERROR; 5951573Srgrimes 596148834Sstefanf c_delbefore1(el); 597148834Sstefanf el->el_line.cursor--; 598276881Sbapt return CC_REFRESH; 59984260Sobrien} 6001573Srgrimes 60184260Sobrien 6021573Srgrimes/* vi_list_or_eof(): 6031573Srgrimes * Vi list choices for completion or indicate end of file if empty line 6041573Srgrimes * [^D] 6051573Srgrimes */ 6061573Srgrimesprotected el_action_t 6071573Srgrimes/*ARGSUSED*/ 608276881Sbaptvi_list_or_eof(EditLine *el, Int c) 6091573Srgrimes{ 61084260Sobrien 611148834Sstefanf if (el->el_line.cursor == el->el_line.lastchar) { 612148834Sstefanf if (el->el_line.cursor == el->el_line.buffer) { 613276881Sbapt terminal_writec(el, c); /* then do a EOF */ 614276881Sbapt return CC_EOF; 615148834Sstefanf } else { 616148834Sstefanf /* 617148834Sstefanf * Here we could list completions, but it is an 618148834Sstefanf * error right now 619148834Sstefanf */ 620276881Sbapt terminal_beep(el); 621276881Sbapt return CC_ERROR; 622148834Sstefanf } 623148834Sstefanf } else { 6241573Srgrimes#ifdef notyet 62584260Sobrien re_goto_bottom(el); 62684260Sobrien *el->el_line.lastchar = '\0'; /* just in case */ 627276881Sbapt return CC_LIST_CHOICES; 628148834Sstefanf#else 629148834Sstefanf /* 630148834Sstefanf * Just complain for now. 631148834Sstefanf */ 632276881Sbapt terminal_beep(el); 633276881Sbapt return CC_ERROR; 634148834Sstefanf#endif 63584260Sobrien } 6361573Srgrimes} 6371573Srgrimes 6381573Srgrimes 6391573Srgrimes/* vi_kill_line_prev(): 6408870Srgrimes * Vi cut from beginning of line to cursor 6411573Srgrimes * [^U] 6421573Srgrimes */ 6431573Srgrimesprotected el_action_t 6441573Srgrimes/*ARGSUSED*/ 645276881Sbaptvi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__))) 6461573Srgrimes{ 647276881Sbapt Char *kp, *cp; 6481573Srgrimes 64984260Sobrien cp = el->el_line.buffer; 65084260Sobrien kp = el->el_chared.c_kill.buf; 65184260Sobrien while (cp < el->el_line.cursor) 65284260Sobrien *kp++ = *cp++; /* copy it */ 65384260Sobrien el->el_chared.c_kill.last = kp; 654237448Spfg c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); 65584260Sobrien el->el_line.cursor = el->el_line.buffer; /* zap! */ 656276881Sbapt return CC_REFRESH; 6571573Srgrimes} 6581573Srgrimes 6591573Srgrimes 6601573Srgrimes/* vi_search_prev(): 6611573Srgrimes * Vi search history previous 6621573Srgrimes * [?] 6631573Srgrimes */ 6641573Srgrimesprotected el_action_t 6651573Srgrimes/*ARGSUSED*/ 666276881Sbaptvi_search_prev(EditLine *el, Int c __attribute__((__unused__))) 6671573Srgrimes{ 66884260Sobrien 669276881Sbapt return cv_search(el, ED_SEARCH_PREV_HISTORY); 6701573Srgrimes} 6711573Srgrimes 6721573Srgrimes 6731573Srgrimes/* vi_search_next(): 6741573Srgrimes * Vi search history next 6751573Srgrimes * [/] 6761573Srgrimes */ 6771573Srgrimesprotected el_action_t 6781573Srgrimes/*ARGSUSED*/ 679276881Sbaptvi_search_next(EditLine *el, Int c __attribute__((__unused__))) 6801573Srgrimes{ 68184260Sobrien 682276881Sbapt return cv_search(el, ED_SEARCH_NEXT_HISTORY); 6831573Srgrimes} 6841573Srgrimes 6851573Srgrimes 6861573Srgrimes/* vi_repeat_search_next(): 6871573Srgrimes * Vi repeat current search in the same search direction 6881573Srgrimes * [n] 6891573Srgrimes */ 6901573Srgrimesprotected el_action_t 6911573Srgrimes/*ARGSUSED*/ 692276881Sbaptvi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__))) 6931573Srgrimes{ 69484260Sobrien 69584260Sobrien if (el->el_search.patlen == 0) 696276881Sbapt return CC_ERROR; 69784260Sobrien else 698276881Sbapt return cv_repeat_srch(el, el->el_search.patdir); 6991573Srgrimes} 7001573Srgrimes 7011573Srgrimes 7021573Srgrimes/* vi_repeat_search_prev(): 7031573Srgrimes * Vi repeat current search in the opposite search direction 7041573Srgrimes * [N] 7051573Srgrimes */ 7061573Srgrimes/*ARGSUSED*/ 7071573Srgrimesprotected el_action_t 708276881Sbaptvi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__))) 7091573Srgrimes{ 71084260Sobrien 71184260Sobrien if (el->el_search.patlen == 0) 712276881Sbapt return CC_ERROR; 71384260Sobrien else 71484260Sobrien return (cv_repeat_srch(el, 71584260Sobrien el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? 71684260Sobrien ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); 7171573Srgrimes} 7181573Srgrimes 7191573Srgrimes 7201573Srgrimes/* vi_next_char(): 7211573Srgrimes * Vi move to the character specified next 7221573Srgrimes * [f] 7231573Srgrimes */ 7241573Srgrimesprotected el_action_t 7251573Srgrimes/*ARGSUSED*/ 726276881Sbaptvi_next_char(EditLine *el, Int c __attribute__((__unused__))) 7271573Srgrimes{ 728148834Sstefanf return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); 7291573Srgrimes} 7301573Srgrimes 7311573Srgrimes 7321573Srgrimes/* vi_prev_char(): 7331573Srgrimes * Vi move to the character specified previous 7341573Srgrimes * [F] 7351573Srgrimes */ 7361573Srgrimesprotected el_action_t 7371573Srgrimes/*ARGSUSED*/ 738276881Sbaptvi_prev_char(EditLine *el, Int c __attribute__((__unused__))) 7391573Srgrimes{ 740148834Sstefanf return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); 7411573Srgrimes} 7421573Srgrimes 7431573Srgrimes 7441573Srgrimes/* vi_to_next_char(): 7451573Srgrimes * Vi move up to the character specified next 7461573Srgrimes * [t] 7471573Srgrimes */ 7481573Srgrimesprotected el_action_t 7491573Srgrimes/*ARGSUSED*/ 750276881Sbaptvi_to_next_char(EditLine *el, Int c __attribute__((__unused__))) 7511573Srgrimes{ 752148834Sstefanf return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); 7531573Srgrimes} 7541573Srgrimes 7551573Srgrimes 7561573Srgrimes/* vi_to_prev_char(): 7571573Srgrimes * Vi move up to the character specified previous 7581573Srgrimes * [T] 7591573Srgrimes */ 7601573Srgrimesprotected el_action_t 7611573Srgrimes/*ARGSUSED*/ 762276881Sbaptvi_to_prev_char(EditLine *el, Int c __attribute__((__unused__))) 7631573Srgrimes{ 764148834Sstefanf return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); 7651573Srgrimes} 7661573Srgrimes 7671573Srgrimes 7681573Srgrimes/* vi_repeat_next_char(): 7691573Srgrimes * Vi repeat current character search in the same search direction 7701573Srgrimes * [;] 7711573Srgrimes */ 7721573Srgrimesprotected el_action_t 7731573Srgrimes/*ARGSUSED*/ 774276881Sbaptvi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__))) 7751573Srgrimes{ 7761573Srgrimes 777148834Sstefanf return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, 778148834Sstefanf el->el_state.argument, el->el_search.chatflg); 7791573Srgrimes} 7801573Srgrimes 7811573Srgrimes 7821573Srgrimes/* vi_repeat_prev_char(): 7831573Srgrimes * Vi repeat current character search in the opposite search direction 7841573Srgrimes * [,] 7851573Srgrimes */ 7861573Srgrimesprotected el_action_t 7871573Srgrimes/*ARGSUSED*/ 788276881Sbaptvi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__))) 7891573Srgrimes{ 790148834Sstefanf el_action_t r; 791148834Sstefanf int dir = el->el_search.chadir; 7921573Srgrimes 793148834Sstefanf r = cv_csearch(el, -dir, el->el_search.chacha, 794148834Sstefanf el->el_state.argument, el->el_search.chatflg); 795148834Sstefanf el->el_search.chadir = dir; 796148834Sstefanf return r; 797148834Sstefanf} 79884260Sobrien 799148834Sstefanf 800148834Sstefanf/* vi_match(): 801148834Sstefanf * Vi go to matching () {} or [] 802148834Sstefanf * [%] 803148834Sstefanf */ 804148834Sstefanfprotected el_action_t 805148834Sstefanf/*ARGSUSED*/ 806276881Sbaptvi_match(EditLine *el, Int c __attribute__((__unused__))) 807148834Sstefanf{ 808276881Sbapt const Char match_chars[] = STR("()[]{}"); 809276881Sbapt Char *cp; 810237448Spfg size_t delta, i, count; 811276881Sbapt Char o_ch, c_ch; 812148834Sstefanf 813148834Sstefanf *el->el_line.lastchar = '\0'; /* just in case */ 814148834Sstefanf 815276881Sbapt i = Strcspn(el->el_line.cursor, match_chars); 816148834Sstefanf o_ch = el->el_line.cursor[i]; 817148834Sstefanf if (o_ch == 0) 818148834Sstefanf return CC_ERROR; 819276881Sbapt delta = (size_t)(Strchr(match_chars, o_ch) - match_chars); 820148834Sstefanf c_ch = match_chars[delta ^ 1]; 821148834Sstefanf count = 1; 822148834Sstefanf delta = 1 - (delta & 1) * 2; 823148834Sstefanf 824148834Sstefanf for (cp = &el->el_line.cursor[i]; count; ) { 825148834Sstefanf cp += delta; 826148834Sstefanf if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) 827148834Sstefanf return CC_ERROR; 828148834Sstefanf if (*cp == o_ch) 829148834Sstefanf count++; 830148834Sstefanf else if (*cp == c_ch) 831148834Sstefanf count--; 832148834Sstefanf } 833148834Sstefanf 834148834Sstefanf el->el_line.cursor = cp; 835148834Sstefanf 836148834Sstefanf if (el->el_chared.c_vcmd.action != NOP) { 837148834Sstefanf /* NB posix says char under cursor should NOT be deleted 838148834Sstefanf for -ve delta - this is different to netbsd vi. */ 839148834Sstefanf if (delta > 0) 840148834Sstefanf el->el_line.cursor++; 841148834Sstefanf cv_delfini(el); 842276881Sbapt return CC_REFRESH; 843148834Sstefanf } 844276881Sbapt return CC_CURSOR; 8451573Srgrimes} 846148834Sstefanf 847148834Sstefanf/* vi_undo_line(): 848148834Sstefanf * Vi undo all changes to line 849148834Sstefanf * [U] 850148834Sstefanf */ 851148834Sstefanfprotected el_action_t 852148834Sstefanf/*ARGSUSED*/ 853276881Sbaptvi_undo_line(EditLine *el, Int c __attribute__((__unused__))) 854148834Sstefanf{ 855148834Sstefanf 856148834Sstefanf cv_undo(el); 857148834Sstefanf return hist_get(el); 858148834Sstefanf} 859148834Sstefanf 860148834Sstefanf/* vi_to_column(): 861148834Sstefanf * Vi go to specified column 862148834Sstefanf * [|] 863148834Sstefanf * NB netbsd vi goes to screen column 'n', posix says nth character 864148834Sstefanf */ 865148834Sstefanfprotected el_action_t 866148834Sstefanf/*ARGSUSED*/ 867276881Sbaptvi_to_column(EditLine *el, Int c __attribute__((__unused__))) 868148834Sstefanf{ 869148834Sstefanf 870148834Sstefanf el->el_line.cursor = el->el_line.buffer; 871148834Sstefanf el->el_state.argument--; 872148834Sstefanf return ed_next_char(el, 0); 873148834Sstefanf} 874148834Sstefanf 875148834Sstefanf/* vi_yank_end(): 876148834Sstefanf * Vi yank to end of line 877148834Sstefanf * [Y] 878148834Sstefanf */ 879148834Sstefanfprotected el_action_t 880148834Sstefanf/*ARGSUSED*/ 881276881Sbaptvi_yank_end(EditLine *el, Int c __attribute__((__unused__))) 882148834Sstefanf{ 883148834Sstefanf 884148834Sstefanf cv_yank(el, el->el_line.cursor, 885237448Spfg (int)(el->el_line.lastchar - el->el_line.cursor)); 886148834Sstefanf return CC_REFRESH; 887148834Sstefanf} 888148834Sstefanf 889148834Sstefanf/* vi_yank(): 890148834Sstefanf * Vi yank 891148834Sstefanf * [y] 892148834Sstefanf */ 893148834Sstefanfprotected el_action_t 894148834Sstefanf/*ARGSUSED*/ 895276881Sbaptvi_yank(EditLine *el, Int c __attribute__((__unused__))) 896148834Sstefanf{ 897148834Sstefanf 898148834Sstefanf return cv_action(el, YANK); 899148834Sstefanf} 900148834Sstefanf 901148834Sstefanf/* vi_comment_out(): 902148834Sstefanf * Vi comment out current command 903148848Sstefanf * [#] 904148834Sstefanf */ 905148834Sstefanfprotected el_action_t 906148834Sstefanf/*ARGSUSED*/ 907276881Sbaptvi_comment_out(EditLine *el, Int c __attribute__((__unused__))) 908148834Sstefanf{ 909148834Sstefanf 910148834Sstefanf el->el_line.cursor = el->el_line.buffer; 911148834Sstefanf c_insert(el, 1); 912148834Sstefanf *el->el_line.cursor = '#'; 913148834Sstefanf re_refresh(el); 914148834Sstefanf return ed_newline(el, 0); 915148834Sstefanf} 916148834Sstefanf 917148834Sstefanf/* vi_alias(): 918148834Sstefanf * Vi include shell alias 919148834Sstefanf * [@] 920148848Sstefanf * NB: posix implies that we should enter insert mode, however 921148834Sstefanf * this is against historical precedent... 922148834Sstefanf */ 923148834Sstefanfprotected el_action_t 924148834Sstefanf/*ARGSUSED*/ 925276881Sbaptvi_alias(EditLine *el, Int c __attribute__((__unused__))) 926148834Sstefanf{ 927148834Sstefanf char alias_name[3]; 928276881Sbapt const char *alias_text; 929148834Sstefanf 930276881Sbapt if (el->el_chared.c_aliasfun == NULL) 931148834Sstefanf return CC_ERROR; 932148834Sstefanf 933148834Sstefanf alias_name[0] = '_'; 934148834Sstefanf alias_name[2] = 0; 935148834Sstefanf if (el_getc(el, &alias_name[1]) != 1) 936148834Sstefanf return CC_ERROR; 937148834Sstefanf 938276881Sbapt alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, 939276881Sbapt alias_name); 940148834Sstefanf if (alias_text != NULL) 941276881Sbapt FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch)); 942148834Sstefanf return CC_NORM; 943148834Sstefanf} 944148834Sstefanf 945148834Sstefanf/* vi_to_history_line(): 946148834Sstefanf * Vi go to specified history file line. 947148834Sstefanf * [G] 948148834Sstefanf */ 949148834Sstefanfprotected el_action_t 950148834Sstefanf/*ARGSUSED*/ 951276881Sbaptvi_to_history_line(EditLine *el, Int c __attribute__((__unused__))) 952148834Sstefanf{ 953148834Sstefanf int sv_event_no = el->el_history.eventno; 954148834Sstefanf el_action_t rval; 955148834Sstefanf 956148834Sstefanf 957148834Sstefanf if (el->el_history.eventno == 0) { 958276881Sbapt (void) Strncpy(el->el_history.buf, el->el_line.buffer, 959148834Sstefanf EL_BUFSIZ); 960148834Sstefanf el->el_history.last = el->el_history.buf + 961148834Sstefanf (el->el_line.lastchar - el->el_line.buffer); 962148834Sstefanf } 963148834Sstefanf 964148834Sstefanf /* Lack of a 'count' means oldest, not 1 */ 965148834Sstefanf if (!el->el_state.doingarg) { 966148834Sstefanf el->el_history.eventno = 0x7fffffff; 967148834Sstefanf hist_get(el); 968148834Sstefanf } else { 969148834Sstefanf /* This is brain dead, all the rest of this code counts 970148834Sstefanf * upwards going into the past. Here we need count in the 971148834Sstefanf * other direction (to match the output of fc -l). 972148834Sstefanf * I could change the world, but this seems to suffice. 973148834Sstefanf */ 974148834Sstefanf el->el_history.eventno = 1; 975148834Sstefanf if (hist_get(el) == CC_ERROR) 976148834Sstefanf return CC_ERROR; 977148834Sstefanf el->el_history.eventno = 1 + el->el_history.ev.num 978148834Sstefanf - el->el_state.argument; 979148834Sstefanf if (el->el_history.eventno < 0) { 980148834Sstefanf el->el_history.eventno = sv_event_no; 981148834Sstefanf return CC_ERROR; 982148834Sstefanf } 983148834Sstefanf } 984148834Sstefanf rval = hist_get(el); 985148834Sstefanf if (rval == CC_ERROR) 986148834Sstefanf el->el_history.eventno = sv_event_no; 987148834Sstefanf return rval; 988148834Sstefanf} 989148834Sstefanf 990148834Sstefanf/* vi_histedit(): 991148834Sstefanf * Vi edit history line with vi 992148834Sstefanf * [v] 993148834Sstefanf */ 994148834Sstefanfprotected el_action_t 995148834Sstefanf/*ARGSUSED*/ 996276881Sbaptvi_histedit(EditLine *el, Int c __attribute__((__unused__))) 997148834Sstefanf{ 998148834Sstefanf int fd; 999148834Sstefanf pid_t pid; 1000237448Spfg ssize_t st; 1001237448Spfg int status; 1002148834Sstefanf char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; 1003276881Sbapt char *cp = NULL; 1004276881Sbapt size_t len; 1005276881Sbapt Char *line = NULL; 1006148834Sstefanf 1007148834Sstefanf if (el->el_state.doingarg) { 1008148834Sstefanf if (vi_to_history_line(el, 0) == CC_ERROR) 1009148834Sstefanf return CC_ERROR; 1010148834Sstefanf } 1011148834Sstefanf 1012148834Sstefanf fd = mkstemp(tempfile); 1013148834Sstefanf if (fd < 0) 1014148834Sstefanf return CC_ERROR; 1015276881Sbapt len = (size_t)(el->el_line.lastchar - el->el_line.buffer); 1016276881Sbapt#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) 1017276881Sbapt cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); 1018276881Sbapt if (cp == NULL) 1019276881Sbapt goto error; 1020276881Sbapt line = el_malloc(len * sizeof(*line) + 1); 1021276881Sbapt if (line == NULL) 1022276881Sbapt goto error; 1023276881Sbapt Strncpy(line, el->el_line.buffer, len); 1024276881Sbapt line[len] = '\0'; 1025276881Sbapt ct_wcstombs(cp, line, TMP_BUFSIZ - 1); 1026276881Sbapt cp[TMP_BUFSIZ - 1] = '\0'; 1027276881Sbapt len = strlen(cp); 1028276881Sbapt write(fd, cp, len); 1029276881Sbapt write(fd, "\n", (size_t)1); 1030148834Sstefanf pid = fork(); 1031148834Sstefanf switch (pid) { 1032148834Sstefanf case -1: 1033276881Sbapt goto error; 1034148834Sstefanf case 0: 1035148834Sstefanf close(fd); 1036237448Spfg execlp("vi", "vi", tempfile, (char *)NULL); 1037148834Sstefanf exit(0); 1038148834Sstefanf /*NOTREACHED*/ 1039148834Sstefanf default: 1040237448Spfg while (waitpid(pid, &status, 0) != pid) 1041148834Sstefanf continue; 1042237448Spfg lseek(fd, (off_t)0, SEEK_SET); 1043290065Sjilles st = read(fd, cp, TMP_BUFSIZ - 1); 1044276881Sbapt if (st > 0) { 1045290065Sjilles cp[st] = '\0'; 1046290065Sjilles len = (size_t)(el->el_line.limit - el->el_line.buffer); 1047276881Sbapt len = ct_mbstowcs(el->el_line.buffer, cp, len); 1048290065Sjilles if (len > 0 && el->el_line.buffer[len - 1] == '\n') 1049276881Sbapt --len; 1050276881Sbapt } 1051276881Sbapt else 1052276881Sbapt len = 0; 1053276881Sbapt el->el_line.cursor = el->el_line.buffer; 1054276881Sbapt el->el_line.lastchar = el->el_line.buffer + len; 1055276881Sbapt el_free(cp); 1056276881Sbapt el_free(line); 1057148834Sstefanf break; 1058148834Sstefanf } 1059148834Sstefanf 1060148834Sstefanf close(fd); 1061148834Sstefanf unlink(tempfile); 1062148834Sstefanf /* return CC_REFRESH; */ 1063148834Sstefanf return ed_newline(el, 0); 1064276881Sbapterror: 1065276881Sbapt el_free(line); 1066276881Sbapt el_free(cp); 1067276881Sbapt close(fd); 1068276881Sbapt unlink(tempfile); 1069276881Sbapt return CC_ERROR; 1070148834Sstefanf} 1071148834Sstefanf 1072148834Sstefanf/* vi_history_word(): 1073148834Sstefanf * Vi append word from previous input line 1074148834Sstefanf * [_] 1075148834Sstefanf * Who knows where this one came from! 1076148834Sstefanf * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' 1077148834Sstefanf */ 1078148834Sstefanfprotected el_action_t 1079148834Sstefanf/*ARGSUSED*/ 1080276881Sbaptvi_history_word(EditLine *el, Int c __attribute__((__unused__))) 1081148834Sstefanf{ 1082276881Sbapt const Char *wp = HIST_FIRST(el); 1083276881Sbapt const Char *wep, *wsp; 1084148834Sstefanf int len; 1085276881Sbapt Char *cp; 1086276881Sbapt const Char *lim; 1087148834Sstefanf 1088148834Sstefanf if (wp == NULL) 1089148834Sstefanf return CC_ERROR; 1090148834Sstefanf 1091148834Sstefanf wep = wsp = 0; 1092148834Sstefanf do { 1093276881Sbapt while (Isspace(*wp)) 1094148834Sstefanf wp++; 1095148834Sstefanf if (*wp == 0) 1096148834Sstefanf break; 1097148834Sstefanf wsp = wp; 1098276881Sbapt while (*wp && !Isspace(*wp)) 1099148834Sstefanf wp++; 1100148834Sstefanf wep = wp; 1101276881Sbapt } while ((!el->el_state.doingarg || --el->el_state.argument > 0) 1102276881Sbapt && *wp != 0); 1103148834Sstefanf 1104148834Sstefanf if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) 1105148834Sstefanf return CC_ERROR; 1106148834Sstefanf 1107148834Sstefanf cv_undo(el); 1108237448Spfg len = (int)(wep - wsp); 1109148834Sstefanf if (el->el_line.cursor < el->el_line.lastchar) 1110148834Sstefanf el->el_line.cursor++; 1111148834Sstefanf c_insert(el, len + 1); 1112148834Sstefanf cp = el->el_line.cursor; 1113148834Sstefanf lim = el->el_line.limit; 1114148834Sstefanf if (cp < lim) 1115148834Sstefanf *cp++ = ' '; 1116148834Sstefanf while (wsp < wep && cp < lim) 1117148834Sstefanf *cp++ = *wsp++; 1118148834Sstefanf el->el_line.cursor = cp; 1119148834Sstefanf 1120148834Sstefanf el->el_map.current = el->el_map.key; 1121148834Sstefanf return CC_REFRESH; 1122148834Sstefanf} 1123148834Sstefanf 1124148834Sstefanf/* vi_redo(): 1125148834Sstefanf * Vi redo last non-motion command 1126148834Sstefanf * [.] 1127148834Sstefanf */ 1128148834Sstefanfprotected el_action_t 1129148834Sstefanf/*ARGSUSED*/ 1130276881Sbaptvi_redo(EditLine *el, Int c __attribute__((__unused__))) 1131148834Sstefanf{ 1132148834Sstefanf c_redo_t *r = &el->el_chared.c_redo; 1133148834Sstefanf 1134148834Sstefanf if (!el->el_state.doingarg && r->count) { 1135148834Sstefanf el->el_state.doingarg = 1; 1136148834Sstefanf el->el_state.argument = r->count; 1137148834Sstefanf } 1138148834Sstefanf 1139148834Sstefanf el->el_chared.c_vcmd.pos = el->el_line.cursor; 1140148834Sstefanf el->el_chared.c_vcmd.action = r->action; 1141148834Sstefanf if (r->pos != r->buf) { 1142148834Sstefanf if (r->pos + 1 > r->lim) 1143148834Sstefanf /* sanity */ 1144148834Sstefanf r->pos = r->lim - 1; 1145148834Sstefanf r->pos[0] = 0; 1146276881Sbapt FUN(el,push)(el, r->buf); 1147148834Sstefanf } 1148148834Sstefanf 1149148834Sstefanf el->el_state.thiscmd = r->cmd; 1150148834Sstefanf el->el_state.thisch = r->ch; 1151276881Sbapt return (*el->el_map.func[r->cmd])(el, r->ch); 1152148834Sstefanf} 1153