12 /* read an input line; ex's input function */
13 static char *ex_read(char *msg
)
18 char *s
= led_prompt(msg
, "");
24 while ((c
= getchar()) != EOF
) {
36 /* print an output line; ex's output function */
37 static void ex_show(char *msg
)
47 /* read ex command location */
48 static char *ex_loc(char *s
, char *loc
)
50 while (*s
== ':' || isspace((unsigned char) *s
))
52 while (*s
&& !isalpha((unsigned char) *s
) && *s
!= '=') {
55 if (*s
== '/' || *s
== '?') {
58 while (*s
&& *s
!= d
) {
59 if (*s
== '\\' && s
[1])
70 /* read ex command name */
71 static char *ex_cmd(char *s
, char *cmd
)
75 while (isspace((unsigned char) *s
))
77 while (isalpha((unsigned char) *s
) || *s
== '=' || *s
== '!')
78 if ((*cmd
++ = *s
++) == 'k' && cmd
== cmd0
+ 1)
84 /* read ex command argument */
85 static char *ex_arg(char *s
, char *arg
)
88 while (isspace((unsigned char) *s
))
90 while (*s
&& !isspace((unsigned char) *s
))
96 static int ex_search(char *pat
)
99 int dir
= *pat
== '/' ? 1 : -1;
109 sbuf_chr(kw
, (unsigned char) *e
);
110 if (*e
== '\\' && e
[1])
113 re_kw
[0] = sbuf_buf(kw
);
114 re
= rset_make(1, re_kw
, 0);
118 while (i
>= 0 && i
< lbuf_len(xb
)) {
119 if (rset_find(re
, lbuf_get(xb
, i
), 0, NULL
, 0) >= 0)
127 static int ex_lineno(char *num
)
130 if (!num
[0] || num
[0] == '.')
135 n
= lbuf_len(xb
) - 1;
137 n
= xrow
- (num
[1] ? ex_lineno(num
+ 1) : 1);
139 n
= xrow
+ (num
[1] ? ex_lineno(num
+ 1) : 1);
141 n
= lbuf_markpos(xb
, num
[1]);
142 if (num
[0] == '/' && num
[1])
144 if (num
[0] == '?' && num
[1])
149 /* parse ex command location */
150 static int ex_region(char *loc
, int *beg
, int *end
)
153 if (!strcmp("%", loc
)) {
155 *end
= MAX(0, lbuf_len(xb
));
160 *end
= xrow
== lbuf_len(xb
) ? xrow
: xrow
+ 1;
165 *end
= ex_lineno(loc
) + 1;
166 *beg
= naddr
++ ? end0
- 1 : *end
- 1;
169 while (*loc
&& *loc
!= ';' && *loc
!= ',')
177 if (*beg
< 0 || *beg
>= lbuf_len(xb
))
179 if (*end
< *beg
|| *end
> lbuf_len(xb
))
184 static void ec_quit(char *ec
)
189 static void ec_edit(char *ec
)
194 fd
= open(arg
, O_RDONLY
);
195 lbuf_rm(xb
, 0, lbuf_len(xb
));
200 xrow
= MAX(0, lbuf_len(xb
) - 1);
202 snprintf(xpath
, PATHLEN
, "%s", arg
);
205 static void ec_read(char *ec
)
207 char arg
[EXLEN
], loc
[EXLEN
];
210 int n
= lbuf_len(xb
);
213 fd
= open(arg
[0] ? arg
: xpath
, O_RDONLY
);
214 if (fd
>= 0 && !ex_region(loc
, &beg
, &end
)) {
215 lbuf_rd(xb
, fd
, lbuf_len(xb
) ? end
: 0);
217 xrow
= end
+ lbuf_len(xb
) - n
;
221 static void ec_write(char *ec
)
223 char cmd
[EXLEN
], arg
[EXLEN
], loc
[EXLEN
];
230 path
= arg
[0] ? arg
: xpath
;
231 if (ex_region(loc
, &beg
, &end
))
237 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
239 lbuf_wr(xb
, fd
, beg
, end
);
242 if (!strcmp("wq", cmd
))
246 static void ec_insert(char *ec
)
248 char arg
[EXLEN
], cmd
[EXLEN
], loc
[EXLEN
];
256 if (ex_region(loc
, &beg
, &end
) && (beg
!= 0 || end
!= 0))
260 lbuf_rm(xb
, beg
, end
);
264 while ((s
= ex_read(""))) {
265 if (!strcmp(".", s
)) {
274 if (end
> lbuf_len(xb
))
277 lbuf_put(xb
, end
, sbuf_buf(sb
));
278 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
282 static void ec_print(char *ec
)
284 char cmd
[EXLEN
], loc
[EXLEN
];
289 if (!cmd
[0] && !loc
[0]) {
290 if (xrow
>= lbuf_len(xb
) - 1)
294 if (!ex_region(loc
, &beg
, &end
)) {
295 for (i
= beg
; i
< end
; i
++)
296 ex_show(lbuf_get(xb
, i
));
301 static void ex_yank(int reg
, int beg
, int end
)
303 char *buf
= lbuf_cp(xb
, beg
, end
);
304 reg_put(reg
, buf
, 1);
308 static void ec_delete(char *ec
)
315 if (!ex_region(loc
, &beg
, &end
) && lbuf_len(xb
)) {
316 ex_yank(arg
[0], beg
, end
);
317 lbuf_rm(xb
, beg
, end
);
322 static void ec_yank(char *ec
)
329 if (!ex_region(loc
, &beg
, &end
) && lbuf_len(xb
))
330 ex_yank(arg
[0], beg
, end
);
333 static void ec_put(char *ec
)
340 int n
= lbuf_len(xb
);
343 buf
= reg_get(arg
[0], &lnmode
);
344 if (buf
&& !ex_region(loc
, &beg
, &end
)) {
345 lbuf_put(xb
, end
, buf
);
346 xrow
= MIN(lbuf_len(xb
) - 1, end
+ lbuf_len(xb
) - n
- 1);
350 static void ec_lnum(char *ec
)
356 if (ex_region(loc
, &beg
, &end
))
358 sprintf(msg
, "%d\n", end
);
362 static void ec_undo(char *ec
)
367 static void ec_redo(char *ec
)
372 static void ec_mark(char *ec
)
374 char loc
[EXLEN
], arg
[EXLEN
];
378 if (ex_region(loc
, &beg
, &end
))
380 lbuf_mark(xb
, arg
[0], end
- 1);
383 static char *readuntil(char **src
, int delim
)
385 struct sbuf
*sbuf
= sbuf_make();
387 /* reading the pattern */
388 while (*s
&& *s
!= delim
) {
389 if (s
[0] == '\\' && s
[1])
390 sbuf_chr(sbuf
, (unsigned char) *s
++);
391 sbuf_chr(sbuf
, (unsigned char) *s
++);
393 if (*s
) /* skipping the delimiter */
396 return sbuf_done(sbuf
);
399 static void ec_substitute(char *ec
)
401 char loc
[EXLEN
], arg
[EXLEN
];
411 if (ex_region(loc
, &beg
, &end
))
413 delim
= (unsigned char) *s
++;
414 pat
= readuntil(&s
, delim
);
415 rep
= readuntil(&s
, delim
);
416 re
= rset_make(1, &pat
, 0);
417 for (i
= beg
; i
< end
; i
++) {
418 char *ln
= lbuf_get(xb
, i
);
419 if (rset_find(re
, ln
, LEN(offs
) / 2, offs
, 0)) {
420 struct sbuf
*r
= sbuf_make();
421 sbuf_mem(r
, ln
, offs
[0]);
423 sbuf_str(r
, ln
+ offs
[1]);
424 lbuf_put(xb
, i
, sbuf_buf(r
));
425 lbuf_rm(xb
, i
+ 1, i
+ 2);
434 static struct excmd
{
439 {"p", "print", ec_print
},
440 {"a", "append", ec_insert
},
441 {"i", "insert", ec_insert
},
442 {"d", "delete", ec_delete
},
443 {"c", "change", ec_insert
},
444 {"e", "edit", ec_edit
},
446 {"k", "mark", ec_mark
},
447 {"pu", "put", ec_put
},
448 {"q", "quit", ec_quit
},
449 {"r", "read", ec_read
},
450 {"w", "write", ec_write
},
451 {"wq", "wq", ec_write
},
452 {"u", "undo", ec_undo
},
453 {"r", "redo", ec_redo
},
454 {"s", "substitute", ec_substitute
},
455 {"ya", "yank", ec_yank
},
459 /* execute a single ex command */
460 void ex_command(char *ln
)
465 for (i
= 0; i
< LEN(excmds
); i
++) {
466 if (!strcmp(excmds
[i
].abbr
, cmd
) || !strcmp(excmds
[i
].name
, cmd
)) {
480 char *ln
= ex_read(":");