Module Name: src Committed By: abhinav Date: Fri May 4 16:39:15 UTC 2018
Modified Files: src/lib/libedit: filecomplete.c src/lib/libedit/TEST: test_filecompletion.c Log Message: Handle filename autocompletion when the cursor is at a backslash or quote character For example, handle following case: $ touch 'foo bar' $ ls foo\<TAB> --> $ ls foo\ bar Also add test cases for this. Thanks to Christos for review To generate a diff of this commit: cvs rdiff -u -r1.49 -r1.50 src/lib/libedit/filecomplete.c cvs rdiff -u -r1.2 -r1.3 src/lib/libedit/TEST/test_filecompletion.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libedit/filecomplete.c diff -u src/lib/libedit/filecomplete.c:1.49 src/lib/libedit/filecomplete.c:1.50 --- src/lib/libedit/filecomplete.c:1.49 Wed May 2 08:45:03 2018 +++ src/lib/libedit/filecomplete.c Fri May 4 16:39:14 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.c,v 1.49 2018/05/02 08:45:03 abhinav Exp $ */ +/* $NetBSD: filecomplete.c,v 1.50 2018/05/04 16:39:14 abhinav Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.49 2018/05/02 08:45:03 abhinav Exp $"); +__RCSID("$NetBSD: filecomplete.c,v 1.50 2018/05/04 16:39:14 abhinav Exp $"); #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -528,6 +528,48 @@ fn_display_match_list(EditLine * el, cha } } +static wchar_t * +find_word_to_complete(const wchar_t * cursor, const wchar_t * buffer, + const wchar_t * word_break, const wchar_t * special_prefixes, size_t * length) +{ + /* We now look backwards for the start of a filename/variable word */ + const wchar_t *ctemp = cursor; + int cursor_at_quote; + size_t len; + wchar_t *temp; + + /* if the cursor is placed at a slash or a quote, we need to find the + * word before it + */ + if (ctemp > buffer) { + switch (ctemp[-1]) { + case '\\': + case '\'': + case '"': + cursor_at_quote = 1; + ctemp--; + break; + default: + cursor_at_quote = 0; + } + } + while (ctemp > buffer + && !wcschr(word_break, ctemp[-1]) + && (!special_prefixes || !wcschr(special_prefixes, ctemp[-1]))) + ctemp--; + + len = (size_t) (cursor - ctemp - cursor_at_quote); + temp = el_malloc((len + 1) * sizeof(*temp)); + if (temp == NULL) + return NULL; + (void) wcsncpy(temp, ctemp, len); + temp[len] = '\0'; + if (cursor_at_quote) + len++; + *length = len; + return temp; +} + /* * Complete the word at or before point, * 'what_to_do' says what to do with the completion. @@ -551,7 +593,6 @@ fn_complete(EditLine *el, const LineInfoW *li; wchar_t *temp; char **matches; - const wchar_t *ctemp; size_t len; int what_to_do = '\t'; int retval = CC_NORM; @@ -568,20 +609,11 @@ fn_complete(EditLine *el, if (!app_func) app_func = append_char_function; - /* We now look backwards for the start of a filename/variable word */ li = el_wline(el); - ctemp = li->cursor; - while (ctemp > li->buffer - && !wcschr(word_break, ctemp[-1]) - && (!special_prefixes || !wcschr(special_prefixes, ctemp[-1]) ) ) - ctemp--; - - len = (size_t)(li->cursor - ctemp); - temp = el_malloc((len + 1) * sizeof(*temp)); + temp = find_word_to_complete(li->cursor, + li->buffer, word_break, special_prefixes, &len); if (temp == NULL) goto out; - (void)wcsncpy(temp, ctemp, len); - temp[len] = '\0'; /* these can be used by function called in completion_matches() */ /* or (*attempted_completion_function)() */ Index: src/lib/libedit/TEST/test_filecompletion.c diff -u src/lib/libedit/TEST/test_filecompletion.c:1.2 src/lib/libedit/TEST/test_filecompletion.c:1.3 --- src/lib/libedit/TEST/test_filecompletion.c:1.2 Sun Oct 15 19:17:30 2017 +++ src/lib/libedit/TEST/test_filecompletion.c Fri May 4 16:39:15 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: test_filecompletion.c,v 1.2 2017/10/15 19:17:30 abhinav Exp $ */ +/* $NetBSD: test_filecompletion.c,v 1.3 2018/05/04 16:39:15 abhinav Exp $ */ /*- * Copyright (c) 2017 Abhinav Upadhyay <abhi...@netbsd.org> @@ -449,6 +449,27 @@ static test_input inputs[] = { "dampers&and", L"ls \"dampers&and\" " }, + { + /* test completion when cursor at \ */ + L"ls foo\\", + "foo", + "foo bar", + L"ls foo\\ bar " + }, + { + /* test completion when cursor at single quote */ + L"ls foo'", + "foo", + "foo bar", + L"ls foo\\ bar " + }, + { + /* test completion when cursor at double quote */ + L"ls foo\"", + "foo", + "foo bar", + L"ls foo\\ bar " + } }; static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";