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 * 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 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