@@ -680,6 +680,7 @@ static char *complete_from_list(const char *text, int state);
680
680
static char * complete_from_const (const char * text , int state );
681
681
static char * * complete_from_variables (char * text ,
682
682
const char * prefix , const char * suffix );
683
+ static char * complete_from_files (const char * text , int state );
683
684
684
685
static char * pg_strdup_same_case (const char * s , const char * ref );
685
686
static PGresult * exec_query (const char * query );
@@ -1630,7 +1631,10 @@ psql_completion(char *text, int start, int end)
1630
1631
pg_strcasecmp (prev3_wd , "BINARY" ) == 0 ) &&
1631
1632
(pg_strcasecmp (prev_wd , "FROM" ) == 0 ||
1632
1633
pg_strcasecmp (prev_wd , "TO" ) == 0 ))
1633
- matches = completion_matches (text , filename_completion_function );
1634
+ {
1635
+ completion_charp = "" ;
1636
+ matches = completion_matches (text , complete_from_files );
1637
+ }
1634
1638
1635
1639
/* Handle COPY|BINARY <sth> FROM|TO filename */
1636
1640
else if ((pg_strcasecmp (prev4_wd , "COPY" ) == 0 ||
@@ -2953,7 +2957,10 @@ psql_completion(char *text, int start, int end)
2953
2957
strcmp (prev_wd , "\\s" ) == 0 ||
2954
2958
strcmp (prev_wd , "\\w" ) == 0 || strcmp (prev_wd , "\\write" ) == 0
2955
2959
)
2956
- matches = completion_matches (text , filename_completion_function );
2960
+ {
2961
+ completion_charp = "\\" ;
2962
+ matches = completion_matches (text , complete_from_files );
2963
+ }
2957
2964
2958
2965
/*
2959
2966
* Finally, we look through the list of "things", such as TABLE, INDEX and
@@ -3426,6 +3433,53 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
3426
3433
}
3427
3434
3428
3435
3436
+ /*
3437
+ * This function wraps rl_filename_completion_function() to strip quotes from
3438
+ * the input before searching for matches and to quote any matches for which
3439
+ * the consuming command will require it.
3440
+ */
3441
+ static char *
3442
+ complete_from_files (const char * text , int state )
3443
+ {
3444
+ static const char * unquoted_text ;
3445
+ char * unquoted_match ;
3446
+ char * ret = NULL ;
3447
+
3448
+ if (state == 0 )
3449
+ {
3450
+ /* Initialization: stash the unquoted input. */
3451
+ unquoted_text = strtokx (text , "" , NULL , "'" , * completion_charp ,
3452
+ false, true, pset .encoding );
3453
+ /* expect a NULL return for the empty string only */
3454
+ if (!unquoted_text )
3455
+ {
3456
+ psql_assert (!* text );
3457
+ unquoted_text = text ;
3458
+ }
3459
+ }
3460
+
3461
+ unquoted_match = filename_completion_function (unquoted_text , state );
3462
+ if (unquoted_match )
3463
+ {
3464
+ /*
3465
+ * Caller sets completion_charp to a zero- or one-character string
3466
+ * containing the escape character. This is necessary since \copy has
3467
+ * no escape character, but every other backslash command recognizes
3468
+ * "\" as an escape character. Since we have only two callers, don't
3469
+ * bother providing a macro to simplify this.
3470
+ */
3471
+ ret = quote_if_needed (unquoted_match , " \t\r\n\"`" ,
3472
+ '\'' , * completion_charp , pset .encoding );
3473
+ if (ret )
3474
+ free (unquoted_match );
3475
+ else
3476
+ ret = unquoted_match ;
3477
+ }
3478
+
3479
+ return ret ;
3480
+ }
3481
+
3482
+
3429
3483
/* HELPER FUNCTIONS */
3430
3484
3431
3485
0 commit comments