1*c3d00a7dSabhinav /* $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $ */
292a9b5c3Sabhinav
392a9b5c3Sabhinav /*-
492a9b5c3Sabhinav * Copyright (c) 2017 Abhinav Upadhyay <abhinav@NetBSD.org>
592a9b5c3Sabhinav * All rights reserved.
692a9b5c3Sabhinav *
792a9b5c3Sabhinav * Redistribution and use in source and binary forms, with or without
892a9b5c3Sabhinav * modification, are permitted provided that the following conditions
992a9b5c3Sabhinav * are met:
1092a9b5c3Sabhinav *
1192a9b5c3Sabhinav * 1. Redistributions of source code must retain the above copyright
1292a9b5c3Sabhinav * notice, this list of conditions and the following disclaimer.
1392a9b5c3Sabhinav * 2. Redistributions in binary form must reproduce the above copyright
1492a9b5c3Sabhinav * notice, this list of conditions and the following disclaimer in
1592a9b5c3Sabhinav * the documentation and/or other materials provided with the
1692a9b5c3Sabhinav * distribution.
1792a9b5c3Sabhinav *
1892a9b5c3Sabhinav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1992a9b5c3Sabhinav * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2092a9b5c3Sabhinav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2192a9b5c3Sabhinav * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2292a9b5c3Sabhinav * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2392a9b5c3Sabhinav * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2492a9b5c3Sabhinav * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2592a9b5c3Sabhinav * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2692a9b5c3Sabhinav * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2792a9b5c3Sabhinav * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2892a9b5c3Sabhinav * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2992a9b5c3Sabhinav * SUCH DAMAGE.
3092a9b5c3Sabhinav */
3192a9b5c3Sabhinav
32fa615556Sabhinav #include "config.h"
33fa615556Sabhinav
34fa615556Sabhinav #include <assert.h>
35fa615556Sabhinav #include <err.h>
36fa615556Sabhinav #include <stdio.h>
37fa615556Sabhinav #include <histedit.h>
38fa615556Sabhinav #include <stdlib.h>
39fa615556Sabhinav #include <string.h>
40fa615556Sabhinav #include <wchar.h>
41fa615556Sabhinav
42fa615556Sabhinav #include "filecomplete.h"
43fa615556Sabhinav #include "el.h"
44fa615556Sabhinav
45fa615556Sabhinav typedef struct {
46fa615556Sabhinav const wchar_t *user_typed_text; /* The actual text typed by the user on the terminal */
47fa615556Sabhinav const char *completion_function_input ; /*the text received by fn_filename_completion_function */
48c93cba3aSabhinav const char *expanded_text[2]; /* the value to which completion_function_input should be expanded */
49fa615556Sabhinav const wchar_t *escaped_output; /* expected escaped value of expanded_text */
50fa615556Sabhinav } test_input;
51fa615556Sabhinav
52fa615556Sabhinav static test_input inputs[] = {
53fa615556Sabhinav {
54fa615556Sabhinav /* simple test for escaping angular brackets */
55fa615556Sabhinav L"ls ang",
56fa615556Sabhinav "ang",
57c93cba3aSabhinav {"ang<ular>test", NULL},
58fa615556Sabhinav L"ls ang\\<ular\\>test "
59fa615556Sabhinav },
60fa615556Sabhinav {
61fa615556Sabhinav /* test angular bracket inside double quotes: ls "dq_ang */
62fa615556Sabhinav L"ls \"dq_ang",
63fa615556Sabhinav "dq_ang",
64c93cba3aSabhinav {"dq_ang<ular>test", NULL},
65fa615556Sabhinav L"ls \"dq_ang<ular>test\""
66fa615556Sabhinav },
67fa615556Sabhinav {
68fa615556Sabhinav /* test angular bracket inside singlq quotes: ls "sq_ang */
69fa615556Sabhinav L"ls 'sq_ang",
70fa615556Sabhinav "sq_ang",
71c93cba3aSabhinav {"sq_ang<ular>test", NULL},
72fa615556Sabhinav L"ls 'sq_ang<ular>test'"
73fa615556Sabhinav },
74fa615556Sabhinav {
75fa615556Sabhinav /* simple test for backslash */
76fa615556Sabhinav L"ls back",
77fa615556Sabhinav "back",
78c93cba3aSabhinav {"backslash\\test", NULL},
79fa615556Sabhinav L"ls backslash\\\\test "
80fa615556Sabhinav },
81fa615556Sabhinav {
82fa615556Sabhinav /* backslash inside single quotes */
83fa615556Sabhinav L"ls 'sback",
84fa615556Sabhinav "sback",
85c93cba3aSabhinav {"sbackslash\\test", NULL},
86fa615556Sabhinav L"ls 'sbackslash\\test'"
87fa615556Sabhinav },
88fa615556Sabhinav {
89fa615556Sabhinav /* backslash inside double quotes */
90fa615556Sabhinav L"ls \"dback",
91fa615556Sabhinav "dback",
92c93cba3aSabhinav {"dbackslash\\test", NULL},
93fa615556Sabhinav L"ls \"dbackslash\\\\test\""
94fa615556Sabhinav },
95fa615556Sabhinav {
96fa615556Sabhinav /* test braces */
97fa615556Sabhinav L"ls br",
98fa615556Sabhinav "br",
99c93cba3aSabhinav {"braces{test}", NULL},
100fa615556Sabhinav L"ls braces\\{test\\} "
101fa615556Sabhinav },
102fa615556Sabhinav {
103fa615556Sabhinav /* test braces inside single quotes */
104fa615556Sabhinav L"ls 'sbr",
105fa615556Sabhinav "sbr",
106c93cba3aSabhinav {"sbraces{test}", NULL},
107fa615556Sabhinav L"ls 'sbraces{test}'"
108fa615556Sabhinav },
109fa615556Sabhinav {
110fa615556Sabhinav /* test braces inside double quotes */
111fa615556Sabhinav L"ls \"dbr",
112fa615556Sabhinav "dbr",
113c93cba3aSabhinav {"dbraces{test}", NULL},
114fa615556Sabhinav L"ls \"dbraces{test}\""
115fa615556Sabhinav },
116fa615556Sabhinav {
117fa615556Sabhinav /* test dollar */
118fa615556Sabhinav L"ls doll",
119fa615556Sabhinav "doll",
120c93cba3aSabhinav {"doll$artest", NULL},
121fa615556Sabhinav L"ls doll\\$artest "
122fa615556Sabhinav },
123fa615556Sabhinav {
124fa615556Sabhinav /* test dollar inside single quotes */
125fa615556Sabhinav L"ls 'sdoll",
126fa615556Sabhinav "sdoll",
127c93cba3aSabhinav {"sdoll$artest", NULL},
128fa615556Sabhinav L"ls 'sdoll$artest'"
129fa615556Sabhinav },
130fa615556Sabhinav {
131fa615556Sabhinav /* test dollar inside double quotes */
132fa615556Sabhinav L"ls \"ddoll",
133fa615556Sabhinav "ddoll",
134c93cba3aSabhinav {"ddoll$artest", NULL},
135fa615556Sabhinav L"ls \"ddoll\\$artest\""
136fa615556Sabhinav },
137fa615556Sabhinav {
138fa615556Sabhinav /* test equals */
139fa615556Sabhinav L"ls eq",
140fa615556Sabhinav "eq",
141c93cba3aSabhinav {"equals==test", NULL},
142fa615556Sabhinav L"ls equals\\=\\=test "
143fa615556Sabhinav },
144fa615556Sabhinav {
145fa615556Sabhinav /* test equals inside sinqle quotes */
146fa615556Sabhinav L"ls 'seq",
147fa615556Sabhinav "seq",
148c93cba3aSabhinav {"sequals==test", NULL},
149fa615556Sabhinav L"ls 'sequals==test'"
150fa615556Sabhinav },
151fa615556Sabhinav {
152fa615556Sabhinav /* test equals inside double quotes */
153fa615556Sabhinav L"ls \"deq",
154fa615556Sabhinav "deq",
155c93cba3aSabhinav {"dequals==test", NULL},
156fa615556Sabhinav L"ls \"dequals==test\""
157fa615556Sabhinav },
158fa615556Sabhinav {
159fa615556Sabhinav /* test \n */
160fa615556Sabhinav L"ls new",
161fa615556Sabhinav "new",
162c93cba3aSabhinav {"new\\nline", NULL},
163fa615556Sabhinav L"ls new\\\\nline "
164fa615556Sabhinav },
165fa615556Sabhinav {
166fa615556Sabhinav /* test \n inside single quotes */
167fa615556Sabhinav L"ls 'snew",
168fa615556Sabhinav "snew",
169c93cba3aSabhinav {"snew\nline", NULL},
170fa615556Sabhinav L"ls 'snew\nline'"
171fa615556Sabhinav },
172fa615556Sabhinav {
173fa615556Sabhinav /* test \n inside double quotes */
174fa615556Sabhinav L"ls \"dnew",
175fa615556Sabhinav "dnew",
176c93cba3aSabhinav {"dnew\nline", NULL},
177fa615556Sabhinav L"ls \"dnew\nline\""
178fa615556Sabhinav },
179fa615556Sabhinav {
180fa615556Sabhinav /* test single space */
181fa615556Sabhinav L"ls spac",
182fa615556Sabhinav "spac",
183c93cba3aSabhinav {"space test", NULL},
184fa615556Sabhinav L"ls space\\ test "
185fa615556Sabhinav },
186fa615556Sabhinav {
187fa615556Sabhinav /* test single space inside singlq quotes */
188fa615556Sabhinav L"ls 's_spac",
189fa615556Sabhinav "s_spac",
190c93cba3aSabhinav {"s_space test", NULL},
191fa615556Sabhinav L"ls 's_space test'"
192fa615556Sabhinav },
193fa615556Sabhinav {
194fa615556Sabhinav /* test single space inside double quotes */
195fa615556Sabhinav L"ls \"d_spac",
196fa615556Sabhinav "d_spac",
197c93cba3aSabhinav {"d_space test", NULL},
198fa615556Sabhinav L"ls \"d_space test\""
199fa615556Sabhinav },
200fa615556Sabhinav {
201fa615556Sabhinav /* test multiple spaces */
202fa615556Sabhinav L"ls multi",
203fa615556Sabhinav "multi",
204c93cba3aSabhinav {"multi space test", NULL},
205fa615556Sabhinav L"ls multi\\ space\\ \\ test "
206fa615556Sabhinav },
207fa615556Sabhinav {
208fa615556Sabhinav /* test multiple spaces inside single quotes */
209fa615556Sabhinav L"ls 's_multi",
210fa615556Sabhinav "s_multi",
211c93cba3aSabhinav {"s_multi space test", NULL},
212fa615556Sabhinav L"ls 's_multi space test'"
213fa615556Sabhinav },
214fa615556Sabhinav {
215fa615556Sabhinav /* test multiple spaces inside double quotes */
216fa615556Sabhinav L"ls \"d_multi",
217fa615556Sabhinav "d_multi",
218c93cba3aSabhinav {"d_multi space test", NULL},
219fa615556Sabhinav L"ls \"d_multi space test\""
220fa615556Sabhinav },
221fa615556Sabhinav {
222fa615556Sabhinav /* test double quotes */
223fa615556Sabhinav L"ls doub",
224fa615556Sabhinav "doub",
225c93cba3aSabhinav {"doub\"quotes", NULL},
226fa615556Sabhinav L"ls doub\\\"quotes "
227fa615556Sabhinav },
228fa615556Sabhinav {
229fa615556Sabhinav /* test double quotes inside single quotes */
230fa615556Sabhinav L"ls 's_doub",
231fa615556Sabhinav "s_doub",
232c93cba3aSabhinav {"s_doub\"quotes", NULL},
233fa615556Sabhinav L"ls 's_doub\"quotes'"
234fa615556Sabhinav },
235fa615556Sabhinav {
236fa615556Sabhinav /* test double quotes inside double quotes */
237fa615556Sabhinav L"ls \"d_doub",
238fa615556Sabhinav "d_doub",
239c93cba3aSabhinav {"d_doub\"quotes", NULL},
240fa615556Sabhinav L"ls \"d_doub\\\"quotes\""
241fa615556Sabhinav },
242fa615556Sabhinav {
243fa615556Sabhinav /* test multiple double quotes */
244fa615556Sabhinav L"ls mud",
245fa615556Sabhinav "mud",
246c93cba3aSabhinav {"mud\"qu\"otes\"", NULL},
247fa615556Sabhinav L"ls mud\\\"qu\\\"otes\\\" "
248fa615556Sabhinav },
249fa615556Sabhinav {
250fa615556Sabhinav /* test multiple double quotes inside single quotes */
251fa615556Sabhinav L"ls 'smud",
252fa615556Sabhinav "smud",
253c93cba3aSabhinav {"smud\"qu\"otes\"", NULL},
254fa615556Sabhinav L"ls 'smud\"qu\"otes\"'"
255fa615556Sabhinav },
256fa615556Sabhinav {
257fa615556Sabhinav /* test multiple double quotes inside double quotes */
258fa615556Sabhinav L"ls \"dmud",
259fa615556Sabhinav "dmud",
260c93cba3aSabhinav {"dmud\"qu\"otes\"", NULL},
261fa615556Sabhinav L"ls \"dmud\\\"qu\\\"otes\\\"\""
262fa615556Sabhinav },
263fa615556Sabhinav {
264fa615556Sabhinav /* test one single quote */
265fa615556Sabhinav L"ls sing",
266fa615556Sabhinav "sing",
267c93cba3aSabhinav {"single'quote", NULL},
268fa615556Sabhinav L"ls single\\'quote "
269fa615556Sabhinav },
270fa615556Sabhinav {
271fa615556Sabhinav /* test one single quote inside single quote */
272fa615556Sabhinav L"ls 'ssing",
273fa615556Sabhinav "ssing",
274c93cba3aSabhinav {"ssingle'quote", NULL},
275fa615556Sabhinav L"ls 'ssingle'\\''quote'"
276fa615556Sabhinav },
277fa615556Sabhinav {
278fa615556Sabhinav /* test one single quote inside double quote */
279fa615556Sabhinav L"ls \"dsing",
280fa615556Sabhinav "dsing",
281c93cba3aSabhinav {"dsingle'quote", NULL},
282fa615556Sabhinav L"ls \"dsingle'quote\""
283fa615556Sabhinav },
284fa615556Sabhinav {
285fa615556Sabhinav /* test multiple single quotes */
286fa615556Sabhinav L"ls mu_sing",
287fa615556Sabhinav "mu_sing",
288c93cba3aSabhinav {"mu_single''quotes''", NULL},
289fa615556Sabhinav L"ls mu_single\\'\\'quotes\\'\\' "
290fa615556Sabhinav },
291fa615556Sabhinav {
292fa615556Sabhinav /* test multiple single quotes inside single quote */
293fa615556Sabhinav L"ls 'smu_sing",
294fa615556Sabhinav "smu_sing",
295c93cba3aSabhinav {"smu_single''quotes''", NULL},
296fa615556Sabhinav L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
297fa615556Sabhinav },
298fa615556Sabhinav {
299fa615556Sabhinav /* test multiple single quotes inside double quote */
300fa615556Sabhinav L"ls \"dmu_sing",
301fa615556Sabhinav "dmu_sing",
302c93cba3aSabhinav {"dmu_single''quotes''", NULL},
303fa615556Sabhinav L"ls \"dmu_single''quotes''\""
304fa615556Sabhinav },
305fa615556Sabhinav {
306fa615556Sabhinav /* test parenthesis */
307fa615556Sabhinav L"ls paren",
308fa615556Sabhinav "paren",
309c93cba3aSabhinav {"paren(test)", NULL},
310fa615556Sabhinav L"ls paren\\(test\\) "
311fa615556Sabhinav },
312fa615556Sabhinav {
313fa615556Sabhinav /* test parenthesis inside single quote */
314fa615556Sabhinav L"ls 'sparen",
315fa615556Sabhinav "sparen",
316c93cba3aSabhinav {"sparen(test)", NULL},
317fa615556Sabhinav L"ls 'sparen(test)'"
318fa615556Sabhinav },
319fa615556Sabhinav {
320fa615556Sabhinav /* test parenthesis inside double quote */
321fa615556Sabhinav L"ls \"dparen",
322fa615556Sabhinav "dparen",
323c93cba3aSabhinav {"dparen(test)", NULL},
324fa615556Sabhinav L"ls \"dparen(test)\""
325fa615556Sabhinav },
326fa615556Sabhinav {
327fa615556Sabhinav /* test pipe */
328fa615556Sabhinav L"ls pip",
329fa615556Sabhinav "pip",
330c93cba3aSabhinav {"pipe|test", NULL},
331fa615556Sabhinav L"ls pipe\\|test "
332fa615556Sabhinav },
333fa615556Sabhinav {
334fa615556Sabhinav /* test pipe inside single quote */
335fa615556Sabhinav L"ls 'spip",
336fa615556Sabhinav "spip",
337c93cba3aSabhinav {"spipe|test", NULL},
338fa615556Sabhinav L"ls 'spipe|test'",
339fa615556Sabhinav },
340fa615556Sabhinav {
341fa615556Sabhinav /* test pipe inside double quote */
342fa615556Sabhinav L"ls \"dpip",
343fa615556Sabhinav "dpip",
344c93cba3aSabhinav {"dpipe|test", NULL},
345fa615556Sabhinav L"ls \"dpipe|test\""
346fa615556Sabhinav },
347fa615556Sabhinav {
348fa615556Sabhinav /* test tab */
349fa615556Sabhinav L"ls ta",
350fa615556Sabhinav "ta",
351c93cba3aSabhinav {"tab\ttest", NULL},
352fa615556Sabhinav L"ls tab\\\ttest "
353fa615556Sabhinav },
354fa615556Sabhinav {
355fa615556Sabhinav /* test tab inside single quote */
356fa615556Sabhinav L"ls 'sta",
357fa615556Sabhinav "sta",
358c93cba3aSabhinav {"stab\ttest", NULL},
359fa615556Sabhinav L"ls 'stab\ttest'"
360fa615556Sabhinav },
361fa615556Sabhinav {
362fa615556Sabhinav /* test tab inside double quote */
363fa615556Sabhinav L"ls \"dta",
364fa615556Sabhinav "dta",
365c93cba3aSabhinav {"dtab\ttest", NULL},
366fa615556Sabhinav L"ls \"dtab\ttest\""
367fa615556Sabhinav },
368fa615556Sabhinav {
369fa615556Sabhinav /* test back tick */
370fa615556Sabhinav L"ls tic",
371fa615556Sabhinav "tic",
372c93cba3aSabhinav {"tick`test`", NULL},
373fa615556Sabhinav L"ls tick\\`test\\` "
374fa615556Sabhinav },
375fa615556Sabhinav {
376fa615556Sabhinav /* test back tick inside single quote */
377fa615556Sabhinav L"ls 'stic",
378fa615556Sabhinav "stic",
379c93cba3aSabhinav {"stick`test`", NULL},
380fa615556Sabhinav L"ls 'stick`test`'"
381fa615556Sabhinav },
382fa615556Sabhinav {
383fa615556Sabhinav /* test back tick inside double quote */
384fa615556Sabhinav L"ls \"dtic",
385fa615556Sabhinav "dtic",
386c93cba3aSabhinav {"dtick`test`", NULL},
387fa615556Sabhinav L"ls \"dtick\\`test\\`\""
388fa615556Sabhinav },
389fa615556Sabhinav {
390fa615556Sabhinav /* test for @ */
391fa615556Sabhinav L"ls at",
392fa615556Sabhinav "at",
393c93cba3aSabhinav {"atthe@rate", NULL},
394fa615556Sabhinav L"ls atthe\\@rate "
395fa615556Sabhinav },
396fa615556Sabhinav {
397fa615556Sabhinav /* test for @ inside single quote */
398fa615556Sabhinav L"ls 'sat",
399fa615556Sabhinav "sat",
400c93cba3aSabhinav {"satthe@rate", NULL},
401fa615556Sabhinav L"ls 'satthe@rate'"
402fa615556Sabhinav },
403fa615556Sabhinav {
404fa615556Sabhinav /* test for @ inside double quote */
405fa615556Sabhinav L"ls \"dat",
406fa615556Sabhinav "dat",
407c93cba3aSabhinav {"datthe@rate", NULL},
408fa615556Sabhinav L"ls \"datthe@rate\""
409fa615556Sabhinav },
410fa615556Sabhinav {
411fa615556Sabhinav /* test ; */
412fa615556Sabhinav L"ls semi",
413fa615556Sabhinav "semi",
414c93cba3aSabhinav {"semi;colon;test", NULL},
415fa615556Sabhinav L"ls semi\\;colon\\;test "
416fa615556Sabhinav },
417fa615556Sabhinav {
418fa615556Sabhinav /* test ; inside single quote */
419fa615556Sabhinav L"ls 'ssemi",
420fa615556Sabhinav "ssemi",
421c93cba3aSabhinav {"ssemi;colon;test", NULL},
422fa615556Sabhinav L"ls 'ssemi;colon;test'"
423fa615556Sabhinav },
424fa615556Sabhinav {
425fa615556Sabhinav /* test ; inside double quote */
426fa615556Sabhinav L"ls \"dsemi",
427fa615556Sabhinav "dsemi",
428c93cba3aSabhinav {"dsemi;colon;test", NULL},
429fa615556Sabhinav L"ls \"dsemi;colon;test\""
430fa615556Sabhinav },
431fa615556Sabhinav {
432fa615556Sabhinav /* test & */
433fa615556Sabhinav L"ls amp",
434fa615556Sabhinav "amp",
435c93cba3aSabhinav {"ampers&and", NULL},
436fa615556Sabhinav L"ls ampers\\&and "
437fa615556Sabhinav },
438fa615556Sabhinav {
439fa615556Sabhinav /* test & inside single quote */
440fa615556Sabhinav L"ls 'samp",
441fa615556Sabhinav "samp",
442c93cba3aSabhinav {"sampers&and", NULL},
443fa615556Sabhinav L"ls 'sampers&and'"
444fa615556Sabhinav },
445fa615556Sabhinav {
446fa615556Sabhinav /* test & inside double quote */
447fa615556Sabhinav L"ls \"damp",
448fa615556Sabhinav "damp",
449c93cba3aSabhinav {"dampers&and", NULL},
450fa615556Sabhinav L"ls \"dampers&and\""
451fa615556Sabhinav },
4522afc179cSabhinav {
4532afc179cSabhinav /* test completion when cursor at \ */
4542afc179cSabhinav L"ls foo\\",
4552afc179cSabhinav "foo",
456c93cba3aSabhinav {"foo bar", NULL},
4572afc179cSabhinav L"ls foo\\ bar "
4582afc179cSabhinav },
4592afc179cSabhinav {
4602afc179cSabhinav /* test completion when cursor at single quote */
4612afc179cSabhinav L"ls foo'",
462c93cba3aSabhinav "foo'",
463c93cba3aSabhinav {"foo bar", NULL},
4642afc179cSabhinav L"ls foo\\ bar "
4652afc179cSabhinav },
4662afc179cSabhinav {
4672afc179cSabhinav /* test completion when cursor at double quote */
4682afc179cSabhinav L"ls foo\"",
469c93cba3aSabhinav "foo\"",
470c93cba3aSabhinav {"foo bar", NULL},
4712afc179cSabhinav L"ls foo\\ bar "
472c93cba3aSabhinav },
473c93cba3aSabhinav {
474c93cba3aSabhinav /* test multiple completion matches */
475c93cba3aSabhinav L"ls fo",
476c93cba3aSabhinav "fo",
477c93cba3aSabhinav {"foo bar", "foo baz"},
478c93cba3aSabhinav L"ls foo\\ ba"
479c93cba3aSabhinav },
480c93cba3aSabhinav {
481c93cba3aSabhinav L"ls ba",
482c93cba3aSabhinav "ba",
483c93cba3aSabhinav {"bar <bar>", "bar <baz>"},
484c93cba3aSabhinav L"ls bar\\ \\<ba"
4852afc179cSabhinav }
486fa615556Sabhinav };
487fa615556Sabhinav
488fa615556Sabhinav static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
489fa615556Sabhinav
490fa615556Sabhinav /*
491c93cba3aSabhinav * Custom completion function passed to fn_complet, NULLe.
492fa615556Sabhinav * The function returns hardcoded completion matches
493fa615556Sabhinav * based on the test cases present in inputs[] (above)
494fa615556Sabhinav */
495fa615556Sabhinav static char *
mycomplet_func(const char * text,int index)496fa615556Sabhinav mycomplet_func(const char *text, int index)
497fa615556Sabhinav {
498c93cba3aSabhinav static int last_index = 0;
499fa615556Sabhinav size_t i = 0;
500c93cba3aSabhinav if (last_index == 2) {
501c93cba3aSabhinav last_index = 0;
502fa615556Sabhinav return NULL;
503fa615556Sabhinav }
504fa615556Sabhinav
505fa615556Sabhinav for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
506c93cba3aSabhinav if (strcmp(text, inputs[i].completion_function_input) == 0) {
507c93cba3aSabhinav if (inputs[i].expanded_text[last_index] != NULL)
508c93cba3aSabhinav return strdup(inputs[i].expanded_text[last_index++]);
509c93cba3aSabhinav else {
510c93cba3aSabhinav last_index = 0;
511c93cba3aSabhinav return NULL;
512c93cba3aSabhinav }
513c93cba3aSabhinav }
514fa615556Sabhinav }
515fa615556Sabhinav
516fa615556Sabhinav return NULL;
517fa615556Sabhinav }
518fa615556Sabhinav
519fa615556Sabhinav int
main(int argc,char ** argv)520fa615556Sabhinav main(int argc, char **argv)
521fa615556Sabhinav {
522fa615556Sabhinav EditLine *el = el_init(argv[0], stdin, stdout, stderr);
523fa615556Sabhinav size_t i;
524fa615556Sabhinav size_t input_len;
525fa615556Sabhinav el_line_t line;
526fa615556Sabhinav wchar_t *buffer = malloc(64 * sizeof(*buffer));
527fa615556Sabhinav if (buffer == NULL)
528fa615556Sabhinav err(EXIT_FAILURE, "malloc failed");
529fa615556Sabhinav
530fa615556Sabhinav for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
531fa615556Sabhinav memset(buffer, 0, 64 * sizeof(*buffer));
532fa615556Sabhinav input_len = wcslen(inputs[i].user_typed_text);
533fa615556Sabhinav wmemcpy(buffer, inputs[i].user_typed_text, input_len);
534fa615556Sabhinav buffer[input_len] = 0;
535fa615556Sabhinav line.buffer = buffer;
536fa615556Sabhinav line.cursor = line.buffer + input_len ;
537fa615556Sabhinav line.lastchar = line.cursor - 1;
538fa615556Sabhinav line.limit = line.buffer + 64 * sizeof(*buffer);
539fa615556Sabhinav el->el_line = line;
540fa615556Sabhinav fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL);
541fa615556Sabhinav
542fa615556Sabhinav /*
543fa615556Sabhinav * fn_complete would have expanded and escaped the input in el->el_line.buffer.
544fa615556Sabhinav * We need to assert that it matches with the expected value in our test data
545fa615556Sabhinav */
546fa615556Sabhinav printf("User input: %ls\t Expected output: %ls\t Generated output: %ls\n",
547fa615556Sabhinav inputs[i].user_typed_text, inputs[i].escaped_output, el->el_line.buffer);
548fa615556Sabhinav assert(wcscmp(el->el_line.buffer, inputs[i].escaped_output) == 0);
549fa615556Sabhinav }
550fa615556Sabhinav el_end(el);
551fa615556Sabhinav return 0;
552fa615556Sabhinav
553fa615556Sabhinav }
554