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

Reply via email to