Bug reported from Martin Dietze:

The place to change the completion_append_character is
    usually somewhere in the `rl_completion_entry_function'
    callback which is where one usually can distinguish between
    file- or dir-like entries to append a slash for dirs etc.

    This does no longer work since `fn_complete()' takes the
    `append_character' as argument before the callback is executed,
    so that changes to the variable `rl_completion_append_character'
    have in fact no effect for the current completion.

Fix by adding a function that returns the rl_completion_append_character,
when it gets passed in a filename in readline emulation.
This commit is contained in:
christos 2005-06-10 20:21:00 +00:00
parent 0320b64715
commit 3cfbfdb2ef
3 changed files with 41 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: filecomplete.c,v 1.5 2005/05/18 22:34:41 christos Exp $ */ /* $NetBSD: filecomplete.c,v 1.6 2005/06/10 20:21:00 christos Exp $ */
/*- /*-
* Copyright (c) 1997 The NetBSD Foundation, Inc. * Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include "config.h" #include "config.h"
#if !defined(lint) && !defined(SCCSID) #if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: filecomplete.c,v 1.5 2005/05/18 22:34:41 christos Exp $"); __RCSID("$NetBSD: filecomplete.c,v 1.6 2005/06/10 20:21:00 christos Exp $");
#endif /* not lint && not SCCSID */ #endif /* not lint && not SCCSID */
#include <sys/types.h> #include <sys/types.h>
@ -81,7 +81,7 @@ static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
* it's callers's responsibility to free() returned string * it's callers's responsibility to free() returned string
*/ */
char * char *
tilde_expand(char *txt) tilde_expand(const char *txt)
{ {
struct passwd pwres, *pass; struct passwd pwres, *pass;
char *temp; char *temp;
@ -226,27 +226,17 @@ filename_completion_function(const char *text, int state)
} }
if (entry) { /* match found */ if (entry) { /* match found */
struct stat stbuf;
const char *isdir = "";
#if defined(__SVR4) || defined(__linux__) #if defined(__SVR4) || defined(__linux__)
len = strlen(entry->d_name); len = strlen(entry->d_name);
#else #else
len = entry->d_namlen; len = entry->d_namlen;
#endif #endif
temp = malloc(strlen(dirpath) + len + 1);
if (temp == NULL)
return NULL;
(void)sprintf(temp, "%s%s", dirpath, entry->d_name); /* safe */
/* test, if it's directory */ temp = malloc(strlen(dirname) + len + 1);
if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
isdir = "/";
free(temp);
temp = malloc(strlen(dirname) + len + 1 + 1);
if (temp == NULL) if (temp == NULL)
return NULL; return NULL;
(void)sprintf(temp, "%s%s%s", dirname, entry->d_name, isdir); (void)sprintf(temp, "%s%s", dirname, entry->d_name);
} else { } else {
(void)closedir(dir); (void)closedir(dir);
dir = NULL; dir = NULL;
@ -257,7 +247,22 @@ filename_completion_function(const char *text, int state)
} }
static const char *
append_char_function(const char *name)
{
struct stat stbuf;
char *expname = *name == '~' ? tilde_expand(name) : NULL;
const char *rs = "";
if (stat(expname ? expname : name, &stbuf) == -1)
goto out;
if (S_ISDIR(stbuf.st_mode))
rs = "/";
out:
if (expname)
free(expname);
return rs;
}
/* /*
* returns list of completions for text given * returns list of completions for text given
* non-static for readline. * non-static for readline.
@ -385,7 +390,7 @@ fn_complete(EditLine *el,
char *(*complet_func)(const char *, int), char *(*complet_func)(const char *, int),
char **(*attempted_completion_function)(const char *, int, int), char **(*attempted_completion_function)(const char *, int, int),
const char *word_break, const char *special_prefixes, const char *word_break, const char *special_prefixes,
char append_character, int query_items, const char *(*app_func)(const char *), int query_items,
int *completion_type, int *over, int *point, int *end) int *completion_type, int *over, int *point, int *end)
{ {
const LineInfo *li; const LineInfo *li;
@ -403,6 +408,8 @@ fn_complete(EditLine *el,
if (!complet_func) if (!complet_func)
complet_func = filename_completion_function; complet_func = filename_completion_function;
if (!app_func)
app_func = append_char_function;
/* We now look backwards for the start of a filename/variable word */ /* We now look backwards for the start of a filename/variable word */
li = el_line(el); li = el_line(el);
@ -459,15 +466,7 @@ fn_complete(EditLine *el,
* it, unless we do filename completion and the * it, unless we do filename completion and the
* object is a directory. * object is a directory.
*/ */
size_t alen = strlen(matches[0]); el_insertstr(el, (*append_char_function)(matches[0]));
if ((complet_func != filename_completion_function
|| (alen > 0 && (matches[0])[alen - 1] != '/'))
&& append_character) {
char buf[2];
buf[0] = append_character;
buf[1] = '\0';
el_insertstr(el, buf);
}
} else if (what_to_do == '!') { } else if (what_to_do == '!') {
display_matches: display_matches:
/* /*
@ -535,6 +534,6 @@ unsigned char
_el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) _el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
{ {
return (unsigned char)fn_complete(el, NULL, NULL, return (unsigned char)fn_complete(el, NULL, NULL,
break_chars, NULL, ' ', 100, break_chars, NULL, NULL, 100,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: filecomplete.h,v 1.2 2005/05/07 16:28:32 dsl Exp $ */ /* $NetBSD: filecomplete.h,v 1.3 2005/06/10 20:21:00 christos Exp $ */
/*- /*-
* Copyright (c) 1997 The NetBSD Foundation, Inc. * Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -41,11 +41,11 @@
int fn_complete(EditLine *, int fn_complete(EditLine *,
char *(*)(const char *, int), char *(*)(const char *, int),
char **(*)(const char *, int, int), char **(*)(const char *, int, int),
const char *, const char *, char, int, const char *, const char *, const char *(*)(const char *), int,
int *, int *, int *, int *); int *, int *, int *, int *);
void fn_display_match_list(EditLine *, char **, int, int); void fn_display_match_list(EditLine *, char **, int, int);
char *tilde_expand(char *txt); char *tilde_expand(const char *);
char *filename_completion_function(const char *, int); char *filename_completion_function(const char *, int);
#endif #endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: readline.c,v 1.55 2005/05/27 14:01:46 agc Exp $ */ /* $NetBSD: readline.c,v 1.56 2005/06/10 20:21:00 christos Exp $ */
/*- /*-
* Copyright (c) 1997 The NetBSD Foundation, Inc. * Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include "config.h" #include "config.h"
#if !defined(lint) && !defined(SCCSID) #if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: readline.c,v 1.55 2005/05/27 14:01:46 agc Exp $"); __RCSID("$NetBSD: readline.c,v 1.56 2005/06/10 20:21:00 christos Exp $");
#endif /* not lint && not SCCSID */ #endif /* not lint && not SCCSID */
#include <sys/types.h> #include <sys/types.h>
@ -1408,6 +1408,16 @@ rl_display_match_list(char **matches, int len, int max)
fn_display_match_list(e, matches, len, max); fn_display_match_list(e, matches, len, max);
} }
static const char *
/*ARGSUSED*/
_rl_completion_append_character_function(const char *dummy
__attribute__((__unused__)))
{
static char buf[2];
buf[1] = rl_completion_append_character;
return buf;
}
/* /*
* complete word at current point * complete word at current point
@ -1432,7 +1442,7 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
(CPFunction *)rl_completion_entry_function, (CPFunction *)rl_completion_entry_function,
rl_attempted_completion_function, rl_attempted_completion_function,
rl_basic_word_break_characters, rl_special_prefixes, rl_basic_word_break_characters, rl_special_prefixes,
rl_completion_append_character, rl_completion_query_items, _rl_completion_append_character_function, rl_completion_query_items,
&rl_completion_type, &rl_attempted_completion_over, &rl_completion_type, &rl_attempted_completion_over,
&rl_point, &rl_end); &rl_point, &rl_end);
} }