Changeset View
Changeset View
Standalone View
Standalone View
lib/libedit/vi.c
/* $NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $ */ | /* $NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 1992, 1993 | * Copyright (c) 1992, 1993 | ||||
* The Regents of the University of California. All rights reserved. | * The Regents of the University of California. All rights reserved. | ||||
* | * | ||||
* This code is derived from software contributed to Berkeley by | * This code is derived from software contributed to Berkeley by | ||||
* Christos Zoulas of Cornell University. | * Christos Zoulas of Cornell University. | ||||
* | * | ||||
Show All 22 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#if !defined(lint) && !defined(SCCSID) | #if !defined(lint) && !defined(SCCSID) | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; | static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; | ||||
#else | #else | ||||
__RCSID("$NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $"); | __RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $"); | ||||
#endif | #endif | ||||
#endif /* not lint && not SCCSID */ | #endif /* not lint && not SCCSID */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
/* | /* | ||||
* vi.c: Vi mode commands. | * vi.c: Vi mode commands. | ||||
*/ | */ | ||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "el.h" | #include "el.h" | ||||
#include "common.h" | #include "common.h" | ||||
#include "emacs.h" | #include "emacs.h" | ||||
#include "fcns.h" | |||||
#include "vi.h" | #include "vi.h" | ||||
private el_action_t cv_action(EditLine *, wint_t); | static el_action_t cv_action(EditLine *, wint_t); | ||||
private el_action_t cv_paste(EditLine *, wint_t); | static el_action_t cv_paste(EditLine *, wint_t); | ||||
/* cv_action(): | /* cv_action(): | ||||
* Handle vi actions. | * Handle vi actions. | ||||
*/ | */ | ||||
private el_action_t | static el_action_t | ||||
cv_action(EditLine *el, wint_t c) | cv_action(EditLine *el, wint_t c) | ||||
{ | { | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
/* 'cc', 'dd' and (possibly) friends */ | /* 'cc', 'dd' and (possibly) friends */ | ||||
if (c != (wint_t)el->el_chared.c_vcmd.action) | if (c != (wint_t)el->el_chared.c_vcmd.action) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
Show All 15 Lines | cv_action(EditLine *el, wint_t c) | ||||
el->el_chared.c_vcmd.pos = el->el_line.cursor; | el->el_chared.c_vcmd.pos = el->el_line.cursor; | ||||
el->el_chared.c_vcmd.action = c; | el->el_chared.c_vcmd.action = c; | ||||
return CC_ARGHACK; | return CC_ARGHACK; | ||||
} | } | ||||
/* cv_paste(): | /* cv_paste(): | ||||
* Paste previous deletion before or after the cursor | * Paste previous deletion before or after the cursor | ||||
*/ | */ | ||||
private el_action_t | static el_action_t | ||||
cv_paste(EditLine *el, wint_t c) | cv_paste(EditLine *el, wint_t c) | ||||
{ | { | ||||
c_kill_t *k = &el->el_chared.c_kill; | c_kill_t *k = &el->el_chared.c_kill; | ||||
size_t len = (size_t)(k->last - k->buf); | size_t len = (size_t)(k->last - k->buf); | ||||
if (k->buf == NULL || len == 0) | if (k->buf == NULL || len == 0) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
#ifdef DEBUG_PASTE | #ifdef DEBUG_PASTE | ||||
(void) fprintf(el->el_errfile, "Paste: \"" FSTARSTR "\"\n", (int)len, | (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len, | ||||
k->buf); | k->buf); | ||||
#endif | #endif | ||||
cv_undo(el); | cv_undo(el); | ||||
if (!c && el->el_line.cursor < el->el_line.lastchar) | if (!c && el->el_line.cursor < el->el_line.lastchar) | ||||
el->el_line.cursor++; | el->el_line.cursor++; | ||||
c_insert(el, (int)len); | c_insert(el, (int)len); | ||||
if (el->el_line.cursor + len > el->el_line.lastchar) | if (el->el_line.cursor + len > el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
(void) memcpy(el->el_line.cursor, k->buf, len * | (void) memcpy(el->el_line.cursor, k->buf, len * | ||||
sizeof(*el->el_line.cursor)); | sizeof(*el->el_line.cursor)); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_paste_next(): | /* vi_paste_next(): | ||||
* Vi paste previous deletion to the right of the cursor | * Vi paste previous deletion to the right of the cursor | ||||
* [p] | * [p] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) | vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_paste(el, 0); | return cv_paste(el, 0); | ||||
} | } | ||||
/* vi_paste_prev(): | /* vi_paste_prev(): | ||||
* Vi paste previous deletion to the left of the cursor | * Vi paste previous deletion to the left of the cursor | ||||
* [P] | * [P] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) | vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_paste(el, 1); | return cv_paste(el, 1); | ||||
} | } | ||||
/* vi_prev_big_word(): | /* vi_prev_big_word(): | ||||
* Vi move to the previous space delimited word | * Vi move to the previous space delimited word | ||||
* [B] | * [B] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor == el->el_line.buffer) | if (el->el_line.cursor == el->el_line.buffer) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv_prev_word(el->el_line.cursor, | el->el_line.cursor = cv_prev_word(el->el_line.cursor, | ||||
el->el_line.buffer, | el->el_line.buffer, | ||||
el->el_state.argument, | el->el_state.argument, | ||||
cv__isWord); | cv__isWord); | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_prev_word(): | /* vi_prev_word(): | ||||
* Vi move to the previous word | * Vi move to the previous word | ||||
* [b] | * [b] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor == el->el_line.buffer) | if (el->el_line.cursor == el->el_line.buffer) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv_prev_word(el->el_line.cursor, | el->el_line.cursor = cv_prev_word(el->el_line.cursor, | ||||
el->el_line.buffer, | el->el_line.buffer, | ||||
el->el_state.argument, | el->el_state.argument, | ||||
cv__isword); | cv__isword); | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_next_big_word(): | /* vi_next_big_word(): | ||||
* Vi move to the next space delimited word | * Vi move to the next space delimited word | ||||
* [W] | * [W] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor >= el->el_line.lastchar - 1) | if (el->el_line.cursor >= el->el_line.lastchar - 1) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv_next_word(el, el->el_line.cursor, | el->el_line.cursor = cv_next_word(el, el->el_line.cursor, | ||||
el->el_line.lastchar, el->el_state.argument, cv__isWord); | el->el_line.lastchar, el->el_state.argument, cv__isWord); | ||||
if (el->el_map.type == MAP_VI) | if (el->el_map.type == MAP_VI) | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_next_word(): | /* vi_next_word(): | ||||
* Vi move to the next word | * Vi move to the next word | ||||
* [w] | * [w] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor >= el->el_line.lastchar - 1) | if (el->el_line.cursor >= el->el_line.lastchar - 1) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv_next_word(el, el->el_line.cursor, | el->el_line.cursor = cv_next_word(el, el->el_line.cursor, | ||||
el->el_line.lastchar, el->el_state.argument, cv__isword); | el->el_line.lastchar, el->el_state.argument, cv__isword); | ||||
if (el->el_map.type == MAP_VI) | if (el->el_map.type == MAP_VI) | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_change_case(): | /* vi_change_case(): | ||||
* Vi change case of character under the cursor and advance one character | * Vi change case of character under the cursor and advance one character | ||||
* [~] | * [~] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
vi_change_case(EditLine *el, wint_t c) | vi_change_case(EditLine *el, wint_t c) | ||||
{ | { | ||||
int i; | int i; | ||||
if (el->el_line.cursor >= el->el_line.lastchar) | if (el->el_line.cursor >= el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
cv_undo(el); | cv_undo(el); | ||||
for (i = 0; i < el->el_state.argument; i++) { | for (i = 0; i < el->el_state.argument; i++) { | ||||
c = *el->el_line.cursor; | c = *el->el_line.cursor; | ||||
if (Isupper(c)) | if (iswupper(c)) | ||||
*el->el_line.cursor = Tolower(c); | *el->el_line.cursor = towlower(c); | ||||
else if (Islower(c)) | else if (iswlower(c)) | ||||
*el->el_line.cursor = Toupper(c); | *el->el_line.cursor = towupper(c); | ||||
if (++el->el_line.cursor >= el->el_line.lastchar) { | if (++el->el_line.cursor >= el->el_line.lastchar) { | ||||
el->el_line.cursor--; | el->el_line.cursor--; | ||||
re_fastaddc(el); | re_fastaddc(el); | ||||
break; | break; | ||||
} | } | ||||
re_fastaddc(el); | re_fastaddc(el); | ||||
} | } | ||||
return CC_NORM; | return CC_NORM; | ||||
} | } | ||||
/* vi_change_meta(): | /* vi_change_meta(): | ||||
* Vi change prefix command | * Vi change prefix command | ||||
* [c] | * [c] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) | vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
/* | /* | ||||
* Delete with insert == change: first we delete and then we leave in | * Delete with insert == change: first we delete and then we leave in | ||||
* insert mode. | * insert mode. | ||||
*/ | */ | ||||
return cv_action(el, DELETE | INSERT); | return cv_action(el, DELETE | INSERT); | ||||
} | } | ||||
/* vi_insert_at_bol(): | /* vi_insert_at_bol(): | ||||
* Vi enter insert mode at the beginning of line | * Vi enter insert mode at the beginning of line | ||||
* [I] | * [I] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) | vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
cv_undo(el); | cv_undo(el); | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_replace_char(): | /* vi_replace_char(): | ||||
* Vi replace character under the cursor with the next character typed | * Vi replace character under the cursor with the next character typed | ||||
* [r] | * [r] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor >= el->el_line.lastchar) | if (el->el_line.cursor >= el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
el->el_state.inputmode = MODE_REPLACE_1; | el->el_state.inputmode = MODE_REPLACE_1; | ||||
cv_undo(el); | cv_undo(el); | ||||
return CC_ARGHACK; | return CC_ARGHACK; | ||||
} | } | ||||
/* vi_replace_mode(): | /* vi_replace_mode(): | ||||
* Vi enter replace mode | * Vi enter replace mode | ||||
* [R] | * [R] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) | vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
el->el_state.inputmode = MODE_REPLACE; | el->el_state.inputmode = MODE_REPLACE; | ||||
cv_undo(el); | cv_undo(el); | ||||
return CC_NORM; | return CC_NORM; | ||||
} | } | ||||
/* vi_substitute_char(): | /* vi_substitute_char(): | ||||
* Vi replace character under the cursor and enter insert mode | * Vi replace character under the cursor and enter insert mode | ||||
* [s] | * [s] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
c_delafter(el, el->el_state.argument); | c_delafter(el, el->el_state.argument); | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_substitute_line(): | /* vi_substitute_line(): | ||||
* Vi substitute entire line | * Vi substitute entire line | ||||
* [S] | * [S] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) | vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
cv_undo(el); | cv_undo(el); | ||||
cv_yank(el, el->el_line.buffer, | cv_yank(el, el->el_line.buffer, | ||||
(int)(el->el_line.lastchar - el->el_line.buffer)); | (int)(el->el_line.lastchar - el->el_line.buffer)); | ||||
(void) em_kill_line(el, 0); | (void) em_kill_line(el, 0); | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_change_to_eol(): | /* vi_change_to_eol(): | ||||
* Vi change to end of line | * Vi change to end of line | ||||
* [C] | * [C] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) | vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
cv_undo(el); | cv_undo(el); | ||||
cv_yank(el, el->el_line.cursor, | cv_yank(el, el->el_line.cursor, | ||||
(int)(el->el_line.lastchar - el->el_line.cursor)); | (int)(el->el_line.lastchar - el->el_line.cursor)); | ||||
(void) ed_kill_line(el, 0); | (void) ed_kill_line(el, 0); | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_insert(): | /* vi_insert(): | ||||
* Vi enter insert mode | * Vi enter insert mode | ||||
* [i] | * [i] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) | vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
cv_undo(el); | cv_undo(el); | ||||
return CC_NORM; | return CC_NORM; | ||||
} | } | ||||
/* vi_add(): | /* vi_add(): | ||||
* Vi enter insert mode after the cursor | * Vi enter insert mode after the cursor | ||||
* [a] | * [a] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_add(EditLine *el, wint_t c __attribute__((__unused__))) | vi_add(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
int ret; | int ret; | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
if (el->el_line.cursor < el->el_line.lastchar) { | if (el->el_line.cursor < el->el_line.lastchar) { | ||||
el->el_line.cursor++; | el->el_line.cursor++; | ||||
if (el->el_line.cursor > el->el_line.lastchar) | if (el->el_line.cursor > el->el_line.lastchar) | ||||
el->el_line.cursor = el->el_line.lastchar; | el->el_line.cursor = el->el_line.lastchar; | ||||
ret = CC_CURSOR; | ret = CC_CURSOR; | ||||
} else | } else | ||||
ret = CC_NORM; | ret = CC_NORM; | ||||
cv_undo(el); | cv_undo(el); | ||||
return (el_action_t)ret; | return (el_action_t)ret; | ||||
} | } | ||||
/* vi_add_at_eol(): | /* vi_add_at_eol(): | ||||
* Vi enter insert mode at end of line | * Vi enter insert mode at end of line | ||||
* [A] | * [A] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) | vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
el->el_line.cursor = el->el_line.lastchar; | el->el_line.cursor = el->el_line.lastchar; | ||||
cv_undo(el); | cv_undo(el); | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_delete_meta(): | /* vi_delete_meta(): | ||||
* Vi delete prefix command | * Vi delete prefix command | ||||
* [d] | * [d] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) | vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_action(el, DELETE); | return cv_action(el, DELETE); | ||||
} | } | ||||
/* vi_end_big_word(): | /* vi_end_big_word(): | ||||
* Vi move to the end of the current space delimited word | * Vi move to the end of the current space delimited word | ||||
* [E] | * [E] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor == el->el_line.lastchar) | if (el->el_line.cursor == el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv__endword(el->el_line.cursor, | el->el_line.cursor = cv__endword(el->el_line.cursor, | ||||
el->el_line.lastchar, el->el_state.argument, cv__isWord); | el->el_line.lastchar, el->el_state.argument, cv__isWord); | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
el->el_line.cursor++; | el->el_line.cursor++; | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_end_word(): | /* vi_end_word(): | ||||
* Vi move to the end of the current word | * Vi move to the end of the current word | ||||
* [e] | * [e] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor == el->el_line.lastchar) | if (el->el_line.cursor == el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
el->el_line.cursor = cv__endword(el->el_line.cursor, | el->el_line.cursor = cv__endword(el->el_line.cursor, | ||||
el->el_line.lastchar, el->el_state.argument, cv__isword); | el->el_line.lastchar, el->el_state.argument, cv__isword); | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
el->el_line.cursor++; | el->el_line.cursor++; | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_undo(): | /* vi_undo(): | ||||
* Vi undo last change | * Vi undo last change | ||||
* [u] | * [u] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) | vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
c_undo_t un = el->el_chared.c_undo; | c_undo_t un = el->el_chared.c_undo; | ||||
if (un.len == -1) | if (un.len == -1) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
Show All 10 Lines | vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_command_mode(): | /* vi_command_mode(): | ||||
* Vi enter command mode (use alternative key bindings) | * Vi enter command mode (use alternative key bindings) | ||||
* [<ESC>] | * [<ESC>] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) | vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
/* [Esc] cancels pending action */ | /* [Esc] cancels pending action */ | ||||
el->el_chared.c_vcmd.action = NOP; | el->el_chared.c_vcmd.action = NOP; | ||||
el->el_chared.c_vcmd.pos = 0; | el->el_chared.c_vcmd.pos = 0; | ||||
el->el_state.doingarg = 0; | el->el_state.doingarg = 0; | ||||
el->el_state.inputmode = MODE_INSERT; | el->el_state.inputmode = MODE_INSERT; | ||||
el->el_map.current = el->el_map.alt; | el->el_map.current = el->el_map.alt; | ||||
#ifdef VI_MOVE | #ifdef VI_MOVE | ||||
if (el->el_line.cursor > el->el_line.buffer) | if (el->el_line.cursor > el->el_line.buffer) | ||||
el->el_line.cursor--; | el->el_line.cursor--; | ||||
#endif | #endif | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_zero(): | /* vi_zero(): | ||||
* Vi move to the beginning of line | * Vi move to the beginning of line | ||||
* [0] | * [0] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
vi_zero(EditLine *el, wint_t c) | vi_zero(EditLine *el, wint_t c) | ||||
{ | { | ||||
if (el->el_state.doingarg) | if (el->el_state.doingarg) | ||||
return ed_argument_digit(el, c); | return ed_argument_digit(el, c); | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
if (el->el_chared.c_vcmd.action != NOP) { | if (el->el_chared.c_vcmd.action != NOP) { | ||||
cv_delfini(el); | cv_delfini(el); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_delete_prev_char(): | /* vi_delete_prev_char(): | ||||
* Vi move to previous character (backspace) | * Vi move to previous character (backspace) | ||||
* [^H] in insert mode only | * [^H] in insert mode only | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_line.cursor <= el->el_line.buffer) | if (el->el_line.cursor <= el->el_line.buffer) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
c_delbefore1(el); | c_delbefore1(el); | ||||
el->el_line.cursor--; | el->el_line.cursor--; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_list_or_eof(): | /* vi_list_or_eof(): | ||||
* Vi list choices for completion or indicate end of file if empty line | * Vi list choices for completion or indicate end of file if empty line | ||||
* [^D] | * [^D] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_list_or_eof(EditLine *el, wint_t c) | vi_list_or_eof(EditLine *el, wint_t c) | ||||
{ | { | ||||
if (el->el_line.cursor == el->el_line.lastchar) { | if (el->el_line.cursor == el->el_line.lastchar) { | ||||
if (el->el_line.cursor == el->el_line.buffer) { | if (el->el_line.cursor == el->el_line.buffer) { | ||||
terminal_writec(el, c); /* then do a EOF */ | terminal_writec(el, c); /* then do a EOF */ | ||||
return CC_EOF; | return CC_EOF; | ||||
Show All 20 Lines | #endif | ||||
} | } | ||||
} | } | ||||
/* vi_kill_line_prev(): | /* vi_kill_line_prev(): | ||||
* Vi cut from beginning of line to cursor | * Vi cut from beginning of line to cursor | ||||
* [^U] | * [^U] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__))) | vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
Char *kp, *cp; | wchar_t *kp, *cp; | ||||
cp = el->el_line.buffer; | cp = el->el_line.buffer; | ||||
kp = el->el_chared.c_kill.buf; | kp = el->el_chared.c_kill.buf; | ||||
while (cp < el->el_line.cursor) | while (cp < el->el_line.cursor) | ||||
*kp++ = *cp++; /* copy it */ | *kp++ = *cp++; /* copy it */ | ||||
el->el_chared.c_kill.last = kp; | el->el_chared.c_kill.last = kp; | ||||
c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); | c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); | ||||
el->el_line.cursor = el->el_line.buffer; /* zap! */ | el->el_line.cursor = el->el_line.buffer; /* zap! */ | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_search_prev(): | /* vi_search_prev(): | ||||
* Vi search history previous | * Vi search history previous | ||||
* [?] | * [?] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) | vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_search(el, ED_SEARCH_PREV_HISTORY); | return cv_search(el, ED_SEARCH_PREV_HISTORY); | ||||
} | } | ||||
/* vi_search_next(): | /* vi_search_next(): | ||||
* Vi search history next | * Vi search history next | ||||
* [/] | * [/] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) | vi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_search(el, ED_SEARCH_NEXT_HISTORY); | return cv_search(el, ED_SEARCH_NEXT_HISTORY); | ||||
} | } | ||||
/* vi_repeat_search_next(): | /* vi_repeat_search_next(): | ||||
* Vi repeat current search in the same search direction | * Vi repeat current search in the same search direction | ||||
* [n] | * [n] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) | vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_search.patlen == 0) | if (el->el_search.patlen == 0) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
else | else | ||||
return cv_repeat_srch(el, el->el_search.patdir); | return cv_repeat_srch(el, el->el_search.patdir); | ||||
} | } | ||||
/* vi_repeat_search_prev(): | /* vi_repeat_search_prev(): | ||||
* Vi repeat current search in the opposite search direction | * Vi repeat current search in the opposite search direction | ||||
* [N] | * [N] | ||||
*/ | */ | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
protected el_action_t | libedit_private el_action_t | ||||
vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) | vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
if (el->el_search.patlen == 0) | if (el->el_search.patlen == 0) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
else | else | ||||
return (cv_repeat_srch(el, | return (cv_repeat_srch(el, | ||||
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? | el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? | ||||
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); | ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); | ||||
} | } | ||||
/* vi_next_char(): | /* vi_next_char(): | ||||
* Vi move to the character specified next | * Vi move to the character specified next | ||||
* [f] | * [f] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); | return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); | ||||
} | } | ||||
/* vi_prev_char(): | /* vi_prev_char(): | ||||
* Vi move to the character specified previous | * Vi move to the character specified previous | ||||
* [F] | * [F] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); | return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); | ||||
} | } | ||||
/* vi_to_next_char(): | /* vi_to_next_char(): | ||||
* Vi move up to the character specified next | * Vi move up to the character specified next | ||||
* [t] | * [t] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); | return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); | ||||
} | } | ||||
/* vi_to_prev_char(): | /* vi_to_prev_char(): | ||||
* Vi move up to the character specified previous | * Vi move up to the character specified previous | ||||
* [T] | * [T] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); | return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); | ||||
} | } | ||||
/* vi_repeat_next_char(): | /* vi_repeat_next_char(): | ||||
* Vi repeat current character search in the same search direction | * Vi repeat current character search in the same search direction | ||||
* [;] | * [;] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, | return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, | ||||
el->el_state.argument, el->el_search.chatflg); | el->el_state.argument, el->el_search.chatflg); | ||||
} | } | ||||
/* vi_repeat_prev_char(): | /* vi_repeat_prev_char(): | ||||
* Vi repeat current character search in the opposite search direction | * Vi repeat current character search in the opposite search direction | ||||
* [,] | * [,] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el_action_t r; | el_action_t r; | ||||
int dir = el->el_search.chadir; | int dir = el->el_search.chadir; | ||||
r = cv_csearch(el, -dir, el->el_search.chacha, | r = cv_csearch(el, -dir, el->el_search.chacha, | ||||
el->el_state.argument, el->el_search.chatflg); | el->el_state.argument, el->el_search.chatflg); | ||||
el->el_search.chadir = dir; | el->el_search.chadir = dir; | ||||
return r; | return r; | ||||
} | } | ||||
/* vi_match(): | /* vi_match(): | ||||
* Vi go to matching () {} or [] | * Vi go to matching () {} or [] | ||||
* [%] | * [%] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_match(EditLine *el, wint_t c __attribute__((__unused__))) | vi_match(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
const Char match_chars[] = STR("()[]{}"); | const wchar_t match_chars[] = L"()[]{}"; | ||||
Char *cp; | wchar_t *cp; | ||||
size_t delta, i, count; | size_t delta, i, count; | ||||
Char o_ch, c_ch; | wchar_t o_ch, c_ch; | ||||
*el->el_line.lastchar = '\0'; /* just in case */ | *el->el_line.lastchar = '\0'; /* just in case */ | ||||
i = Strcspn(el->el_line.cursor, match_chars); | i = wcscspn(el->el_line.cursor, match_chars); | ||||
o_ch = el->el_line.cursor[i]; | o_ch = el->el_line.cursor[i]; | ||||
if (o_ch == 0) | if (o_ch == 0) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
delta = (size_t)(Strchr(match_chars, o_ch) - match_chars); | delta = (size_t)(wcschr(match_chars, o_ch) - match_chars); | ||||
c_ch = match_chars[delta ^ 1]; | c_ch = match_chars[delta ^ 1]; | ||||
count = 1; | count = 1; | ||||
delta = 1 - (delta & 1) * 2; | delta = 1 - (delta & 1) * 2; | ||||
for (cp = &el->el_line.cursor[i]; count; ) { | for (cp = &el->el_line.cursor[i]; count; ) { | ||||
cp += delta; | cp += delta; | ||||
if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) | if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
Show All 15 Lines | vi_match(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
} | } | ||||
return CC_CURSOR; | return CC_CURSOR; | ||||
} | } | ||||
/* vi_undo_line(): | /* vi_undo_line(): | ||||
* Vi undo all changes to line | * Vi undo all changes to line | ||||
* [U] | * [U] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) | vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
cv_undo(el); | cv_undo(el); | ||||
return hist_get(el); | return hist_get(el); | ||||
} | } | ||||
/* vi_to_column(): | /* vi_to_column(): | ||||
* Vi go to specified column | * Vi go to specified column | ||||
* [|] | * [|] | ||||
* NB netbsd vi goes to screen column 'n', posix says nth character | * NB netbsd vi goes to screen column 'n', posix says nth character | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) | vi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
el->el_state.argument--; | el->el_state.argument--; | ||||
return ed_next_char(el, 0); | return ed_next_char(el, 0); | ||||
} | } | ||||
/* vi_yank_end(): | /* vi_yank_end(): | ||||
* Vi yank to end of line | * Vi yank to end of line | ||||
* [Y] | * [Y] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) | vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
cv_yank(el, el->el_line.cursor, | cv_yank(el, el->el_line.cursor, | ||||
(int)(el->el_line.lastchar - el->el_line.cursor)); | (int)(el->el_line.lastchar - el->el_line.cursor)); | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_yank(): | /* vi_yank(): | ||||
* Vi yank | * Vi yank | ||||
* [y] | * [y] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_yank(EditLine *el, wint_t c __attribute__((__unused__))) | vi_yank(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
return cv_action(el, YANK); | return cv_action(el, YANK); | ||||
} | } | ||||
/* vi_comment_out(): | /* vi_comment_out(): | ||||
* Vi comment out current command | * Vi comment out current command | ||||
* [#] | * [#] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) | vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
c_insert(el, 1); | c_insert(el, 1); | ||||
*el->el_line.cursor = '#'; | *el->el_line.cursor = '#'; | ||||
re_refresh(el); | re_refresh(el); | ||||
return ed_newline(el, 0); | return ed_newline(el, 0); | ||||
} | } | ||||
/* vi_alias(): | /* vi_alias(): | ||||
* Vi include shell alias | * Vi include shell alias | ||||
* [@] | * [@] | ||||
* NB: posix implies that we should enter insert mode, however | * NB: posix implies that we should enter insert mode, however | ||||
* this is against historical precedent... | * this is against historical precedent... | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_alias(EditLine *el, wint_t c __attribute__((__unused__))) | vi_alias(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
char alias_name[3]; | char alias_name[3]; | ||||
const char *alias_text; | const char *alias_text; | ||||
if (el->el_chared.c_aliasfun == NULL) | if (el->el_chared.c_aliasfun == NULL) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
alias_name[0] = '_'; | alias_name[0] = '_'; | ||||
alias_name[2] = 0; | alias_name[2] = 0; | ||||
if (el_getc(el, &alias_name[1]) != 1) | if (el_getc(el, &alias_name[1]) != 1) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, | alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, | ||||
alias_name); | alias_name); | ||||
if (alias_text != NULL) | if (alias_text != NULL) | ||||
FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch)); | el_wpush(el, ct_decode_string(alias_text, &el->el_scratch)); | ||||
return CC_NORM; | return CC_NORM; | ||||
} | } | ||||
/* vi_to_history_line(): | /* vi_to_history_line(): | ||||
* Vi go to specified history file line. | * Vi go to specified history file line. | ||||
* [G] | * [G] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) | vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
int sv_event_no = el->el_history.eventno; | int sv_event_no = el->el_history.eventno; | ||||
el_action_t rval; | el_action_t rval; | ||||
if (el->el_history.eventno == 0) { | if (el->el_history.eventno == 0) { | ||||
(void) Strncpy(el->el_history.buf, el->el_line.buffer, | (void) wcsncpy(el->el_history.buf, el->el_line.buffer, | ||||
EL_BUFSIZ); | EL_BUFSIZ); | ||||
el->el_history.last = el->el_history.buf + | el->el_history.last = el->el_history.buf + | ||||
(el->el_line.lastchar - el->el_line.buffer); | (el->el_line.lastchar - el->el_line.buffer); | ||||
} | } | ||||
/* Lack of a 'count' means oldest, not 1 */ | /* Lack of a 'count' means oldest, not 1 */ | ||||
if (!el->el_state.doingarg) { | if (!el->el_state.doingarg) { | ||||
el->el_history.eventno = 0x7fffffff; | el->el_history.eventno = 0x7fffffff; | ||||
Show All 19 Lines | if (rval == CC_ERROR) | ||||
el->el_history.eventno = sv_event_no; | el->el_history.eventno = sv_event_no; | ||||
return rval; | return rval; | ||||
} | } | ||||
/* vi_histedit(): | /* vi_histedit(): | ||||
* Vi edit history line with vi | * Vi edit history line with vi | ||||
* [v] | * [v] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) | vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
int fd; | int fd; | ||||
pid_t pid; | pid_t pid; | ||||
ssize_t st; | ssize_t st; | ||||
int status; | int status; | ||||
char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; | char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; | ||||
char *cp = NULL; | char *cp = NULL; | ||||
size_t len; | size_t len; | ||||
Char *line = NULL; | wchar_t *line = NULL; | ||||
if (el->el_state.doingarg) { | if (el->el_state.doingarg) { | ||||
if (vi_to_history_line(el, 0) == CC_ERROR) | if (vi_to_history_line(el, 0) == CC_ERROR) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
} | } | ||||
fd = mkstemp(tempfile); | fd = mkstemp(tempfile); | ||||
if (fd < 0) | if (fd < 0) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
len = (size_t)(el->el_line.lastchar - el->el_line.buffer); | len = (size_t)(el->el_line.lastchar - el->el_line.buffer); | ||||
#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) | #define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) | ||||
cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); | cp = el_calloc(TMP_BUFSIZ, sizeof(*cp)); | ||||
if (cp == NULL) | if (cp == NULL) | ||||
goto error; | goto error; | ||||
line = el_malloc(len * sizeof(*line) + 1); | line = el_calloc(len + 1, sizeof(*line)); | ||||
if (line == NULL) | if (line == NULL) | ||||
goto error; | goto error; | ||||
Strncpy(line, el->el_line.buffer, len); | wcsncpy(line, el->el_line.buffer, len); | ||||
line[len] = '\0'; | line[len] = '\0'; | ||||
ct_wcstombs(cp, line, TMP_BUFSIZ - 1); | wcstombs(cp, line, TMP_BUFSIZ - 1); | ||||
cp[TMP_BUFSIZ - 1] = '\0'; | cp[TMP_BUFSIZ - 1] = '\0'; | ||||
len = strlen(cp); | len = strlen(cp); | ||||
write(fd, cp, len); | write(fd, cp, len); | ||||
write(fd, "\n", (size_t)1); | write(fd, "\n", (size_t)1); | ||||
pid = fork(); | pid = fork(); | ||||
switch (pid) { | switch (pid) { | ||||
case -1: | case -1: | ||||
goto error; | goto error; | ||||
case 0: | case 0: | ||||
close(fd); | close(fd); | ||||
execlp("vi", "vi", tempfile, (char *)NULL); | execlp("vi", "vi", tempfile, (char *)NULL); | ||||
exit(0); | exit(0); | ||||
/*NOTREACHED*/ | /*NOTREACHED*/ | ||||
default: | default: | ||||
while (waitpid(pid, &status, 0) != pid) | while (waitpid(pid, &status, 0) != pid) | ||||
continue; | continue; | ||||
lseek(fd, (off_t)0, SEEK_SET); | lseek(fd, (off_t)0, SEEK_SET); | ||||
st = read(fd, cp, TMP_BUFSIZ - 1); | st = read(fd, cp, TMP_BUFSIZ - 1); | ||||
if (st > 0) { | if (st > 0) { | ||||
cp[st] = '\0'; | cp[st] = '\0'; | ||||
len = (size_t)(el->el_line.limit - el->el_line.buffer); | len = (size_t)(el->el_line.limit - el->el_line.buffer); | ||||
len = ct_mbstowcs(el->el_line.buffer, cp, len); | len = mbstowcs(el->el_line.buffer, cp, len); | ||||
if (len > 0 && el->el_line.buffer[len - 1] == '\n') | if (len > 0 && el->el_line.buffer[len - 1] == '\n') | ||||
--len; | --len; | ||||
} | } | ||||
else | else | ||||
len = 0; | len = 0; | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
el->el_line.lastchar = el->el_line.buffer + len; | el->el_line.lastchar = el->el_line.buffer + len; | ||||
el_free(cp); | el_free(cp); | ||||
Show All 14 Lines | |||||
} | } | ||||
/* vi_history_word(): | /* vi_history_word(): | ||||
* Vi append word from previous input line | * Vi append word from previous input line | ||||
* [_] | * [_] | ||||
* Who knows where this one came from! | * Who knows where this one came from! | ||||
* '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' | * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) | vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
const Char *wp = HIST_FIRST(el); | const wchar_t *wp = HIST_FIRST(el); | ||||
const Char *wep, *wsp; | const wchar_t *wep, *wsp; | ||||
int len; | int len; | ||||
Char *cp; | wchar_t *cp; | ||||
const Char *lim; | const wchar_t *lim; | ||||
if (wp == NULL) | if (wp == NULL) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
wep = wsp = NULL; | wep = wsp = NULL; | ||||
do { | do { | ||||
while (Isspace(*wp)) | while (iswspace(*wp)) | ||||
wp++; | wp++; | ||||
if (*wp == 0) | if (*wp == 0) | ||||
break; | break; | ||||
wsp = wp; | wsp = wp; | ||||
while (*wp && !Isspace(*wp)) | while (*wp && !iswspace(*wp)) | ||||
wp++; | wp++; | ||||
wep = wp; | wep = wp; | ||||
} while ((!el->el_state.doingarg || --el->el_state.argument > 0) | } while ((!el->el_state.doingarg || --el->el_state.argument > 0) | ||||
&& *wp != 0); | && *wp != 0); | ||||
if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) | if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
Show All 13 Lines | vi_history_word(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
el->el_map.current = el->el_map.key; | el->el_map.current = el->el_map.key; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
/* vi_redo(): | /* vi_redo(): | ||||
* Vi redo last non-motion command | * Vi redo last non-motion command | ||||
* [.] | * [.] | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
vi_redo(EditLine *el, wint_t c __attribute__((__unused__))) | vi_redo(EditLine *el, wint_t c __attribute__((__unused__))) | ||||
{ | { | ||||
c_redo_t *r = &el->el_chared.c_redo; | c_redo_t *r = &el->el_chared.c_redo; | ||||
if (!el->el_state.doingarg && r->count) { | if (!el->el_state.doingarg && r->count) { | ||||
el->el_state.doingarg = 1; | el->el_state.doingarg = 1; | ||||
el->el_state.argument = r->count; | el->el_state.argument = r->count; | ||||
} | } | ||||
el->el_chared.c_vcmd.pos = el->el_line.cursor; | el->el_chared.c_vcmd.pos = el->el_line.cursor; | ||||
el->el_chared.c_vcmd.action = r->action; | el->el_chared.c_vcmd.action = r->action; | ||||
if (r->pos != r->buf) { | if (r->pos != r->buf) { | ||||
if (r->pos + 1 > r->lim) | if (r->pos + 1 > r->lim) | ||||
/* sanity */ | /* sanity */ | ||||
r->pos = r->lim - 1; | r->pos = r->lim - 1; | ||||
r->pos[0] = 0; | r->pos[0] = 0; | ||||
FUN(el,push)(el, r->buf); | el_wpush(el, r->buf); | ||||
} | } | ||||
el->el_state.thiscmd = r->cmd; | el->el_state.thiscmd = r->cmd; | ||||
el->el_state.thisch = r->ch; | el->el_state.thisch = r->ch; | ||||
return (*el->el_map.func[r->cmd])(el, r->ch); | return (*el->el_map.func[r->cmd])(el, r->ch); | ||||
} | } |