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