1 #include <stic.h>
2 
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include "../../src/engine/cmds.h"
7 #include "../../src/utils/macros.h"
8 
9 #include "suite.h"
10 
11 static int dummy_handler(const cmd_info_t* cmd_info);
12 static int goto_cmd(const cmd_info_t* cmd_info);
13 static int exec_cmd(const cmd_info_t* cmd_info);
14 static int call_cmd(const cmd_info_t* cmd_info);
15 static int delete_cmd(const cmd_info_t* cmd_info);
16 static int edia_cmd(const cmd_info_t* cmd_info);
17 static int edit_cmd(const cmd_info_t* cmd_info);
18 static int file_cmd(const cmd_info_t* cmd_info);
19 static int filter_cmd(const cmd_info_t* cmd_info);
20 static int history_cmd(const cmd_info_t* cmd_info);
21 static int invert_cmd(const cmd_info_t* cmd_info);
22 static int substitute_cmd(const cmd_info_t* cmd_info);
23 static int quit_cmd(const cmd_info_t* cmd_info);
24 
25 extern cmds_conf_t cmds_conf;
26 
27 static cmd_info_t cmdi;
28 static char *arg;
29 
30 static const cmd_add_t commands[] = {
31 	{ .name = "",                 .abbr = NULL,  .id = -1,      .descr = "descr",
32 	  .flags = HAS_RANGE,
33 	  .handler = &goto_cmd,       .min_args = 0, .max_args = 0, },
34 	{ .name = "!",                .abbr = NULL,  .id = -1,      .descr = "descr",
35 	  .flags = HAS_EMARK | HAS_QMARK_NO_ARGS | HAS_BG_FLAG,
36 	  .handler = &exec_cmd,       .min_args = 1, .max_args = 1, },
37 	{ .name = "call",             .abbr = "cal", .id = -1,      .descr = "descr",
38 	  .flags = HAS_QUOTED_ARGS | HAS_QMARK_WITH_ARGS | HAS_MACROS_FOR_CMD,
39 	  .handler = &call_cmd,       .min_args = 1, .max_args = 1, },
40 	{ .name = "delete",           .abbr = "d",   .id =  1,      .descr = "descr",
41 	  .flags = HAS_RANGE | HAS_QUOTED_ARGS | HAS_EMARK,
42 	  .handler = &delete_cmd,     .min_args = 0, .max_args = 1, },
43 	{ .name = "edia",             .abbr = NULL,  .id = -1,      .descr = "descr",
44 	  .flags = HAS_RANGE | HAS_RAW_ARGS,
45 	  .handler = &edia_cmd,       .min_args = 0, .max_args = NOT_DEF, },
46 	{ .name = "edit",             .abbr = "e",   .id = -1,      .descr = "descr",
47 	  .flags = HAS_RANGE,
48 	  .handler = &edit_cmd,       .min_args = 0, .max_args = NOT_DEF, },
49 	{ .name = "file",             .abbr = NULL,  .id = -1,      .descr = "descr",
50 	  .flags = HAS_RANGE | HAS_QMARK_NO_ARGS | HAS_BG_FLAG,
51 	  .handler = &file_cmd,       .min_args = 0, .max_args = 0, },
52 	{ .name = "filter",           .abbr = "fil", .id = -1,      .descr = "descr",
53 	  .flags = HAS_RANGE | HAS_EMARK | HAS_QMARK_NO_ARGS | HAS_REGEXP_ARGS,
54 	  .handler = &filter_cmd,     .min_args = 0, .max_args = NOT_DEF, },
55 	{ .name = "history",          .abbr = "his", .id = -1,      .descr = "descr",
56 	  .flags = 0,
57 	  .handler = &history_cmd,    .min_args = 0, .max_args = 0, },
58 	{ .name = "invert",           .abbr = NULL,  .id = -1,      .descr = "descr",
59 	  .flags = HAS_QMARK_NO_ARGS,
60 	  .handler = &invert_cmd,     .min_args = 0, .max_args = 0, },
61 	{ .name = "set",              .abbr = "se",  .id = -1,      .descr = "descr",
62 	  .flags = HAS_COMMENT,
63 	  .handler = &call_cmd,       .min_args = 0, .max_args = NOT_DEF, },
64 	{ .name = "substitute",       .abbr = "s",   .id = -1,      .descr = "descr",
65 	  .flags = HAS_CUST_SEP | HAS_EMARK,
66 	  .handler = &substitute_cmd, .min_args = 0, .max_args = 3, },
67 	{ .name = "put",              .abbr = "pu",  .id = -1,      .descr = "descr",
68 	  .flags = HAS_EMARK | HAS_BG_FLAG,
69 	  .handler = &dummy_handler,  .min_args = 0, .max_args = 1, },
70 	{ .name = "quit",             .abbr = "q",   .id = -1,      .descr = "descr",
71 	  .flags = HAS_EMARK,
72 	  .handler = &quit_cmd,       .min_args = 0, .max_args = 0, },
73 };
74 
SETUP()75 SETUP()
76 {
77 	vle_cmds_add(commands, ARRAY_LEN(commands));
78 }
79 
80 static int
dummy_handler(const cmd_info_t * cmd_info)81 dummy_handler(const cmd_info_t* cmd_info)
82 {
83 	return 0;
84 }
85 
86 static int
goto_cmd(const cmd_info_t * cmd_info)87 goto_cmd(const cmd_info_t* cmd_info)
88 {
89 	cmdi = *cmd_info;
90 	return 0;
91 }
92 
93 static int
exec_cmd(const cmd_info_t * cmd_info)94 exec_cmd(const cmd_info_t* cmd_info)
95 {
96 	cmdi = *cmd_info;
97 	if(cmdi.argc > 0)
98 	{
99 		free(arg);
100 		arg = strdup(cmdi.argv[0]);
101 	}
102 	return 0;
103 }
104 
105 static int
call_cmd(const cmd_info_t * cmd_info)106 call_cmd(const cmd_info_t* cmd_info)
107 {
108 	cmdi = *cmd_info;
109 	if(cmdi.argc > 0)
110 	{
111 		free(arg);
112 		arg = strdup(cmdi.args);
113 	}
114 	return 0;
115 }
116 
117 static int
delete_cmd(const cmd_info_t * cmd_info)118 delete_cmd(const cmd_info_t* cmd_info)
119 {
120 	cmdi = *cmd_info;
121 	if(cmdi.argc > 0)
122 	{
123 		free(arg);
124 		arg = strdup(cmdi.argv[0]);
125 	}
126 	return 0;
127 }
128 
129 static int
edia_cmd(const cmd_info_t * cmd_info)130 edia_cmd(const cmd_info_t* cmd_info)
131 {
132 	cmdi = *cmd_info;
133 	cmdi.usr1 = 1;
134 	if(cmdi.argc > 0)
135 	{
136 		free(arg);
137 		arg = strdup(cmdi.argv[0]);
138 	}
139 	return 0;
140 }
141 
142 static int
edit_cmd(const cmd_info_t * cmd_info)143 edit_cmd(const cmd_info_t* cmd_info)
144 {
145 	cmdi = *cmd_info;
146 	cmdi.usr1 = 2;
147 	if(cmdi.argc > 0)
148 	{
149 		free(arg);
150 		arg = strdup(cmdi.argv[0]);
151 	}
152 	return 0;
153 }
154 
155 static int
file_cmd(const cmd_info_t * cmd_info)156 file_cmd(const cmd_info_t* cmd_info)
157 {
158 	cmdi = *cmd_info;
159 	return 0;
160 }
161 
162 static int
filter_cmd(const cmd_info_t * cmd_info)163 filter_cmd(const cmd_info_t* cmd_info)
164 {
165 	cmdi = *cmd_info;
166 	if(cmdi.argc > 0)
167 	{
168 		free(arg);
169 		arg = strdup(cmdi.argv[0]);
170 	}
171 	return 0;
172 }
173 
174 static int
history_cmd(const cmd_info_t * cmd_info)175 history_cmd(const cmd_info_t* cmd_info)
176 {
177 	cmdi = *cmd_info;
178 	return 0;
179 }
180 
181 static int
invert_cmd(const cmd_info_t * cmd_info)182 invert_cmd(const cmd_info_t* cmd_info)
183 {
184 	cmdi = *cmd_info;
185 	return 0;
186 }
187 
188 static int
substitute_cmd(const cmd_info_t * cmd_info)189 substitute_cmd(const cmd_info_t* cmd_info)
190 {
191 	cmdi = *cmd_info;
192 	if(cmdi.argc > 0)
193 	{
194 		free(arg);
195 		arg = strdup(cmdi.argv[0]);
196 	}
197 	return 0;
198 }
199 
200 static int
quit_cmd(const cmd_info_t * cmd_info)201 quit_cmd(const cmd_info_t* cmd_info)
202 {
203 	cmdi = *cmd_info;
204 	return 0;
205 }
206 
TEST(leading_whitespace_trimming)207 TEST(leading_whitespace_trimming)
208 {
209 	assert_int_equal(0, vle_cmds_run("q"));
210 	assert_int_equal(0, vle_cmds_run(" q"));
211 	assert_int_equal(0, vle_cmds_run("   q"));
212 	assert_int_equal(0, vle_cmds_run("\tq"));
213 	assert_int_equal(0, vle_cmds_run("\t\tq"));
214 	assert_int_equal(0, vle_cmds_run("\t\t q"));
215 	assert_int_equal(0, vle_cmds_run(" \t \tq"));
216 	assert_int_equal(0, vle_cmds_run("\t \tq"));
217 }
218 
TEST(range_acceptance)219 TEST(range_acceptance)
220 {
221 	assert_int_equal(0, vle_cmds_run("%delete"));
222 	assert_int_equal(0, vle_cmds_run(",%delete"));
223 	assert_int_equal(0, vle_cmds_run(";%delete"));
224 	assert_int_equal(CMDS_ERR_NO_RANGE_ALLOWED, vle_cmds_run("%history"));
225 	assert_int_equal(CMDS_ERR_NO_RANGE_ALLOWED, vle_cmds_run("%,history"));
226 	assert_int_equal(CMDS_ERR_NO_RANGE_ALLOWED, vle_cmds_run("%;history"));
227 }
228 
TEST(single_quote_doubling)229 TEST(single_quote_doubling)
230 {
231 	assert_int_equal(0, vle_cmds_run("delete 'file''with''single''quotes'"));
232 	assert_string_equal("file'with'single'quotes", arg);
233 }
234 
TEST(range)235 TEST(range)
236 {
237 	cmds_conf.begin = 0;
238 	cmds_conf.current = 50;
239 	cmds_conf.end = 100;
240 
241 	assert_int_equal(0, vle_cmds_run("%delete!"));
242 	assert_int_equal(0, cmdi.begin);
243 	assert_int_equal(100, cmdi.end);
244 	assert_true(cmdi.emark);
245 
246 	assert_int_equal(0, vle_cmds_run("$delete!"));
247 	assert_int_equal(100, cmdi.begin);
248 	assert_int_equal(100, cmdi.end);
249 	assert_true(cmdi.emark);
250 
251 	assert_int_equal(0, vle_cmds_run(".,$delete!"));
252 	assert_int_equal(50, cmdi.begin);
253 	assert_int_equal(100, cmdi.end);
254 	assert_true(cmdi.emark);
255 
256 	assert_int_equal(0, vle_cmds_run(",$delete!"));
257 	assert_int_equal(50, cmdi.begin);
258 	assert_int_equal(100, cmdi.end);
259 	assert_true(cmdi.emark);
260 
261 	assert_int_equal(0, vle_cmds_run("$,.delete!"));
262 	assert_int_equal(50, cmdi.begin);
263 	assert_int_equal(100, cmdi.end);
264 	assert_true(cmdi.emark);
265 
266 	assert_int_equal(0, vle_cmds_run("$,delete!"));
267 	assert_int_equal(50, cmdi.begin);
268 	assert_int_equal(100, cmdi.end);
269 	assert_true(cmdi.emark);
270 
271 	assert_int_equal(0, vle_cmds_run(",delete!"));
272 	assert_int_equal(50, cmdi.begin);
273 	assert_int_equal(50, cmdi.end);
274 	assert_true(cmdi.emark);
275 
276 	assert_int_equal(0, vle_cmds_run("5,6,7delete!"));
277 	assert_int_equal(5, cmdi.begin);
278 	assert_int_equal(6, cmdi.end);
279 	assert_true(cmdi.emark);
280 
281 	assert_int_equal(0, vle_cmds_run("1,3,7"));
282 	assert_int_equal(2, cmdi.begin);
283 	assert_int_equal(6, cmdi.end);
284 
285 	assert_int_equal(0, vle_cmds_run("7,3,1"));
286 	assert_int_equal(2, cmdi.begin);
287 	assert_int_equal(0, cmdi.end);
288 }
289 
TEST(semicolon_range)290 TEST(semicolon_range)
291 {
292 	cmds_conf.begin = 0;
293 	cmds_conf.current = 50;
294 	cmds_conf.end = 100;
295 
296 	assert_int_equal(0, vle_cmds_run(".;$delete!"));
297 	assert_int_equal(50, cmdi.begin);
298 	assert_int_equal(100, cmdi.end);
299 	assert_true(cmdi.emark);
300 
301 	assert_int_equal(0, vle_cmds_run(";$delete!"));
302 	assert_int_equal(50, cmdi.begin);
303 	assert_int_equal(100, cmdi.end);
304 	assert_true(cmdi.emark);
305 
306 	assert_int_equal(0, vle_cmds_run("$;delete!"));
307 	assert_int_equal(50, cmdi.begin);
308 	assert_int_equal(100, cmdi.end);
309 	assert_true(cmdi.emark);
310 
311 	assert_int_equal(0, vle_cmds_run(";;delete!"));
312 	assert_int_equal(50, cmdi.begin);
313 	assert_int_equal(50, cmdi.end);
314 	assert_true(cmdi.emark);
315 
316 	assert_int_equal(0, vle_cmds_run("5;6;7delete!"));
317 	assert_int_equal(5, cmdi.begin);
318 	assert_int_equal(6, cmdi.end);
319 	assert_true(cmdi.emark);
320 }
321 
TEST(range_plus_minus)322 TEST(range_plus_minus)
323 {
324 	cmds_conf.begin = 0;
325 	cmds_conf.current = 50;
326 	cmds_conf.end = 100;
327 
328 	assert_int_equal(0, vle_cmds_run(".+"));
329 	assert_int_equal(51, cmdi.begin);
330 	assert_int_equal(51, cmdi.end);
331 
332 	assert_int_equal(0, vle_cmds_run("+2"));
333 	assert_int_equal(52, cmdi.begin);
334 	assert_int_equal(52, cmdi.end);
335 
336 	assert_int_equal(0, vle_cmds_run(".++"));
337 	assert_int_equal(52, cmdi.begin);
338 	assert_int_equal(52, cmdi.end);
339 
340 	assert_int_equal(0, vle_cmds_run(".+0-0"));
341 	assert_int_equal(50, cmdi.begin);
342 	assert_int_equal(50, cmdi.end);
343 
344 	assert_int_equal(0, vle_cmds_run(".+-"));
345 	assert_int_equal(50, cmdi.begin);
346 	assert_int_equal(50, cmdi.end);
347 
348 	assert_int_equal(0, vle_cmds_run(".+5-2"));
349 	assert_int_equal(53, cmdi.begin);
350 	assert_int_equal(53, cmdi.end);
351 
352 	assert_int_equal(0, vle_cmds_run(".,.+500"));
353 	assert_int_equal(50, cmdi.begin);
354 	assert_int_equal(100, cmdi.end);
355 
356 	assert_int_equal(0, vle_cmds_run(".,.-500"));
357 	assert_int_equal(50, cmdi.begin);
358 	assert_int_equal(0, cmdi.end);
359 }
360 
TEST(range_comma_vs_semicolon_bases)361 TEST(range_comma_vs_semicolon_bases)
362 {
363 	cmds_conf.begin = 0;
364 	cmds_conf.current = 0;
365 	cmds_conf.end = 3;
366 
367 	assert_int_equal(0, vle_cmds_run("2,+2"));
368 	assert_int_equal(1, cmdi.begin);
369 	assert_int_equal(2, cmdi.end);
370 
371 	assert_int_equal(0, vle_cmds_run("2;+2"));
372 	assert_int_equal(1, cmdi.begin);
373 	assert_int_equal(3, cmdi.end);
374 }
375 
TEST(range_and_spaces)376 TEST(range_and_spaces)
377 {
378 	cmds_conf.begin = 10;
379 	cmds_conf.current = 50;
380 	cmds_conf.end = 100;
381 
382 	assert_int_equal(0, vle_cmds_run("% delete!"));
383 	assert_int_equal(10, cmdi.begin);
384 	assert_int_equal(100, cmdi.end);
385 	assert_true(cmdi.emark);
386 
387 	assert_int_equal(0, vle_cmds_run("  ,  ,  ,   $  ,   .   delete!"));
388 	assert_int_equal(50, cmdi.begin);
389 	assert_int_equal(100, cmdi.end);
390 	assert_true(cmdi.emark);
391 }
392 
TEST(empty_range_empty_command_called)393 TEST(empty_range_empty_command_called)
394 {
395 	cmds_conf.begin = 10;
396 	cmds_conf.current = 50;
397 	cmds_conf.end = 100;
398 
399 	assert_int_equal(0, vle_cmds_run(""));
400 	assert_int_equal(NOT_DEF, cmdi.begin);
401 	assert_int_equal(NOT_DEF, cmdi.end);
402 
403 	assert_int_equal(0, vle_cmds_run(","));
404 	assert_int_equal(50, cmdi.begin);
405 	assert_int_equal(50, cmdi.end);
406 
407 	assert_int_equal(0, vle_cmds_run(";"));
408 	assert_int_equal(50, cmdi.begin);
409 	assert_int_equal(50, cmdi.end);
410 }
411 
TEST(bang_acceptance)412 TEST(bang_acceptance)
413 {
414 	assert_int_equal(0, vle_cmds_run("q"));
415 	assert_int_equal(CMDS_ERR_NO_BANG_ALLOWED, vle_cmds_run("history!"));
416 }
417 
TEST(bang)418 TEST(bang)
419 {
420 	assert_int_equal(0, vle_cmds_run("q"));
421 	assert_false(cmdi.emark);
422 
423 	assert_int_equal(0, vle_cmds_run("q!"));
424 	assert_true(cmdi.emark);
425 
426 	assert_int_equal(0, vle_cmds_run("!vim"));
427 	assert_false(cmdi.emark);
428 
429 	assert_int_equal(0, vle_cmds_run("!!vim"));
430 	assert_true(cmdi.emark);
431 
432 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("q !"));
433 }
434 
TEST(qmark_acceptance)435 TEST(qmark_acceptance)
436 {
437 	assert_int_equal(0, vle_cmds_run("invert?"));
438 	assert_int_equal(CMDS_ERR_NO_QMARK_ALLOWED, vle_cmds_run("history?"));
439 }
440 
TEST(qmark)441 TEST(qmark)
442 {
443 	assert_int_equal(0, vle_cmds_run("invert"));
444 	assert_false(cmdi.qmark);
445 
446 	assert_int_equal(0, vle_cmds_run("invert?"));
447 	assert_true(cmdi.qmark);
448 
449 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("invert ?"));
450 }
451 
TEST(args)452 TEST(args)
453 {
454 	assert_int_equal(CMDS_ERR_TOO_FEW_ARGS, vle_cmds_run("call"));
455 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("call a b"));
456 
457 	assert_int_equal(0, vle_cmds_run("call a"));
458 	assert_int_equal(1, cmdi.argc);
459 
460 	assert_int_equal(0, vle_cmds_run("delete"));
461 	assert_int_equal(0, cmdi.argc);
462 
463 	assert_int_equal(0, vle_cmds_run("edit a b c d"));
464 	assert_int_equal(4, cmdi.argc);
465 }
466 
TEST(count)467 TEST(count)
468 {
469 	assert_int_equal(0, vle_cmds_run("delete 10"));
470 	assert_int_equal(1, cmdi.argc);
471 	assert_string_equal("10", arg);
472 
473 	assert_int_equal(0, vle_cmds_run("delete10"));
474 	assert_int_equal(1, cmdi.argc);
475 	assert_string_equal("10", arg);
476 }
477 
TEST(end_characters)478 TEST(end_characters)
479 {
480 	assert_int_equal(0, vle_cmds_run("call a"));
481 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("call, a"));
482 }
483 
TEST(custom_separator)484 TEST(custom_separator)
485 {
486 	assert_int_equal(0, vle_cmds_run("s"));
487 	assert_int_equal(0, cmdi.argc);
488 	assert_int_equal(0, vle_cmds_run("s/some"));
489 	assert_int_equal(1, cmdi.argc);
490 	assert_int_equal(0, vle_cmds_run("s/some/thing"));
491 	assert_int_equal(2, cmdi.argc);
492 	assert_int_equal(0, vle_cmds_run("s/some/thing"));
493 	assert_int_equal(2, cmdi.argc);
494 	assert_int_equal(0, vle_cmds_run("s/some/thing/g"));
495 	assert_int_equal(3, cmdi.argc);
496 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("s/some/thing/g/j"));
497 }
498 
TEST(custom_separator_and_arg_format)499 TEST(custom_separator_and_arg_format)
500 {
501 	assert_int_equal(0, vle_cmds_run("s/\"so\"me\"/thing/g"));
502 	assert_int_equal(3, cmdi.argc);
503 	assert_string_equal("\"so\"me\"", arg);
504 
505 	assert_int_equal(0, vle_cmds_run("s/'some'/thing/g"));
506 	assert_int_equal(3, cmdi.argc);
507 	assert_string_equal("'some'", arg);
508 }
509 
TEST(custom_separator_and_emark)510 TEST(custom_separator_and_emark)
511 {
512 	assert_int_equal(0, vle_cmds_run("s!"));
513 	assert_int_equal(0, cmdi.argc);
514 	assert_true(cmdi.emark);
515 
516 	assert_int_equal(0, vle_cmds_run("s!/some"));
517 	assert_int_equal(1, cmdi.argc);
518 	assert_true(cmdi.emark);
519 
520 	assert_int_equal(0, vle_cmds_run("s!/some/thing"));
521 	assert_int_equal(2, cmdi.argc);
522 	assert_true(cmdi.emark);
523 
524 	assert_int_equal(0, vle_cmds_run("s!/some/thing/g"));
525 	assert_int_equal(3, cmdi.argc);
526 	assert_true(cmdi.emark);
527 
528 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("s!/some/thing/g/j"));
529 }
530 
TEST(incomplete_regexp_causes_error)531 TEST(incomplete_regexp_causes_error)
532 {
533 	assert_failure(vle_cmds_run("filter /te"));
534 }
535 
TEST(regexp_flag_strips_slashes)536 TEST(regexp_flag_strips_slashes)
537 {
538 	assert_int_equal(0, vle_cmds_run("e /te|xt/"));
539 	assert_int_equal(1, cmdi.argc);
540 	assert_string_equal("/te|xt/", arg);
541 
542 	assert_int_equal(0, vle_cmds_run("filter /te|xt/"));
543 	assert_int_equal(1, cmdi.argc);
544 	assert_string_equal("te|xt", arg);
545 }
546 
TEST(regexp_flag_slashes_and_spaces)547 TEST(regexp_flag_slashes_and_spaces)
548 {
549 	assert_int_equal(0, vle_cmds_run("filter /te|xt/i"));
550 	assert_int_equal(2, cmdi.argc);
551 	assert_string_equal("te|xt", arg);
552 
553 	assert_int_equal(0, vle_cmds_run("filter/te|xt/i"));
554 	assert_int_equal(2, cmdi.argc);
555 	assert_string_equal("te|xt", arg);
556 }
557 
TEST(regexp_flag_bang_slashes_and_spaces)558 TEST(regexp_flag_bang_slashes_and_spaces)
559 {
560 	assert_int_equal(0, vle_cmds_run("filter! /te|xt/i"));
561 	assert_int_equal(2, cmdi.argc);
562 	assert_string_equal("te|xt", arg);
563 
564 	assert_int_equal(0, vle_cmds_run("filter!/te|xt/i"));
565 	assert_int_equal(2, cmdi.argc);
566 	assert_string_equal("te|xt", arg);
567 }
568 
TEST(backgrounding)569 TEST(backgrounding)
570 {
571 	assert_int_equal(0, vle_cmds_run("e &"));
572 	assert_int_equal(1, cmdi.argc);
573 	assert_int_equal(0, cmdi.bg);
574 
575 	assert_int_equal(0, vle_cmds_run("!vim&"));
576 	assert_int_equal(1, cmdi.argc);
577 	assert_int_equal(0, cmdi.bg);
578 
579 	assert_int_equal(0, vle_cmds_run("!vim &"));
580 	assert_int_equal(1, cmdi.argc);
581 	assert_string_equal("vim", arg);
582 	assert_int_equal(1, cmdi.bg);
583 }
584 
TEST(no_args_after_qmark_1)585 TEST(no_args_after_qmark_1)
586 {
587 	assert_int_equal(0, vle_cmds_run("filter?"));
588 	assert_int_equal(0, vle_cmds_run("filter?      "));
589 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("filter? some_thing"));
590 }
591 
TEST(args_after_qmark_2)592 TEST(args_after_qmark_2)
593 {
594 	assert_int_equal(0, vle_cmds_run("call? arg"));
595 	assert_int_equal(0, vle_cmds_run("call? some_thing"));
596 }
597 
TEST(no_space_before_e_and_q_marks)598 TEST(no_space_before_e_and_q_marks)
599 {
600 	assert_int_equal(0, vle_cmds_run("filter?"));
601 	assert_int_equal(cmdi.argc, 0);
602 	assert_true(cmdi.qmark);
603 
604 	assert_int_equal(0, vle_cmds_run("filter ?"));
605 	assert_int_equal(cmdi.argc, 1);
606 	assert_false(cmdi.qmark);
607 }
608 
TEST(only_one_mark)609 TEST(only_one_mark)
610 {
611 	assert_int_equal(0, vle_cmds_run("filter?"));
612 	assert_int_equal(cmdi.argc, 0);
613 	assert_true(cmdi.qmark);
614 
615 	assert_int_equal(0, vle_cmds_run("filter!"));
616 	assert_int_equal(cmdi.argc, 0);
617 	assert_true(cmdi.emark);
618 
619 	assert_int_equal(0, vle_cmds_run("filter!!"));
620 	assert_int_equal(cmdi.argc, 1);
621 	assert_true(cmdi.emark);
622 
623 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("filter?!"));
624 	assert_int_equal(CMDS_ERR_TRAILING_CHARS, vle_cmds_run("filter??"));
625 
626 	assert_int_equal(0, vle_cmds_run("filter!?"));
627 	assert_int_equal(cmdi.argc, 1);
628 	assert_true(cmdi.emark);
629 	assert_false(cmdi.qmark);
630 }
631 
TEST(args_whitespace_trimming)632 TEST(args_whitespace_trimming)
633 {
634 	assert_int_equal(0, vle_cmds_run("call hi"));
635 	assert_int_equal(1, cmdi.argc);
636 	assert_string_equal("hi", arg);
637 
638 	assert_int_equal(0, vle_cmds_run("call\t'hi'"));
639 	assert_int_equal(1, cmdi.argc);
640 	assert_string_equal("'hi'", arg);
641 
642 	assert_int_equal(0, vle_cmds_run("call\t hi "));
643 	assert_int_equal(1, cmdi.argc);
644 	assert_string_equal("hi", arg);
645 
646 	assert_int_equal(0, vle_cmds_run("call hi \t"));
647 	assert_int_equal(1, cmdi.argc);
648 	assert_string_equal("hi", arg);
649 
650 	assert_int_equal(0, vle_cmds_run("call\t \thi\\  "));
651 	assert_int_equal(1, cmdi.argc);
652 	assert_string_equal("hi\\ ", arg);
653 }
654 
TEST(bg_and_no_args)655 TEST(bg_and_no_args)
656 {
657 	assert_int_equal(0, vle_cmds_run("file"));
658 	assert_false(cmdi.bg);
659 
660 	assert_int_equal(0, vle_cmds_run("file &"));
661 	assert_true(cmdi.bg);
662 }
663 
TEST(bg_followed_by_whitespace)664 TEST(bg_followed_by_whitespace)
665 {
666 	assert_int_equal(0, vle_cmds_run("file & "));
667 	assert_true(cmdi.bg);
668 
669 	assert_int_equal(0, vle_cmds_run("file &  "));
670 	assert_true(cmdi.bg);
671 
672 	assert_int_equal(0, vle_cmds_run("file& "));
673 	assert_true(cmdi.bg);
674 
675 	assert_int_equal(0, vle_cmds_run("file&  "));
676 	assert_true(cmdi.bg);
677 }
678 
TEST(short_forms)679 TEST(short_forms)
680 {
681 	assert_int_equal(0, vle_cmds_run("e"));
682 	assert_int_equal(2, cmdi.usr1);
683 
684 	assert_int_equal(0, vle_cmds_run("ed"));
685 	assert_int_equal(2, cmdi.usr1);
686 
687 	assert_int_equal(0, vle_cmds_run("edi"));
688 	assert_int_equal(2, cmdi.usr1);
689 
690 	assert_int_equal(0, vle_cmds_run("edit"));
691 	assert_int_equal(2, cmdi.usr1);
692 
693 	assert_int_equal(0, vle_cmds_run("edia"));
694 	assert_int_equal(1, cmdi.usr1);
695 }
696 
TEST(qmark_and_bg)697 TEST(qmark_and_bg)
698 {
699 	assert_int_equal(0, vle_cmds_run("file &"));
700 	assert_true(cmdi.bg);
701 
702 	assert_int_equal(0, vle_cmds_run("file?"));
703 	assert_true(cmdi.qmark);
704 
705 	assert_int_equal(0, vle_cmds_run("file? &"));
706 	assert_true(cmdi.bg);
707 	assert_true(cmdi.qmark);
708 }
709 
TEST(extra_long_command_name)710 TEST(extra_long_command_name)
711 {
712 	char cmd_name[1024];
713 
714 	memset(cmd_name, 'a', sizeof(cmd_name) - 1);
715 	cmd_name[sizeof(cmd_name) - 1] = '\0';
716 
717 	assert_false(vle_cmds_run(cmd_name) == 0);
718 }
719 
TEST(emark_is_checked_before_number_of_args)720 TEST(emark_is_checked_before_number_of_args)
721 {
722 	assert_int_equal(CMDS_ERR_NO_BANG_ALLOWED, vle_cmds_run("call!"));
723 }
724 
TEST(qmark_is_checked_before_number_of_args)725 TEST(qmark_is_checked_before_number_of_args)
726 {
727 	assert_int_equal(CMDS_ERR_NO_QMARK_ALLOWED, vle_cmds_run("quit? from here"));
728 }
729 
TEST(missing_quotes_are_allowed)730 TEST(missing_quotes_are_allowed)
731 {
732 	assert_int_equal(CMDS_ERR_INVALID_ARG, vle_cmds_run("call 'ismissing"));
733 }
734 
TEST(non_printable_arg)735 TEST(non_printable_arg)
736 {
737 	/* \x0C is Ctrl-L. */
738 	assert_int_equal(0, vle_cmds_run("call \x0C"));
739 	assert_string_equal("\x0C", arg);
740 }
741 
TEST(closing_double_quote_is_taken_as_comment)742 TEST(closing_double_quote_is_taken_as_comment)
743 {
744 	/* That's result of ambiguity of parsing, instead real :set doesn't have
745 	 * comments enabled for engine/cmds, but engine/set handles the comments. */
746 	assert_success(vle_cmds_run("set \"  string  \""));
747 	assert_string_equal("\"  string", arg);
748 }
749 
TEST(background_mark_is_removed_properly_in_presence_of_a_quote)750 TEST(background_mark_is_removed_properly_in_presence_of_a_quote)
751 {
752 	assert_success(vle_cmds_run("put \" &"));
753 }
754 
TEST(escaping_allows_use_of_spaces)755 TEST(escaping_allows_use_of_spaces)
756 {
757 	assert_success(vle_cmds_run("edit \\ something"));
758 	assert_int_equal(1, cmdi.argc);
759 	assert_string_equal(" something", arg);
760 }
761 
TEST(escaping_is_ignored_for_raw_arguments)762 TEST(escaping_is_ignored_for_raw_arguments)
763 {
764 	assert_success(vle_cmds_run("edia \\ something"));
765 	assert_int_equal(2, cmdi.argc);
766 	assert_string_equal("\\", arg);
767 }
768 
TEST(bad_mark)769 TEST(bad_mark)
770 {
771 	assert_int_equal(CMDS_ERR_INVALID_RANGE, vle_cmds_run("'1,'2file"));
772 }
773 
TEST(bad_range)774 TEST(bad_range)
775 {
776 	assert_int_equal(CMDS_ERR_INVALID_CMD, vle_cmds_run("#file"));
777 }
778 
TEST(inversed_range)779 TEST(inversed_range)
780 {
781 	swap_range = 0;
782 	assert_int_equal(CMDS_ERR_INVALID_RANGE, vle_cmds_run("20,10file"));
783 }
784 
785 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
786 /* vim: set cinoptions+=t0 filetype=c : */
787