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 <[email protected]>
@@ -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\"\\'`@$><=;|&{(";