xref: /freebsd/contrib/libedit/TEST/test_filecompletion.c (revision 61c1328eb016476ee7ff5ad65d8224bb43e572db)
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