Module Name: src
Committed By: abhinav
Date: Sun Sep 8 05:50:58 UTC 2019
Modified Files:
src/lib/libedit: filecomplete.c
src/lib/libedit/TEST: test_filecompletion.c
Log Message:
PR lib/54510: Fix file completion inside quotes which broke in rev 1.53
While there also fix handling character appending in the file completions when
inside quotes. For example when inside a quote, if the completion is a
directory then
append a '/' but don't close the quote. On the other hand when inside a quote
if the
completion is a file name and it is the only match then we can close the quote.
To generate a diff of this commit:
cvs rdiff -u -r1.57 -r1.58 src/lib/libedit/filecomplete.c
cvs rdiff -u -r1.4 -r1.5 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.57 src/lib/libedit/filecomplete.c:1.58
--- src/lib/libedit/filecomplete.c:1.57 Sun Jul 28 09:27:29 2019
+++ src/lib/libedit/filecomplete.c Sun Sep 8 05:50:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: filecomplete.c,v 1.57 2019/07/28 09:27:29 christos Exp $ */
+/* $NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 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.57 2019/07/28 09:27:29 christos Exp $");
+__RCSID("$NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 abhinav Exp $");
#endif /* not lint && not SCCSID */
#include <sys/types.h>
@@ -192,7 +192,8 @@ unescape_string(const wchar_t *string, s
}
static char *
-escape_filename(EditLine * el, const char *filename)
+escape_filename(EditLine * el, const char *filename, int single_match,
+ const char *(*app_func)(const char *))
{
size_t original_len = 0;
size_t escaped_character_count = 0;
@@ -204,6 +205,7 @@ escape_filename(EditLine * el, const cha
size_t d_quoted = 0; /* does the input contain a double quote */
char *escaped_str;
wchar_t *temp = el->el_line.buffer;
+ const char *append_char = NULL;
if (filename == NULL)
return NULL;
@@ -246,6 +248,9 @@ escape_filename(EditLine * el, const cha
if (s_quoted || d_quoted)
newlen++;
+ if (single_match && app_func)
+ newlen++;
+
if ((escaped_str = el_malloc(newlen)) == NULL)
return NULL;
@@ -285,11 +290,24 @@ escape_filename(EditLine * el, const cha
escaped_str[offset++] = c;
}
- /* close the quotes */
- if (s_quoted)
- escaped_str[offset++] = '\'';
- else if (d_quoted)
- escaped_str[offset++] = '"';
+ if (single_match && app_func) {
+ escaped_str[offset] = 0;
+ append_char = app_func(escaped_str);
+ /* we want to append space only if we are not inside quotes */
+ if (append_char[0] == ' ') {
+ if (!s_quoted && !d_quoted)
+ escaped_str[offset++] = append_char[0];
+ } else
+ escaped_str[offset++] = append_char[0];
+ }
+
+ /* close the quotes if single match and the match is not a directory */
+ if (single_match && (append_char && append_char[0] == ' ')) {
+ if (s_quoted)
+ escaped_str[offset++] = '\'';
+ else if (d_quoted)
+ escaped_str[offset++] = '"';
+ }
escaped_str[offset] = 0;
return escaped_str;
@@ -596,6 +614,10 @@ find_word_to_complete(const wchar_t * cu
if (ctemp - buffer >= 2 && ctemp[-2] == '\\') {
ctemp -= 2;
continue;
+ } else if (ctemp - buffer >= 2 &&
+ (ctemp[-2] == '\'' || ctemp[-2] == '"')) {
+ ctemp--;
+ continue;
} else
break;
}
@@ -605,6 +627,10 @@ find_word_to_complete(const wchar_t * cu
}
len = (size_t) (cursor - ctemp);
+ if (len == 1 && (ctemp[0] == '\'' || ctemp[0] == '"')) {
+ len = 0;
+ ctemp++;
+ }
*length = len;
wchar_t *unescaped_word = unescape_string(ctemp, len);
if (unescaped_word == NULL)
@@ -689,31 +715,29 @@ fn_complete(EditLine *el,
retval = CC_REFRESH;
if (matches[0][0] != '\0') {
- el_deletestr(el, (int) len);
+ el_deletestr(el, (int)len);
if (!attempted_completion_function)
- completion = escape_filename(el, matches[0]);
+ completion = escape_filename(el, matches[0],
+ single_match, app_func);
else
completion = strdup(matches[0]);
if (completion == NULL)
goto out;
if (single_match) {
- /*
- * We found exact match. Add a space after
- * it, unless we do filename completion and the
- * object is a directory. Also do necessary escape quoting
+ /* We found exact match. Add a space after it,
+ * unless we do filename completion and the
+ * object is a directory. Also do necessary
+ * escape quoting
*/
el_winsertstr(el,
- ct_decode_string(completion, &el->el_scratch));
- el_winsertstr(el,
- ct_decode_string((*app_func)(completion),
- &el->el_scratch));
+ ct_decode_string(completion, &el->el_scratch));
} else {
- /*
- * Only replace the completed string with common part of
- * possible matches if there is possible completion.
+ /* Only replace the completed string with
+ * common part of possible matches if there is
+ * possible completion.
*/
el_winsertstr(el,
- ct_decode_string(completion, &el->el_scratch));
+ ct_decode_string(completion, &el->el_scratch));
}
free(completion);
}
Index: src/lib/libedit/TEST/test_filecompletion.c
diff -u src/lib/libedit/TEST/test_filecompletion.c:1.4 src/lib/libedit/TEST/test_filecompletion.c:1.5
--- src/lib/libedit/TEST/test_filecompletion.c:1.4 Sun Mar 31 03:04:57 2019
+++ src/lib/libedit/TEST/test_filecompletion.c Sun Sep 8 05:50:58 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: test_filecompletion.c,v 1.4 2019/03/31 03:04:57 abhinav Exp $ */
+/* $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $ */
/*-
* Copyright (c) 2017 Abhinav Upadhyay <[email protected]>
@@ -62,14 +62,14 @@ static test_input inputs[] = {
L"ls \"dq_ang",
"dq_ang",
{"dq_ang<ular>test", NULL},
- L"ls \"dq_ang<ular>test\" "
+ L"ls \"dq_ang<ular>test\""
},
{
/* test angular bracket inside singlq quotes: ls "sq_ang */
L"ls 'sq_ang",
"sq_ang",
{"sq_ang<ular>test", NULL},
- L"ls 'sq_ang<ular>test' "
+ L"ls 'sq_ang<ular>test'"
},
{
/* simple test for backslash */
@@ -83,14 +83,14 @@ static test_input inputs[] = {
L"ls 'sback",
"sback",
{"sbackslash\\test", NULL},
- L"ls 'sbackslash\\test' "
+ L"ls 'sbackslash\\test'"
},
{
/* backslash inside double quotes */
L"ls \"dback",
"dback",
{"dbackslash\\test", NULL},
- L"ls \"dbackslash\\\\test\" "
+ L"ls \"dbackslash\\\\test\""
},
{
/* test braces */
@@ -104,14 +104,14 @@ static test_input inputs[] = {
L"ls 'sbr",
"sbr",
{"sbraces{test}", NULL},
- L"ls 'sbraces{test}' "
+ L"ls 'sbraces{test}'"
},
{
/* test braces inside double quotes */
L"ls \"dbr",
"dbr",
{"dbraces{test}", NULL},
- L"ls \"dbraces{test}\" "
+ L"ls \"dbraces{test}\""
},
{
/* test dollar */
@@ -125,14 +125,14 @@ static test_input inputs[] = {
L"ls 'sdoll",
"sdoll",
{"sdoll$artest", NULL},
- L"ls 'sdoll$artest' "
+ L"ls 'sdoll$artest'"
},
{
/* test dollar inside double quotes */
L"ls \"ddoll",
"ddoll",
{"ddoll$artest", NULL},
- L"ls \"ddoll\\$artest\" "
+ L"ls \"ddoll\\$artest\""
},
{
/* test equals */
@@ -146,14 +146,14 @@ static test_input inputs[] = {
L"ls 'seq",
"seq",
{"sequals==test", NULL},
- L"ls 'sequals==test' "
+ L"ls 'sequals==test'"
},
{
/* test equals inside double quotes */
L"ls \"deq",
"deq",
{"dequals==test", NULL},
- L"ls \"dequals==test\" "
+ L"ls \"dequals==test\""
},
{
/* test \n */
@@ -167,14 +167,14 @@ static test_input inputs[] = {
L"ls 'snew",
"snew",
{"snew\nline", NULL},
- L"ls 'snew\nline' "
+ L"ls 'snew\nline'"
},
{
/* test \n inside double quotes */
L"ls \"dnew",
"dnew",
{"dnew\nline", NULL},
- L"ls \"dnew\nline\" "
+ L"ls \"dnew\nline\""
},
{
/* test single space */
@@ -188,14 +188,14 @@ static test_input inputs[] = {
L"ls 's_spac",
"s_spac",
{"s_space test", NULL},
- L"ls 's_space test' "
+ L"ls 's_space test'"
},
{
/* test single space inside double quotes */
L"ls \"d_spac",
"d_spac",
{"d_space test", NULL},
- L"ls \"d_space test\" "
+ L"ls \"d_space test\""
},
{
/* test multiple spaces */
@@ -209,14 +209,14 @@ static test_input inputs[] = {
L"ls 's_multi",
"s_multi",
{"s_multi space test", NULL},
- L"ls 's_multi space test' "
+ L"ls 's_multi space test'"
},
{
/* test multiple spaces inside double quotes */
L"ls \"d_multi",
"d_multi",
{"d_multi space test", NULL},
- L"ls \"d_multi space test\" "
+ L"ls \"d_multi space test\""
},
{
/* test double quotes */
@@ -230,14 +230,14 @@ static test_input inputs[] = {
L"ls 's_doub",
"s_doub",
{"s_doub\"quotes", NULL},
- L"ls 's_doub\"quotes' "
+ L"ls 's_doub\"quotes'"
},
{
/* test double quotes inside double quotes */
L"ls \"d_doub",
"d_doub",
{"d_doub\"quotes", NULL},
- L"ls \"d_doub\\\"quotes\" "
+ L"ls \"d_doub\\\"quotes\""
},
{
/* test multiple double quotes */
@@ -251,14 +251,14 @@ static test_input inputs[] = {
L"ls 'smud",
"smud",
{"smud\"qu\"otes\"", NULL},
- L"ls 'smud\"qu\"otes\"' "
+ L"ls 'smud\"qu\"otes\"'"
},
{
/* test multiple double quotes inside double quotes */
L"ls \"dmud",
"dmud",
{"dmud\"qu\"otes\"", NULL},
- L"ls \"dmud\\\"qu\\\"otes\\\"\" "
+ L"ls \"dmud\\\"qu\\\"otes\\\"\""
},
{
/* test one single quote */
@@ -272,14 +272,14 @@ static test_input inputs[] = {
L"ls 'ssing",
"ssing",
{"ssingle'quote", NULL},
- L"ls 'ssingle'\\''quote' "
+ L"ls 'ssingle'\\''quote'"
},
{
/* test one single quote inside double quote */
L"ls \"dsing",
"dsing",
{"dsingle'quote", NULL},
- L"ls \"dsingle'quote\" "
+ L"ls \"dsingle'quote\""
},
{
/* test multiple single quotes */
@@ -293,14 +293,14 @@ static test_input inputs[] = {
L"ls 'smu_sing",
"smu_sing",
{"smu_single''quotes''", NULL},
- L"ls 'smu_single'\\'''\\''quotes'\\\'''\\''' "
+ L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
},
{
/* test multiple single quotes inside double quote */
L"ls \"dmu_sing",
"dmu_sing",
{"dmu_single''quotes''", NULL},
- L"ls \"dmu_single''quotes''\" "
+ L"ls \"dmu_single''quotes''\""
},
{
/* test parenthesis */
@@ -314,14 +314,14 @@ static test_input inputs[] = {
L"ls 'sparen",
"sparen",
{"sparen(test)", NULL},
- L"ls 'sparen(test)' "
+ L"ls 'sparen(test)'"
},
{
/* test parenthesis inside double quote */
L"ls \"dparen",
"dparen",
{"dparen(test)", NULL},
- L"ls \"dparen(test)\" "
+ L"ls \"dparen(test)\""
},
{
/* test pipe */
@@ -335,14 +335,14 @@ static test_input inputs[] = {
L"ls 'spip",
"spip",
{"spipe|test", NULL},
- L"ls 'spipe|test' ",
+ L"ls 'spipe|test'",
},
{
/* test pipe inside double quote */
L"ls \"dpip",
"dpip",
{"dpipe|test", NULL},
- L"ls \"dpipe|test\" "
+ L"ls \"dpipe|test\""
},
{
/* test tab */
@@ -356,14 +356,14 @@ static test_input inputs[] = {
L"ls 'sta",
"sta",
{"stab\ttest", NULL},
- L"ls 'stab\ttest' "
+ L"ls 'stab\ttest'"
},
{
/* test tab inside double quote */
L"ls \"dta",
"dta",
{"dtab\ttest", NULL},
- L"ls \"dtab\ttest\" "
+ L"ls \"dtab\ttest\""
},
{
/* test back tick */
@@ -377,14 +377,14 @@ static test_input inputs[] = {
L"ls 'stic",
"stic",
{"stick`test`", NULL},
- L"ls 'stick`test`' "
+ L"ls 'stick`test`'"
},
{
/* test back tick inside double quote */
L"ls \"dtic",
"dtic",
{"dtick`test`", NULL},
- L"ls \"dtick\\`test\\`\" "
+ L"ls \"dtick\\`test\\`\""
},
{
/* test for @ */
@@ -398,14 +398,14 @@ static test_input inputs[] = {
L"ls 'sat",
"sat",
{"satthe@rate", NULL},
- L"ls 'satthe@rate' "
+ L"ls 'satthe@rate'"
},
{
/* test for @ inside double quote */
L"ls \"dat",
"dat",
{"datthe@rate", NULL},
- L"ls \"datthe@rate\" "
+ L"ls \"datthe@rate\""
},
{
/* test ; */
@@ -419,14 +419,14 @@ static test_input inputs[] = {
L"ls 'ssemi",
"ssemi",
{"ssemi;colon;test", NULL},
- L"ls 'ssemi;colon;test' "
+ L"ls 'ssemi;colon;test'"
},
{
/* test ; inside double quote */
L"ls \"dsemi",
"dsemi",
{"dsemi;colon;test", NULL},
- L"ls \"dsemi;colon;test\" "
+ L"ls \"dsemi;colon;test\""
},
{
/* test & */
@@ -440,14 +440,14 @@ static test_input inputs[] = {
L"ls 'samp",
"samp",
{"sampers&and", NULL},
- L"ls 'sampers&and' "
+ L"ls 'sampers&and'"
},
{
/* test & inside double quote */
L"ls \"damp",
"damp",
{"dampers&and", NULL},
- L"ls \"dampers&and\" "
+ L"ls \"dampers&and\""
},
{
/* test completion when cursor at \ */