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