1
/* $NetBSD: vi.c,v 1.28 2009/02/06 13:14:37 sketch Exp $ */
4
* Copyright (c) 1992, 1993
5
* The Regents of the University of California. All rights reserved.
7
* This code is derived from software contributed to Berkeley by
8
* Christos Zoulas of Cornell University.
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of the University nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
#if !defined(lint) && !defined(SCCSID)
42
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
45
#endif /* not lint && not SCCSID */
48
* vi.c: Vi mode commands.
52
private el_action_t cv_action(EditLine *, int);
53
private el_action_t cv_paste(EditLine *, int);
59
cv_action(EditLine *el, int c)
62
if (el->el_chared.c_vcmd.action != NOP) {
63
/* 'cc', 'dd' and (possibly) friends */
64
if (c != el->el_chared.c_vcmd.action)
69
cv_yank(el, el->el_line.buffer,
70
el->el_line.lastchar - el->el_line.buffer);
71
el->el_chared.c_vcmd.action = NOP;
72
el->el_chared.c_vcmd.pos = 0;
74
el->el_line.lastchar = el->el_line.buffer;
75
el->el_line.cursor = el->el_line.buffer;
78
el->el_map.current = el->el_map.key;
82
el->el_chared.c_vcmd.pos = el->el_line.cursor;
83
el->el_chared.c_vcmd.action = c;
88
* Paste previous deletion before or after the cursor
91
cv_paste(EditLine *el, int c)
93
c_kill_t *k = &el->el_chared.c_kill;
94
int len = k->last - k->buf;
96
if (k->buf == NULL || len == 0)
99
(void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", len, k->buf);
104
if (!c && el->el_line.cursor < el->el_line.lastchar)
105
el->el_line.cursor++;
108
if (el->el_line.cursor + len > el->el_line.lastchar)
110
(void) memcpy(el->el_line.cursor, k->buf, len +0u);
117
* Vi paste previous deletion to the right of the cursor
120
protected el_action_t
122
vi_paste_next(EditLine *el, int c __attribute__((__unused__)))
125
return (cv_paste(el, 0));
130
* Vi paste previous deletion to the left of the cursor
133
protected el_action_t
135
vi_paste_prev(EditLine *el, int c __attribute__((__unused__)))
138
return (cv_paste(el, 1));
142
/* vi_prev_big_word():
143
* Vi move to the previous space delimited word
146
protected el_action_t
148
vi_prev_big_word(EditLine *el, int c)
151
if (el->el_line.cursor == el->el_line.buffer)
154
el->el_line.cursor = cv_prev_word(el->el_line.cursor,
156
el->el_state.argument,
159
if (el->el_chared.c_vcmd.action != NOP) {
168
* Vi move to the previous word
171
protected el_action_t
173
vi_prev_word(EditLine *el, int c __attribute__((__unused__)))
176
if (el->el_line.cursor == el->el_line.buffer)
179
el->el_line.cursor = cv_prev_word(el->el_line.cursor,
181
el->el_state.argument,
184
if (el->el_chared.c_vcmd.action != NOP) {
192
/* vi_next_big_word():
193
* Vi move to the next space delimited word
196
protected el_action_t
198
vi_next_big_word(EditLine *el, int c)
201
if (el->el_line.cursor >= el->el_line.lastchar - 1)
204
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
205
el->el_line.lastchar, el->el_state.argument, cv__isWord);
207
if (el->el_map.type == MAP_VI)
208
if (el->el_chared.c_vcmd.action != NOP) {
217
* Vi move to the next word
220
protected el_action_t
222
vi_next_word(EditLine *el, int c __attribute__((__unused__)))
225
if (el->el_line.cursor >= el->el_line.lastchar - 1)
228
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
229
el->el_line.lastchar, el->el_state.argument, cv__isword);
231
if (el->el_map.type == MAP_VI)
232
if (el->el_chared.c_vcmd.action != NOP) {
241
* Vi change case of character under the cursor and advance one character
244
protected el_action_t
245
vi_change_case(EditLine *el, int c)
249
if (el->el_line.cursor >= el->el_line.lastchar)
252
for (i = 0; i < el->el_state.argument; i++) {
254
c = *(unsigned char *)el->el_line.cursor;
256
*el->el_line.cursor = tolower(c);
258
*el->el_line.cursor = toupper(c);
260
if (++el->el_line.cursor >= el->el_line.lastchar) {
261
el->el_line.cursor--;
272
* Vi change prefix command
275
protected el_action_t
277
vi_change_meta(EditLine *el, int c __attribute__((__unused__)))
281
* Delete with insert == change: first we delete and then we leave in
284
return (cv_action(el, DELETE | INSERT));
288
/* vi_insert_at_bol():
289
* Vi enter insert mode at the beginning of line
292
protected el_action_t
294
vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__)))
297
el->el_line.cursor = el->el_line.buffer;
299
el->el_map.current = el->el_map.key;
304
/* vi_replace_char():
305
* Vi replace character under the cursor with the next character typed
308
protected el_action_t
310
vi_replace_char(EditLine *el, int c __attribute__((__unused__)))
313
if (el->el_line.cursor >= el->el_line.lastchar)
316
el->el_map.current = el->el_map.key;
317
el->el_state.inputmode = MODE_REPLACE_1;
323
/* vi_replace_mode():
324
* Vi enter replace mode
327
protected el_action_t
329
vi_replace_mode(EditLine *el, int c __attribute__((__unused__)))
332
el->el_map.current = el->el_map.key;
333
el->el_state.inputmode = MODE_REPLACE;
339
/* vi_substitute_char():
340
* Vi replace character under the cursor and enter insert mode
343
protected el_action_t
345
vi_substitute_char(EditLine *el, int c __attribute__((__unused__)))
348
c_delafter(el, el->el_state.argument);
349
el->el_map.current = el->el_map.key;
354
/* vi_substitute_line():
355
* Vi substitute entire line
358
protected el_action_t
360
vi_substitute_line(EditLine *el, int c __attribute__((__unused__)))
364
cv_yank(el, el->el_line.buffer,
365
el->el_line.lastchar - el->el_line.buffer);
366
(void) em_kill_line(el, 0);
367
el->el_map.current = el->el_map.key;
372
/* vi_change_to_eol():
373
* Vi change to end of line
376
protected el_action_t
378
vi_change_to_eol(EditLine *el, int c __attribute__((__unused__)))
382
cv_yank(el, el->el_line.cursor,
383
el->el_line.lastchar - el->el_line.cursor);
384
(void) ed_kill_line(el, 0);
385
el->el_map.current = el->el_map.key;
391
* Vi enter insert mode
394
protected el_action_t
396
vi_insert(EditLine *el, int c __attribute__((__unused__)))
399
el->el_map.current = el->el_map.key;
406
* Vi enter insert mode after the cursor
409
protected el_action_t
411
vi_add(EditLine *el, int c __attribute__((__unused__)))
415
el->el_map.current = el->el_map.key;
416
if (el->el_line.cursor < el->el_line.lastchar) {
417
el->el_line.cursor++;
418
if (el->el_line.cursor > el->el_line.lastchar)
419
el->el_line.cursor = el->el_line.lastchar;
431
* Vi enter insert mode at end of line
434
protected el_action_t
436
vi_add_at_eol(EditLine *el, int c __attribute__((__unused__)))
439
el->el_map.current = el->el_map.key;
440
el->el_line.cursor = el->el_line.lastchar;
447
* Vi delete prefix command
450
protected el_action_t
452
vi_delete_meta(EditLine *el, int c __attribute__((__unused__)))
455
return (cv_action(el, DELETE));
459
/* vi_end_big_word():
460
* Vi move to the end of the current space delimited word
463
protected el_action_t
465
vi_end_big_word(EditLine *el, int c)
468
if (el->el_line.cursor == el->el_line.lastchar)
471
el->el_line.cursor = cv__endword(el->el_line.cursor,
472
el->el_line.lastchar, el->el_state.argument, cv__isWord);
474
if (el->el_chared.c_vcmd.action != NOP) {
475
el->el_line.cursor++;
484
* Vi move to the end of the current word
487
protected el_action_t
489
vi_end_word(EditLine *el, int c __attribute__((__unused__)))
492
if (el->el_line.cursor == el->el_line.lastchar)
495
el->el_line.cursor = cv__endword(el->el_line.cursor,
496
el->el_line.lastchar, el->el_state.argument, cv__isword);
498
if (el->el_chared.c_vcmd.action != NOP) {
499
el->el_line.cursor++;
508
* Vi undo last change
511
protected el_action_t
513
vi_undo(EditLine *el, int c __attribute__((__unused__)))
515
c_undo_t un = el->el_chared.c_undo;
520
/* switch line buffer and undo buffer */
521
el->el_chared.c_undo.buf = el->el_line.buffer;
522
el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
523
el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer;
524
el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
525
el->el_line.buffer = un.buf;
526
el->el_line.cursor = un.buf + un.cursor;
527
el->el_line.lastchar = un.buf + un.len;
533
/* vi_command_mode():
534
* Vi enter command mode (use alternative key bindings)
537
protected el_action_t
539
vi_command_mode(EditLine *el, int c __attribute__((__unused__)))
542
/* [Esc] cancels pending action */
543
el->el_chared.c_vcmd.action = NOP;
544
el->el_chared.c_vcmd.pos = 0;
546
el->el_state.doingarg = 0;
548
el->el_state.inputmode = MODE_INSERT;
549
el->el_map.current = el->el_map.alt;
551
if (el->el_line.cursor > el->el_line.buffer)
552
el->el_line.cursor--;
559
* Vi move to the beginning of line
562
protected el_action_t
563
vi_zero(EditLine *el, int c)
566
if (el->el_state.doingarg)
567
return ed_argument_digit(el, c);
569
el->el_line.cursor = el->el_line.buffer;
570
if (el->el_chared.c_vcmd.action != NOP) {
578
/* vi_delete_prev_char():
579
* Vi move to previous character (backspace)
580
* [^H] in insert mode only
582
protected el_action_t
584
vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
587
if (el->el_line.cursor <= el->el_line.buffer)
591
el->el_line.cursor--;
597
* Vi list choices for completion or indicate end of file if empty line
600
protected el_action_t
602
vi_list_or_eof(EditLine *el, int c)
605
if (el->el_line.cursor == el->el_line.lastchar) {
606
if (el->el_line.cursor == el->el_line.buffer) {
607
term_writec(el, c); /* then do a EOF */
611
* Here we could list completions, but it is an
620
*el->el_line.lastchar = '\0'; /* just in case */
621
return (CC_LIST_CHOICES);
624
* Just complain for now.
633
/* vi_kill_line_prev():
634
* Vi cut from beginning of line to cursor
637
protected el_action_t
639
vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__)))
643
cp = el->el_line.buffer;
644
kp = el->el_chared.c_kill.buf;
645
while (cp < el->el_line.cursor)
646
*kp++ = *cp++; /* copy it */
647
el->el_chared.c_kill.last = kp;
648
c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
649
el->el_line.cursor = el->el_line.buffer; /* zap! */
655
* Vi search history previous
658
protected el_action_t
660
vi_search_prev(EditLine *el, int c __attribute__((__unused__)))
663
return (cv_search(el, ED_SEARCH_PREV_HISTORY));
668
* Vi search history next
671
protected el_action_t
673
vi_search_next(EditLine *el, int c __attribute__((__unused__)))
676
return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
680
/* vi_repeat_search_next():
681
* Vi repeat current search in the same search direction
684
protected el_action_t
686
vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__)))
689
if (el->el_search.patlen == 0)
692
return (cv_repeat_srch(el, el->el_search.patdir));
696
/* vi_repeat_search_prev():
697
* Vi repeat current search in the opposite search direction
701
protected el_action_t
702
vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__)))
705
if (el->el_search.patlen == 0)
708
return (cv_repeat_srch(el,
709
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
710
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
715
* Vi move to the character specified next
718
protected el_action_t
720
vi_next_char(EditLine *el, int c __attribute__((__unused__)))
722
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
727
* Vi move to the character specified previous
730
protected el_action_t
732
vi_prev_char(EditLine *el, int c __attribute__((__unused__)))
734
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
738
/* vi_to_next_char():
739
* Vi move up to the character specified next
742
protected el_action_t
744
vi_to_next_char(EditLine *el, int c __attribute__((__unused__)))
746
return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
750
/* vi_to_prev_char():
751
* Vi move up to the character specified previous
754
protected el_action_t
756
vi_to_prev_char(EditLine *el, int c __attribute__((__unused__)))
758
return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
762
/* vi_repeat_next_char():
763
* Vi repeat current character search in the same search direction
766
protected el_action_t
768
vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__)))
771
return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
772
el->el_state.argument, el->el_search.chatflg);
776
/* vi_repeat_prev_char():
777
* Vi repeat current character search in the opposite search direction
780
protected el_action_t
782
vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__)))
785
int dir = el->el_search.chadir;
787
r = cv_csearch(el, -dir, el->el_search.chacha,
788
el->el_state.argument, el->el_search.chatflg);
789
el->el_search.chadir = dir;
795
* Vi go to matching () {} or []
798
protected el_action_t
800
vi_match(EditLine *el, int c)
802
const char match_chars[] = "()[]{}";
807
*el->el_line.lastchar = '\0'; /* just in case */
809
i = strcspn(el->el_line.cursor, match_chars);
810
o_ch = el->el_line.cursor[i];
813
delta = strchr(match_chars, o_ch) - match_chars;
814
c_ch = match_chars[delta ^ 1];
816
delta = 1 - (delta & 1) * 2;
818
for (cp = &el->el_line.cursor[i]; count; ) {
820
if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
824
else if (*cp == c_ch)
828
el->el_line.cursor = cp;
830
if (el->el_chared.c_vcmd.action != NOP) {
831
/* NB posix says char under cursor should NOT be deleted
832
for -ve delta - this is different to netbsd vi. */
834
el->el_line.cursor++;
842
* Vi undo all changes to line
845
protected el_action_t
847
vi_undo_line(EditLine *el, int c)
855
* Vi go to specified column
857
* NB netbsd vi goes to screen column 'n', posix says nth character
859
protected el_action_t
861
vi_to_column(EditLine *el, int c)
864
el->el_line.cursor = el->el_line.buffer;
865
el->el_state.argument--;
866
return ed_next_char(el, 0);
870
* Vi yank to end of line
873
protected el_action_t
875
vi_yank_end(EditLine *el, int c)
878
cv_yank(el, el->el_line.cursor,
879
el->el_line.lastchar - el->el_line.cursor);
887
protected el_action_t
889
vi_yank(EditLine *el, int c)
892
return cv_action(el, YANK);
896
* Vi comment out current command
899
protected el_action_t
901
vi_comment_out(EditLine *el, int c)
904
el->el_line.cursor = el->el_line.buffer;
906
*el->el_line.cursor = '#';
908
return ed_newline(el, 0);
912
* Vi include shell alias
914
* NB: posix implies that we should enter insert mode, however
915
* this is against historical precedent...
917
#if defined(__weak_reference) && !defined(__FreeBSD__)
918
extern char *get_alias_text(const char *) __weak_reference(get_alias_text);
920
protected el_action_t
922
vi_alias(EditLine *el, int c)
924
#if defined(__weak_reference) && !defined(__FreeBSD__)
928
if (get_alias_text == 0) {
934
if (el_getc(el, &alias_name[1]) != 1)
937
alias_text = get_alias_text(alias_name);
938
if (alias_text != NULL)
939
el_push(el, alias_text);
946
/* vi_to_history_line():
947
* Vi go to specified history file line.
950
protected el_action_t
952
vi_to_history_line(EditLine *el, int c)
954
int sv_event_no = el->el_history.eventno;
958
if (el->el_history.eventno == 0) {
959
(void) strncpy(el->el_history.buf, el->el_line.buffer,
961
el->el_history.last = el->el_history.buf +
962
(el->el_line.lastchar - el->el_line.buffer);
965
/* Lack of a 'count' means oldest, not 1 */
966
if (!el->el_state.doingarg) {
967
el->el_history.eventno = 0x7fffffff;
970
/* This is brain dead, all the rest of this code counts
971
* upwards going into the past. Here we need count in the
972
* other direction (to match the output of fc -l).
973
* I could change the world, but this seems to suffice.
975
el->el_history.eventno = 1;
976
if (hist_get(el) == CC_ERROR)
978
el->el_history.eventno = 1 + el->el_history.ev.num
979
- el->el_state.argument;
980
if (el->el_history.eventno < 0) {
981
el->el_history.eventno = sv_event_no;
986
if (rval == CC_ERROR)
987
el->el_history.eventno = sv_event_no;
992
* Vi edit history line with vi
995
protected el_action_t
997
vi_histedit(EditLine *el, int c)
1002
char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
1005
if (el->el_state.doingarg) {
1006
if (vi_to_history_line(el, 0) == CC_ERROR)
1010
fd = mkstemp(tempfile);
1013
cp = el->el_line.buffer;
1014
write(fd, cp, el->el_line.lastchar - cp +0u);
1024
execlp("vi", "vi", tempfile, (char *)NULL);
1028
while (waitpid(pid, &st, 0) != pid)
1030
lseek(fd, 0ll, SEEK_SET);
1031
st = read(fd, cp, el->el_line.limit - cp +0u);
1032
if (st > 0 && cp[st - 1] == '\n')
1034
el->el_line.cursor = cp;
1035
el->el_line.lastchar = cp + st;
1041
/* return CC_REFRESH; */
1042
return ed_newline(el, 0);
1045
/* vi_history_word():
1046
* Vi append word from previous input line
1048
* Who knows where this one came from!
1049
* '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
1051
protected el_action_t
1053
vi_history_word(EditLine *el, int c)
1055
const char *wp = HIST_FIRST(el);
1056
const char *wep, *wsp;
1066
while (isspace((unsigned char)*wp))
1071
while (*wp && !isspace((unsigned char)*wp))
1074
} while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0);
1076
if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
1081
if (el->el_line.cursor < el->el_line.lastchar)
1082
el->el_line.cursor++;
1083
c_insert(el, len + 1);
1084
cp = el->el_line.cursor;
1085
lim = el->el_line.limit;
1088
while (wsp < wep && cp < lim)
1090
el->el_line.cursor = cp;
1092
el->el_map.current = el->el_map.key;
1097
* Vi redo last non-motion command
1100
protected el_action_t
1102
vi_redo(EditLine *el, int c)
1104
c_redo_t *r = &el->el_chared.c_redo;
1106
if (!el->el_state.doingarg && r->count) {
1107
el->el_state.doingarg = 1;
1108
el->el_state.argument = r->count;
1111
el->el_chared.c_vcmd.pos = el->el_line.cursor;
1112
el->el_chared.c_vcmd.action = r->action;
1113
if (r->pos != r->buf) {
1114
if (r->pos + 1 > r->lim)
1116
r->pos = r->lim - 1;
1118
el_push(el, r->buf);
1121
el->el_state.thiscmd = r->cmd;
1122
el->el_state.thisch = r->ch;
1123
return (*el->el_map.func[r->cmd])(el, r->ch);