10 #define REG(s) ((s)[0] != '\\' ? (unsigned char) (s)[0] : 0x80 | (unsigned char) (s)[1])
12 int xrow
, xoff
, xtop
; /* current row, column, and top row */
13 int xleft
; /* the first visible column */
14 int xquit
; /* exit if set */
15 int xvis
; /* visual mode */
16 int xai
= 1; /* autoindent option */
17 int xic
= 1; /* ignorecase option */
18 int xaw
; /* autowrite option */
19 int xwa
; /* writeany option */
20 int xhl
= 1; /* syntax highlight option */
21 int xhll
; /* highlight current line */
22 int xled
= 1; /* use the line editor */
23 int xtd
= +1; /* current text direction */
24 int xshape
= 1; /* perform letter shaping */
25 int xorder
= 1; /* change the order of characters */
26 int xkmap
= 0; /* the current keymap */
27 int xkmap_alt
= 1; /* the alternate keymap */
28 int xlim
= 256; /* do not process lines longer than this */
29 int xru
= 1; /* show line number */
30 int xhist
= 0; /* number of history lines */
31 static char xkwd
[EXLEN
]; /* the last searched keyword */
32 static char xrep
[EXLEN
]; /* the last replacement */
33 static int xkwddir
; /* the last search direction */
34 static int xgdep
; /* global command recursion depth */
35 static char **next
; /* argument list */
36 static int next_pos
; /* position in argument list */
39 char ft
[32]; /* file type */
40 char *path
; /* file path */
42 int row
, off
, top
, left
;
43 short id
; /* buffer number */
44 short td
; /* text direction */
45 long mtime
; /* modification time */
48 static int bufs_cnt
= 0; /* number of allocated buffers */
50 static void bufs_free(int idx
)
54 lbuf_free(bufs
[idx
].lb
);
55 memset(&bufs
[idx
], 0, sizeof(bufs
[idx
]));
59 static int bufs_find(char *path
)
62 path
= path
[0] == '/' && path
[1] == '\0' ? "" : path
;
63 for (i
= 0; i
< LEN(bufs
); i
++)
64 if (bufs
[i
].path
&& !strcmp(bufs
[i
].path
, path
))
69 static int bufs_findroom(void)
72 for (i
= 0; i
< LEN(bufs
) - 1; i
++)
78 static void bufs_init(int idx
, char *path
)
81 bufs
[idx
].id
= ++bufs_cnt
;
82 bufs
[idx
].path
= uc_dup(path
);
83 bufs
[idx
].lb
= lbuf_make();
90 strcpy(bufs
[idx
].ft
, syn_filetype(path
));
93 static int bufs_open(char *path
)
95 int idx
= bufs_findroom();
100 static void bufs_save(void)
105 bufs
[0].left
= xleft
;
109 static void bufs_load(void)
114 xleft
= bufs
[0].left
;
116 reg_put('%', bufs
[0].path
? bufs
[0].path
: "", 0);
119 static void bufs_shift(void)
122 memmove(&bufs
[0], &bufs
[1], sizeof(bufs
) - sizeof(bufs
[0]));
123 memset(&bufs
[LEN(bufs
) - 1], 0, sizeof(bufs
[0]));
127 static void bufs_switch(int idx
)
131 memcpy(&tmp
, &bufs
[idx
], sizeof(tmp
));
132 memmove(&bufs
[1], &bufs
[0], sizeof(tmp
) * idx
);
133 memcpy(&bufs
[0], &tmp
, sizeof(tmp
));
137 static void bufs_number(void)
141 for (i
= 0; i
< LEN(bufs
); i
++)
142 if (bufs
[i
].lb
!= NULL
)
145 for (i
= 0; i
< LEN(bufs
); i
++)
146 if (bufs
[i
].lb
!= NULL
)
150 static long mtime(char *path
)
153 if (!stat(path
, &st
))
163 struct lbuf
*ex_lbuf(void)
168 char *ex_filetype(void)
173 /* replace % and # with current and alternate path names; returns a static buffer */
174 static char *ex_pathexpand(char *src
, int spaceallowed
)
176 static char buf
[1024];
178 char *end
= dst
+ sizeof(buf
);
179 while (dst
+ 1 < end
&& *src
&& *src
!= '\n' &&
180 (spaceallowed
|| (*src
!= ' ' && *src
!= '\t'))) {
181 if (*src
== '%' || *src
== '#') {
182 int idx
= *src
== '#';
183 if (!bufs
[idx
].path
|| !bufs
[idx
].path
[0]) {
184 ex_show("pathname \"%\" or \"#\" is not set");
187 dst
+= snprintf(dst
, end
- dst
, "%s", bufs
[idx
].path
);
189 } else if (dst
== buf
&& *src
== '=') {
190 char *cur
= bufs
[0].path
;
191 char *dir
= cur
!= NULL
? strrchr(cur
, '/') : NULL
;
192 if (cur
!= NULL
&& dir
!= NULL
) {
193 int len
= MIN(dir
- cur
, end
- dst
- 2);
194 memcpy(dst
, cur
, len
);
200 if (*src
== '\\' && src
[1])
211 /* read :e +cmd arguments */
212 static char *ex_plus(char *src
, char *dst
)
219 while (*src
&& *src
!= ' ') {
220 if (src
[0] == '\\' && src
[1])
225 while (*src
== ' ' || *src
== '\t')
230 /* the previous search keyword */
231 int ex_kwd(char **kwd
, int *dir
)
240 /* set the previous search keyword */
241 void ex_kwdset(char *kwd
, int dir
)
244 snprintf(xkwd
, sizeof(xkwd
), "%s", kwd
);
248 static int ex_search(char **pat
)
254 char *kw
= re_read(pat
);
255 if (kw
!= NULL
&& *kw
)
256 ex_kwdset(kw
, delim
== '/' ? 1 : -1);
258 if (ex_kwd(&pat_re
, &dir
))
260 re
= rstr_make(pat_re
, xic
? RE_ICASE
: 0);
264 while (row
>= 0 && row
< lbuf_len(xb
)) {
265 if (rstr_find(re
, lbuf_get(xb
, row
), 0, NULL
, 0) >= 0)
270 return row
>= 0 && row
< lbuf_len(xb
) ? row
: -1;
273 static int ex_lineno(char **num
)
276 switch ((unsigned char) **num
) {
281 n
= lbuf_len(xb
) - 1;
285 if (lbuf_jump(xb
, (unsigned char) *++(*num
), &n
, NULL
))
294 if (isdigit((unsigned char) **num
)) {
296 while (isdigit((unsigned char) **num
))
300 while (**num
== '-' || **num
== '+') {
302 while (isdigit((unsigned char) **num
))
308 /* parse ex command addresses */
309 static int ex_region(char *loc
, int *beg
, int *end
)
312 if (!strcmp("%", loc
)) {
314 *end
= MAX(0, lbuf_len(xb
));
319 *end
= xrow
== lbuf_len(xb
) ? xrow
: xrow
+ 1;
324 *end
= ex_lineno(&loc
) + 1;
325 *beg
= naddr
++ ? end0
- 1 : *end
- 1;
328 while (*loc
&& *loc
!= ';' && *loc
!= ',')
336 if (*beg
< 0 && *end
== 0)
338 if (*beg
< 0 || *beg
>= lbuf_len(xb
))
340 if (*end
< *beg
|| *end
> lbuf_len(xb
))
345 static int ec_write(char *loc
, char *cmd
, char *arg
, char *txt
);
347 static int ex_modifiedbuffer(char *msg
)
349 if (!lbuf_modified(xb
))
351 if (xaw
&& ex_path()[0])
352 return ec_write("", "w", "", NULL
);
358 static int ec_buffer(char *loc
, char *cmd
, char *arg
, char *txt
)
360 char *aliases
= "%#^";
364 /* print buffer list */
365 for (i
= 0; i
< LEN(bufs
) && bufs
[i
].lb
; i
++) {
366 char c
= i
< strlen(aliases
) ? aliases
[i
] : ' ';
367 char m
= lbuf_modified(bufs
[i
].lb
) ? '*' : ' ';
368 snprintf(ln
, LEN(ln
), "%2i %c %s %c",
369 (int) bufs
[i
].id
, c
, bufs
[i
].path
, m
);
372 } else if (arg
[0] == '!') {
375 if (bufs
[0].lb
== NULL
)
377 } else if (arg
[0] == '~') {
378 /* reassign buffer ids */
381 int id
= arg
[0] ? atoi(arg
) : 0;
383 /* switch to the given buffer */
384 if (isdigit((unsigned char) arg
[0])) { /* buffer id given */
385 for (idx
= 0; idx
< LEN(bufs
); idx
++)
386 if (bufs
[idx
].lb
&& id
== bufs
[idx
].id
)
388 } else if (arg
[0] == '-') { /* previous buffer */
389 for (i
= 0; i
< LEN(bufs
); i
++)
390 if (bufs
[i
].lb
&& bufs
[i
].id
< bufs
[0].id
)
391 if (idx
< 0 || bufs
[i
].id
> bufs
[idx
].id
)
393 } else if (arg
[0] == '+') { /* next buffer */
394 for (i
= 0; i
< LEN(bufs
); i
++)
395 if (bufs
[i
].lb
&& bufs
[i
].id
> bufs
[0].id
)
396 if (idx
< 0 || bufs
[i
].id
< bufs
[idx
].id
)
398 } else { /* buffer alias given */
399 char *r
= strchr(aliases
, (unsigned char) arg
[0]);
400 idx
= r
? r
- aliases
: -1;
402 if (idx
>= 0 && idx
< LEN(bufs
) && bufs
[idx
].lb
) {
403 if (xb
&& !xwa
&& strchr(cmd
, '!') == NULL
)
404 if (ex_modifiedbuffer("buffer modified"))
408 ex_show("no such buffer");
415 static int ec_quit(char *loc
, char *cmd
, char *arg
, char *txt
)
417 if (!strchr(cmd
, '!'))
418 if (ex_modifiedbuffer("buffer modified"))
424 static int ec_edit(char *loc
, char *cmd
, char *arg
, char *txt
)
430 if (!strchr(cmd
, '!'))
431 if (xb
&& !xwa
&& ex_modifiedbuffer("buffer modified"))
433 arg
= ex_plus(arg
, pls
);
434 if (!(path
= ex_pathexpand(arg
, 0)))
436 /* ew: switch buffer without changing # */
437 if (path
[0] && cmd
[0] == 'e' && cmd
[1] == 'w' && bufs_find(path
) > 1)
439 /* check if the buffer is already available */
440 if (path
[0] && bufs_find(path
) >= 0) {
441 bufs_switch(bufs_find(path
));
443 return ex_command(pls
+ 1);
446 if (path
[0] || !bufs
[0].path
)
447 bufs_switch(bufs_open(path
));
448 fd
= open(ex_path(), O_RDONLY
);
450 int rd
= lbuf_rd(xb
, fd
, 0, lbuf_len(xb
));
452 snprintf(msg
, sizeof(msg
), "\"%s\" [=%d] [r]",
453 ex_path(), lbuf_len(xb
));
455 ex_show("read failed");
459 lbuf_saved(xb
, path
[0] != '\0');
460 bufs
[0].mtime
= mtime(ex_path());
461 xrow
= MAX(0, MIN(xrow
, lbuf_len(xb
) - 1));
463 xtop
= MAX(0, MIN(xtop
, lbuf_len(xb
) - 1));
465 return ex_command(pls
+ 1);
469 static int ex_next(char *cmd
, int dis
)
473 int idx
= next
!= NULL
&& next
[old
] != NULL
? next_pos
+ dis
: -1;
474 char *path
= idx
>= 0 && next
[idx
] != NULL
? next
[idx
] : NULL
;
476 char *r
= path
!= NULL
? path
: "";
477 if (dis
&& path
== NULL
) {
478 ex_show("no more files");
481 while (*r
&& s
+ 2 < arg
+ sizeof(arg
)) {
482 if (*r
== ' ' || *r
== '%' || *r
== '#' || *r
== '=')
487 if (ec_edit("", cmd
, arg
, NULL
))
493 static int ec_next(char *loc
, char *cmd
, char *arg
, char *txt
)
495 return ex_next(cmd
, +1);
498 static int ec_prev(char *loc
, char *cmd
, char *arg
, char *txt
)
500 return ex_next(cmd
, -1);
503 static int ec_read(char *loc
, char *cmd
, char *arg
, char *txt
)
509 int n
= lbuf_len(xb
);
510 path
= arg
[0] ? ex_pathexpand(arg
, 1) : ex_path();
511 if (ex_region(loc
, &beg
, &end
) || path
== NULL
)
513 pos
= lbuf_len(xb
) ? end
: 0;
514 if (path
[0] == '!') {
517 obuf
= cmd_pipe(path
+ 1, NULL
, 1);
519 lbuf_edit(xb
, obuf
, pos
, pos
);
522 int fd
= open(path
, O_RDONLY
);
524 ex_show("read failed");
527 if (lbuf_rd(xb
, fd
, pos
, pos
)) {
528 ex_show("read failed");
534 xrow
= end
+ lbuf_len(xb
) - n
- 1;
535 snprintf(msg
, sizeof(msg
), "\"%s\" [=%d] [r]",
536 path
, lbuf_len(xb
) - n
);
541 static int ec_write(char *loc
, char *cmd
, char *arg
, char *txt
)
547 path
= arg
[0] ? ex_pathexpand(arg
, 1) : ex_path();
548 if (cmd
[0] == 'x' && !lbuf_modified(xb
))
549 return ec_quit("", cmd
, "", NULL
);
550 if (ex_region(loc
, &beg
, &end
) || path
== NULL
)
556 if (path
[0] == '!') {
559 ibuf
= lbuf_cp(xb
, beg
, end
);
561 cmd_pipe(path
+ 1, ibuf
, 0);
565 if (!strchr(cmd
, '!') && bufs
[0].path
&&
566 !strcmp(bufs
[0].path
, path
) &&
567 mtime(bufs
[0].path
) > bufs
[0].mtime
) {
568 ex_show("write failed: file changed");
571 if (!strchr(cmd
, '!') && arg
[0] && mtime(arg
) >= 0) {
572 ex_show("write failed: file exists");
575 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, conf_mode());
577 ex_show("write failed: cannot create file");
580 if (lbuf_wr(xb
, fd
, beg
, end
)) {
581 ex_show("write failed");
587 snprintf(msg
, sizeof(msg
), "\"%s\" [=%d] [w]", path
, end
- beg
);
591 bufs
[0].path
= uc_dup(path
);
592 reg_put('%', path
, 0);
594 if (!strcmp(ex_path(), path
))
596 if (!strcmp(ex_path(), path
))
597 bufs
[0].mtime
= mtime(path
);
598 if (cmd
[0] == 'x' || (cmd
[0] == 'w' && cmd
[1] == 'q'))
599 ec_quit("", cmd
, "", NULL
);
603 static int ec_insert(char *loc
, char *cmd
, char *arg
, char *txt
)
607 if (ex_region(loc
, &beg
, &end
) && (beg
!= 0 || end
!= 0))
610 if (beg
+ 1 <= lbuf_len(xb
))
615 lbuf_edit(xb
, txt
, beg
, end
);
616 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
620 static int ec_print(char *loc
, char *cmd
, char *arg
, char *txt
)
624 if (!cmd
[0] && !loc
[0])
625 if (xrow
>= lbuf_len(xb
))
627 if (ex_region(loc
, &beg
, &end
))
629 for (i
= beg
; i
< end
; i
++)
630 ex_print(lbuf_get(xb
, i
));
631 xrow
= MAX(beg
, end
- 1);
636 static int ec_null(char *loc
, char *cmd
, char *arg
, char *txt
)
640 xrow
= xrow
+ 1 < lbuf_len(xb
) ? xrow
+ 1 : xrow
;
641 return ec_print(loc
, cmd
, arg
, txt
);
643 if (ex_region(loc
, &beg
, &end
))
645 xrow
= MAX(beg
, end
- 1);
650 static void ex_yank(int reg
, int beg
, int end
)
652 char *buf
= lbuf_cp(xb
, beg
, end
);
653 reg_put(reg
, buf
, 1);
657 static int ec_ye(char *loc
, char *cmd
, char *arg
, char *txt
)
659 reg_put(REG(arg
), txt
, 1);
663 static int ec_delete(char *loc
, char *cmd
, char *arg
, char *txt
)
666 if (ex_region(loc
, &beg
, &end
) || !lbuf_len(xb
))
668 ex_yank(REG(arg
), beg
, end
);
669 lbuf_edit(xb
, NULL
, beg
, end
);
674 static int ec_yank(char *loc
, char *cmd
, char *arg
, char *txt
)
677 if (ex_region(loc
, &beg
, &end
) || !lbuf_len(xb
))
679 ex_yank(REG(arg
), beg
, end
);
683 static int ec_put(char *loc
, char *cmd
, char *arg
, char *txt
)
688 int n
= lbuf_len(xb
);
689 buf
= reg_get(REG(arg
), &lnmode
);
690 if (!buf
|| ex_region(loc
, &beg
, &end
))
692 lbuf_edit(xb
, buf
, end
, end
);
693 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
697 static int ec_lnum(char *loc
, char *cmd
, char *arg
, char *txt
)
701 if (ex_region(loc
, &beg
, &end
))
703 sprintf(msg
, "%d\n", end
);
708 static int ec_undo(char *loc
, char *cmd
, char *arg
, char *txt
)
710 return lbuf_undo(xb
);
713 static int ec_redo(char *loc
, char *cmd
, char *arg
, char *txt
)
715 return lbuf_redo(xb
);
718 static int ec_mark(char *loc
, char *cmd
, char *arg
, char *txt
)
721 if (ex_region(loc
, &beg
, &end
))
723 lbuf_mark(xb
, (unsigned char) arg
[0], end
- 1, 0);
727 static void replace(struct sbuf
*dst
, char *rep
, char *ln
, int *offs
)
730 if (rep
[0] == '\\' && rep
[1]) {
731 if (rep
[1] >= '0' && rep
[1] <= '9') {
732 int grp
= (rep
[1] - '0') * 2;
733 int len
= offs
[grp
+ 1] - offs
[grp
];
734 sbuf_mem(dst
, ln
+ offs
[grp
], len
);
736 sbuf_chr(dst
, (unsigned char) rep
[1]);
740 sbuf_chr(dst
, (unsigned char) rep
[0]);
746 static int ec_substitute(char *loc
, char *cmd
, char *arg
, char *txt
)
751 char *pat
= NULL
, *rep
= NULL
;
754 if (ex_region(loc
, &beg
, &end
))
764 snprintf(xrep
, sizeof(xrep
), "%s", rep
? rep
: "");
767 if (ex_kwd(&pat
, NULL
))
769 re
= rstr_make(pat
, xic
? RE_ICASE
: 0);
772 for (i
= beg
; i
< end
; i
++) {
773 char *ln
= lbuf_get(xb
, i
);
774 struct sbuf
*r
= NULL
;
775 while (rstr_find(re
, ln
, LEN(offs
) / 2, offs
, 0) >= 0) {
778 sbuf_mem(r
, ln
, offs
[0]);
779 replace(r
, xrep
, ln
, offs
);
781 if (offs
[1] <= 0) /* zero-length match */
782 sbuf_chr(r
, (unsigned char) *ln
++);
783 if (!*ln
|| *ln
== '\n' || !strchr(s
, 'g'))
788 lbuf_edit(xb
, sbuf_buf(r
), i
, i
+ 1);
796 static int ec_exec(char *loc
, char *cmd
, char *arg
, char *txt
)
803 ex_modifiedbuffer(NULL
);
804 if (!(ecmd
= ex_pathexpand(arg
, 1)))
808 return cmd_exec(ecmd
);
810 if (ex_region(loc
, &beg
, &end
))
812 text
= lbuf_cp(xb
, beg
, end
);
813 rep
= cmd_pipe(ecmd
, text
, 1);
815 lbuf_edit(xb
, rep
, beg
, end
);
821 static int ec_make(char *loc
, char *cmd
, char *arg
, char *txt
)
826 ex_modifiedbuffer(NULL
);
827 if (!(target
= ex_pathexpand(arg
, 0)))
829 sprintf(make
, "make %s", target
);
836 static int ec_ft(char *loc
, char *cmd
, char *arg
, char *txt
)
839 snprintf(bufs
[0].ft
, sizeof(bufs
[0].ft
), "%s", arg
);
841 ex_print(ex_filetype());
845 static int ec_cmap(char *loc
, char *cmd
, char *arg
, char *txt
)
848 xkmap_alt
= conf_kmapfind(arg
);
850 ex_print(conf_kmap(xkmap
)[0]);
851 if (arg
[0] && !strchr(cmd
, '!'))
856 static int ex_exec(char *ln
);
858 static int ec_glob(char *loc
, char *cmd
, char *arg
, char *txt
)
866 if (!loc
[0] && !xgdep
)
868 if (ex_region(loc
, &beg
, &end
))
870 not = strchr(cmd
, '!') || cmd
[0] == 'v';
875 if (ex_kwd(&pat
, NULL
))
877 if (!(re
= rstr_make(pat
, xic
? RE_ICASE
: 0)))
880 for (i
= beg
+ 1; i
< end
; i
++)
881 lbuf_globset(xb
, i
, xgdep
);
883 while (i
< lbuf_len(xb
)) {
884 char *ln
= lbuf_get(xb
, i
);
885 if ((rstr_find(re
, ln
, LEN(offs
) / 2, offs
, 0) < 0) == not) {
891 while (i
< lbuf_len(xb
) && !lbuf_globget(xb
, i
, xgdep
))
894 for (i
= 0; i
< lbuf_len(xb
); i
++)
895 lbuf_globget(xb
, i
, xgdep
);
904 static int tag_row
[TAGCNT
];
905 static int tag_off
[TAGCNT
];
906 static int tag_pos
[TAGCNT
];
907 static char tag_path
[TAGCNT
][TAGLEN
];
908 static char tag_name
[TAGCNT
][TAGLEN
];
909 static int tag_cnt
= 0;
911 static void ex_tagput(char *name
)
913 if (tag_cnt
< TAGCNT
) {
914 tag_row
[tag_cnt
] = xrow
;
915 tag_off
[tag_cnt
] = xoff
;
916 snprintf(tag_path
[tag_cnt
], TAGLEN
, "%s", ex_path());
917 snprintf(tag_name
[tag_cnt
], TAGLEN
, "%s", name
);
922 /* go to definition (dir=+1 next, dir=-1 prev, dir=0 first) */
923 static int tag_goto(char *cw
, int dir
)
925 char path
[120], cmd
[120];
927 int pos
= dir
== 0 || tag_cnt
== 0 ? 0 : tag_pos
[tag_cnt
- 1];
928 if (tag_find(cw
, &pos
, dir
, path
, sizeof(path
), cmd
, sizeof(cmd
))) {
929 ex_show("not found");
934 tag_pos
[tag_cnt
- 1] = pos
;
935 if (strcmp(path
, ex_path()) != 0) {
936 if (access(path
, R_OK
) != 0) {
937 ex_show("cannot open");
940 if (ec_edit("", "e", path
, NULL
) != 0)
946 ln
= lbuf_get(xb
, xrow
);
947 if (ln
&& (s
= strstr(ln
, cw
)) != NULL
)
952 static int ec_tag(char *loc
, char *cmd
, char *arg
, char *txt
)
954 return tag_goto(arg
, 0);
957 static int ec_tfree(char *loc
, char *cmd
, char *arg
, char *txt
)
963 static int ec_pop(char *loc
, char *cmd
, char *arg
, char *txt
)
967 if (ex_path() == NULL
|| strcmp(tag_path
[tag_cnt
], ex_path()) != 0)
968 ec_edit("", "e", tag_path
[tag_cnt
], txt
);
969 xrow
= tag_row
[tag_cnt
];
970 xoff
= tag_off
[tag_cnt
];
973 ex_show("not found");
978 static int ec_tnext(char *loc
, char *cmd
, char *arg
, char *txt
)
981 return tag_goto(tag_name
[tag_cnt
- 1], +1);
985 static int ec_tprev(char *loc
, char *cmd
, char *arg
, char *txt
)
988 return tag_goto(tag_name
[tag_cnt
- 1], -1);
992 static int ec_at(char *loc
, char *cmd
, char *arg
, char *txt
)
996 char *buf
= reg_get(REG(arg
), &lnmode
);
997 if (!buf
|| ex_region(loc
, &beg
, &end
))
1000 return ex_command(buf
);
1003 static int ec_source(char *loc
, char *cmd
, char *arg
, char *txt
)
1005 char *path
= arg
[0] ? ex_pathexpand(arg
, 1) : ex_path();
1008 int fd
= path
[0] ? open(path
, O_RDONLY
) : -1;
1013 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
1014 sbuf_mem(sb
, buf
, nr
);
1015 ex_command(sbuf_buf(sb
));
1020 static struct option
{
1025 {"ai", "autoindent", &xai
},
1026 {"aw", "autowrite", &xaw
},
1027 {"wa", "writeany", &xwa
},
1028 {"ic", "ignorecase", &xic
},
1029 {"td", "textdirection", &xtd
},
1030 {"shape", "shape", &xshape
},
1031 {"order", "xorder", &xorder
},
1032 {"hl", "highlight", &xhl
},
1033 {"hll", "highlightline", &xhll
},
1034 {"lim", "linelimit", &xlim
},
1035 {"ru", "ruler", &xru
},
1036 {"hist", "history", &xhist
},
1039 static char *cutword(char *s
, char *d
)
1043 while (*s
&& !isspace(*s
))
1051 static int ec_set(char *loc
, char *cmd
, char *arg
, char *txt
)
1059 s
= cutword(s
, tok
);
1060 if (tok
[0] == 'n' && tok
[1] == 'o') {
1061 strcpy(opt
, tok
+ 2);
1064 char *r
= strchr(tok
, '=');
1074 for (i
= 0; i
< LEN(options
); i
++) {
1075 struct option
*o
= &options
[i
];
1076 if (!strcmp(o
->abbr
, opt
) || !strcmp(o
->name
, opt
)) {
1081 ex_show("unknown option");
1087 static struct excmd
{
1090 int (*ec
)(char *loc
, char *cmd
, char *arg
, char *txt
);
1092 {"b", "buffer", ec_buffer
},
1093 {"p", "print", ec_print
},
1094 {"a", "append", ec_insert
},
1095 {"i", "insert", ec_insert
},
1096 {"d", "delete", ec_delete
},
1097 {"c", "change", ec_insert
},
1098 {"e", "edit", ec_edit
},
1099 {"e!", "edit!", ec_edit
},
1100 {"ew", "ew", ec_edit
},
1101 {"ew!", "ew!", ec_edit
},
1102 {"g", "global", ec_glob
},
1103 {"g!", "global!", ec_glob
},
1104 {"=", "=", ec_lnum
},
1105 {"k", "mark", ec_mark
},
1106 {"po", "pop", ec_pop
},
1107 {"pu", "put", ec_put
},
1108 {"n", "next", ec_next
},
1109 {"prev", "prev", ec_prev
},
1110 {"q", "quit", ec_quit
},
1111 {"q!", "quit!", ec_quit
},
1112 {"r", "read", ec_read
},
1113 {"ta", "tag", ec_tag
},
1114 {"tn", "tnext", ec_tnext
},
1115 {"tp", "tprev", ec_tprev
},
1116 {"tf", "tfree", ec_tfree
},
1117 {"v", "vglobal", ec_glob
},
1118 {"w", "write", ec_write
},
1119 {"w!", "write!", ec_write
},
1120 {"wq", "wq", ec_write
},
1121 {"wq!", "wq!", ec_write
},
1122 {"u", "undo", ec_undo
},
1123 {"redo", "redo", ec_redo
},
1124 {"se", "set", ec_set
},
1125 {"s", "substitute", ec_substitute
},
1126 {"x", "xit", ec_write
},
1127 {"x!", "xit!", ec_write
},
1128 {"y", "yank", ec_yank
},
1129 {"ye", "yankex", ec_ye
},
1130 {"so", "source", ec_source
},
1131 {"!", "!", ec_exec
},
1132 {"make", "make", ec_make
},
1133 {"ft", "filetype", ec_ft
},
1134 {"cm", "cmap", ec_cmap
},
1135 {"cm!", "cmap!", ec_cmap
},
1140 static int ex_idx(char *cmd
)
1143 for (i
= 0; i
< LEN(excmds
); i
++)
1144 if (!strcmp(excmds
[i
].abbr
, cmd
) || !strcmp(excmds
[i
].name
, cmd
))
1149 /* read ex command addresses */
1150 static char *ex_loc(char *src
, char *loc
)
1152 while (*src
== ':' || *src
== ' ' || *src
== '\t')
1154 while (*src
&& strchr(".$0123456789'/?+-,;%", (unsigned char) *src
) != NULL
) {
1157 if (*src
== '/' || *src
== '?') {
1160 while (*src
&& *src
!= d
) {
1161 if (*src
== '\\' && src
[1])
1173 /* read ex command name */
1174 static char *ex_cmd(char *src
, char *cmd
)
1177 while (*src
== ' ' || *src
== '\t')
1179 while (isalpha((unsigned char) *src
) && cmd
< cmd0
+ 16)
1180 if ((*cmd
++ = *src
++) == 'k' && cmd
== cmd0
+ 1)
1182 if (*src
== '!' || *src
== '=' || *src
== '@')
1188 /* read ex command argument for excmd command */
1189 static char *ex_arg(char *src
, char *dst
, char *excmd
)
1192 int c1
= c0
? excmd
[1] : 0;
1193 while (*src
== ' ' || *src
== '\t')
1195 if (c0
== '!' || c0
== 'g' || c0
== 'v' ||
1196 ((c0
== 'r' || c0
== 'w') && src
[0] == '!')) {
1197 while (*src
&& *src
!= '\n') {
1198 if (*src
== '\\' && src
[1])
1202 } else if ((c0
== 's' && c1
!= 'e') || c0
== '&' || c0
== '~') {
1206 while (*src
&& *src
!= '\n' && cnt
> 0) {
1209 if (*src
== '\\' && src
[1])
1214 while (*src
&& *src
!= '\n' && *src
!= '|' && *src
!= '"') {
1215 if (*src
== '\\' && src
[1])
1220 while (*src
&& *src
!= '\n')
1223 if (*src
== '\n' || *src
== '|')
1229 /* read ex text input for excmd command */
1230 static char *ex_txt(char *src
, char **dst
, char *excmd
)
1233 int c1
= c0
? excmd
[1] : 0;
1235 if (c0
== 'y' && c1
== 'e' && src
[0]) {
1238 while (src
[0] && (src
[0] != '\n' || src
[1] != '.' || src
[2] != '\n'))
1240 res
= malloc((src
- beg
) + 1 + 1);
1241 memcpy(res
, beg
, src
- beg
);
1242 res
[src
- beg
] = '\n';
1243 res
[src
- beg
+ 1] = '\0';
1245 return src
[0] ? src
+ 3 : src
;
1247 if ((c0
== 'y' && c1
== 'e') || (c1
== 0 && (c0
== 'i' || c0
== 'a' || c0
== 'c'))) {
1248 struct sbuf
*sb
= sbuf_make();
1250 while ((s
= ex_read(""))) {
1251 if (!strcmp(".", s
)) {
1259 *dst
= sbuf_done(sb
);
1265 /* execute a single ex command */
1266 static int ex_exec(char *ln
)
1268 char loc
[EXLEN
], cmd
[EXLEN
], arg
[EXLEN
];
1270 if (strlen(ln
) >= EXLEN
) {
1271 ex_show("command too long");
1277 ln
= ex_loc(ln
, loc
);
1278 ln
= ex_cmd(ln
, cmd
);
1280 ln
= ex_arg(ln
, arg
, idx
>= 0 ? excmds
[idx
].abbr
: "unknown");
1281 ln
= ex_txt(ln
, &txt
, idx
>= 0 ? excmds
[idx
].abbr
: "unknown");
1283 ret
= excmds
[idx
].ec(loc
, cmd
, arg
, txt
);
1285 ex_show("unknown command");
1291 /* execute a single ex command */
1292 int ex_command(char *ln
)
1294 int ret
= ex_exec(ln
);
1303 char *ln
= ex_read(":");
1306 reg_put(':', ln
, 1);
1312 int ex_init(char **files
)
1315 if (ex_next("e", 0))
1317 if (getenv("EXINIT"))
1318 ex_command(getenv("EXINIT"));
1325 for (i
= 0; i
< LEN(bufs
); i
++)