12 char xpath
[PATHLEN
]; /* current file */
13 char xpath_alt
[PATHLEN
]; /* alternate file */
14 char xft
[32]; /* filetype */
15 int xquit
; /* exit if set */
16 int xvis
; /* visual mode */
17 int xai
= 1; /* autoindent option */
18 int xic
= 1; /* ignorecase option */
19 struct lbuf
*xb
; /* current buffer */
20 int xrow
, xoff
, xtop
; /* current row, column, and top row */
21 int xrow_alt
; /* alternate row, column, and top row */
22 int xled
= 1; /* use the line editor */
23 int xdir
= +1; /* current direction context */
24 int xshape
= 1; /* perform letter shaping */
25 int xorder
= 1; /* change the order of characters */
27 /* read ex command location */
28 static char *ex_loc(char *s
, char *loc
)
30 while (*s
== ':' || isspace((unsigned char) *s
))
32 while (*s
&& !isalpha((unsigned char) *s
) && *s
!= '=') {
35 if (*s
== '/' || *s
== '?') {
38 while (*s
&& *s
!= d
) {
39 if (*s
== '\\' && s
[1])
50 /* read ex command name */
51 static char *ex_cmd(char *s
, char *cmd
)
55 while (isspace((unsigned char) *s
))
57 while (isalpha((unsigned char) *s
) || *s
== '=' || *s
== '!')
58 if ((*cmd
++ = *s
++) == 'k' && cmd
== cmd0
+ 1)
64 /* read ex command argument */
65 static char *ex_arg(char *s
, char *arg
)
68 while (isspace((unsigned char) *s
))
70 while (*s
&& !isspace((unsigned char) *s
))
76 static int ex_search(char *pat
)
79 int dir
= *pat
== '/' ? 1 : -1;
89 sbuf_chr(kw
, (unsigned char) *e
);
90 if (*e
== '\\' && e
[1])
93 re_kw
[0] = sbuf_buf(kw
);
94 re
= rset_make(1, re_kw
, xic
? RE_ICASE
: 0);
98 while (i
>= 0 && i
< lbuf_len(xb
)) {
99 if (rset_find(re
, lbuf_get(xb
, i
), 0, NULL
, 0) >= 0)
107 static int ex_lineno(char *num
)
110 if (!num
[0] || num
[0] == '.')
115 n
= lbuf_len(xb
) - 1;
117 n
= xrow
- (num
[1] ? ex_lineno(num
+ 1) : 1);
119 n
= xrow
+ (num
[1] ? ex_lineno(num
+ 1) : 1);
121 lbuf_jump(xb
, num
[1], &n
, NULL
);
122 if (num
[0] == '/' && num
[1])
124 if (num
[0] == '?' && num
[1])
129 /* parse ex command location */
130 static int ex_region(char *loc
, int *beg
, int *end
)
133 if (!strcmp("%", loc
)) {
135 *end
= MAX(0, lbuf_len(xb
));
140 *end
= xrow
== lbuf_len(xb
) ? xrow
: xrow
+ 1;
145 *end
= ex_lineno(loc
) + 1;
146 *beg
= naddr
++ ? end0
- 1 : *end
- 1;
149 while (*loc
&& *loc
!= ';' && *loc
!= ',')
157 if (*beg
< 0 || *beg
>= lbuf_len(xb
))
159 if (*end
< *beg
|| *end
> lbuf_len(xb
))
164 static void ec_quit(char *ec
)
169 static void ec_edit(char *ec
)
175 if (!arg
[0] || !strcmp(arg
, "%") || !strcmp(xpath
, arg
)) {
177 } else if (!strcmp(arg
, "#")) {
178 char xpath_tmp
[PATHLEN
];
181 ex_show("\"#\" is unset\n");
184 strcpy(xpath_tmp
, xpath_alt
);
185 strcpy(xpath_alt
, xpath
);
186 strcpy(xpath
, xpath_tmp
);
192 strcpy(xpath_alt
, xpath
);
193 snprintf(xpath
, PATHLEN
, "%s", arg
);
195 xrow
= xvis
? 0 : 1 << 20;
197 strcpy(xft
, syn_filetype(xpath
));
198 fd
= open(xpath
, O_RDONLY
);
199 lbuf_rm(xb
, 0, lbuf_len(xb
));
203 snprintf(msg
, sizeof(msg
), "\"%s\" %d lines [r]\n",
204 xpath
, lbuf_len(xb
));
207 xrow
= MAX(0, MIN(xrow
, lbuf_len(xb
) - 1));
211 static void ec_read(char *ec
)
213 char arg
[EXLEN
], loc
[EXLEN
];
218 int n
= lbuf_len(xb
);
221 path
= arg
[0] ? arg
: xpath
;
222 fd
= open(path
, O_RDONLY
);
223 if (fd
>= 0 && !ex_region(loc
, &beg
, &end
)) {
224 lbuf_rd(xb
, fd
, lbuf_len(xb
) ? end
: 0);
226 xrow
= end
+ lbuf_len(xb
) - n
;
227 snprintf(msg
, sizeof(msg
), "\"%s\" %d lines [r]\n",
228 path
, lbuf_len(xb
) - n
);
233 static void ec_write(char *ec
)
235 char cmd
[EXLEN
], arg
[EXLEN
], loc
[EXLEN
];
243 path
= arg
[0] ? arg
: xpath
;
244 if (ex_region(loc
, &beg
, &end
))
250 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
252 lbuf_wr(xb
, fd
, beg
, end
);
254 snprintf(msg
, sizeof(msg
), "\"%s\" %d lines [w]\n",
257 if (!strcmp(xpath
, path
))
260 if (!strcmp("wq", cmd
))
264 static void ec_insert(char *ec
)
266 char arg
[EXLEN
], cmd
[EXLEN
], loc
[EXLEN
];
274 if (ex_region(loc
, &beg
, &end
) && (beg
!= 0 || end
!= 0))
278 lbuf_rm(xb
, beg
, end
);
282 while ((s
= ex_read(""))) {
283 if (!strcmp(".", s
)) {
292 if (end
> lbuf_len(xb
))
295 lbuf_put(xb
, end
, sbuf_buf(sb
));
296 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
300 static void ec_print(char *ec
)
302 char cmd
[EXLEN
], loc
[EXLEN
];
307 if (!cmd
[0] && !loc
[0]) {
308 if (xrow
>= lbuf_len(xb
) - 1)
312 if (!ex_region(loc
, &beg
, &end
)) {
313 for (i
= beg
; i
< end
; i
++)
314 ex_show(lbuf_get(xb
, i
));
319 static void ex_yank(int reg
, int beg
, int end
)
321 char *buf
= lbuf_cp(xb
, beg
, end
);
322 reg_put(reg
, buf
, 1);
326 static void ec_delete(char *ec
)
333 if (!ex_region(loc
, &beg
, &end
) && lbuf_len(xb
)) {
334 ex_yank(arg
[0], beg
, end
);
335 lbuf_rm(xb
, beg
, end
);
340 static void ec_yank(char *ec
)
347 if (!ex_region(loc
, &beg
, &end
) && lbuf_len(xb
))
348 ex_yank(arg
[0], beg
, end
);
351 static void ec_put(char *ec
)
358 int n
= lbuf_len(xb
);
361 buf
= reg_get(arg
[0], &lnmode
);
362 if (buf
&& !ex_region(loc
, &beg
, &end
)) {
363 lbuf_put(xb
, end
, buf
);
364 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
368 static void ec_lnum(char *ec
)
374 if (ex_region(loc
, &beg
, &end
))
376 sprintf(msg
, "%d\n", end
);
380 static void ec_undo(char *ec
)
385 static void ec_redo(char *ec
)
390 static void ec_mark(char *ec
)
392 char loc
[EXLEN
], arg
[EXLEN
];
396 if (ex_region(loc
, &beg
, &end
))
398 lbuf_mark(xb
, arg
[0], end
- 1, 0);
401 static char *readuntil(char **src
, int delim
)
403 struct sbuf
*sbuf
= sbuf_make();
405 /* reading the pattern */
406 while (*s
&& *s
!= delim
) {
407 if (s
[0] == '\\' && s
[1])
408 sbuf_chr(sbuf
, (unsigned char) *s
++);
409 sbuf_chr(sbuf
, (unsigned char) *s
++);
411 if (*s
) /* skipping the delimiter */
414 return sbuf_done(sbuf
);
417 static void ec_substitute(char *ec
)
419 char loc
[EXLEN
], arg
[EXLEN
];
429 if (ex_region(loc
, &beg
, &end
))
431 delim
= (unsigned char) *s
++;
432 pat
= readuntil(&s
, delim
);
433 rep
= readuntil(&s
, delim
);
434 re
= rset_make(1, &pat
, xic
? RE_ICASE
: 0);
435 for (i
= beg
; i
< end
; i
++) {
436 char *ln
= lbuf_get(xb
, i
);
437 if (rset_find(re
, ln
, LEN(offs
) / 2, offs
, 0)) {
438 struct sbuf
*r
= sbuf_make();
439 sbuf_mem(r
, ln
, offs
[0]);
441 sbuf_str(r
, ln
+ offs
[1]);
442 lbuf_put(xb
, i
, sbuf_buf(r
));
443 lbuf_rm(xb
, i
+ 1, i
+ 2);
452 static struct option
{
457 {"ai", "autoindent", &xai
},
458 {"ic", "ignorecase", &xic
},
459 {"td", "textdirection", &xdir
},
460 {"shape", "shape", &xshape
},
461 {"order", "xorder", &xorder
},
464 static char *cutword(char *s
, char *d
)
468 while (*s
&& !isspace(*s
))
476 static void ec_set(char *ec
)
487 if (tok
[0] == 'n' && tok
[1] == 'o') {
488 strcpy(opt
, tok
+ 2);
491 char *r
= strchr(tok
, '=');
501 for (i
= 0; i
< LEN(options
); i
++) {
502 struct option
*o
= &options
[i
];
503 if (!strcmp(o
->abbr
, opt
) || !strcmp(o
->name
, opt
))
509 static struct excmd
{
514 {"p", "print", ec_print
},
515 {"a", "append", ec_insert
},
516 {"i", "insert", ec_insert
},
517 {"d", "delete", ec_delete
},
518 {"c", "change", ec_insert
},
519 {"e", "edit", ec_edit
},
521 {"k", "mark", ec_mark
},
522 {"pu", "put", ec_put
},
523 {"q", "quit", ec_quit
},
524 {"r", "read", ec_read
},
525 {"w", "write", ec_write
},
526 {"wq", "wq", ec_write
},
527 {"u", "undo", ec_undo
},
528 {"r", "redo", ec_redo
},
529 {"se", "set", ec_set
},
530 {"s", "substitute", ec_substitute
},
531 {"ya", "yank", ec_yank
},
535 /* execute a single ex command */
536 void ex_command(char *ln
)
541 for (i
= 0; i
< LEN(excmds
); i
++) {
542 if (!strcmp(excmds
[i
].abbr
, cmd
) || !strcmp(excmds
[i
].name
, cmd
)) {
556 char *ln
= ex_read(":");