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.
@ -38,7 +38,7 @@
#include "config.h"
#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 */
#include <sys/types.h>
@ -81,7 +81,7 @@ static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
* it's callers's responsibility to free() returned string
*/
char *
tilde_expand(char *txt)
tilde_expand(const char *txt)
{
struct passwd pwres, *pass;
char *temp;
@ -226,27 +226,17 @@ filename_completion_function(const char *text, int state)
}
if (entry) { /* match found */
struct stat stbuf;
const char *isdir = "";
#if defined(__SVR4) || defined(__linux__)
len = strlen(entry->d_name);
#else
len = entry->d_namlen;
#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 */
if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
isdir = "/";
free(temp);
temp = malloc(strlen(dirname) + len + 1 + 1);
temp = malloc(strlen(dirname) + len + 1);
if (temp == NULL)
return NULL;
(void)sprintf(temp, "%s%s%s", dirname, entry->d_name, isdir);
(void)sprintf(temp, "%s%s", dirname, entry->d_name);
} else {
(void)closedir(dir);
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
* non-static for readline.
@ -385,7 +390,7 @@ fn_complete(EditLine *el,
char *(*complet_func)(const char *, int),
char **(*attempted_completion_function)(const char *, int, int),
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)
{
const LineInfo *li;
@ -403,6 +408,8 @@ fn_complete(EditLine *el,
if (!complet_func)
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 */
li = el_line(el);
@ -459,15 +466,7 @@ fn_complete(EditLine *el,
* it, unless we do filename completion and the
* object is a directory.
*/
size_t alen = strlen(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);
}
el_insertstr(el, (*append_char_function)(matches[0]));
} else if (what_to_do == '!') {
display_matches:
/*
@ -535,6 +534,6 @@ unsigned char
_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
{
return (unsigned char)fn_complete(el, NULL, NULL,
break_chars, NULL, ' ', 100,
break_chars, NULL, NULL, 100,
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.
@ -41,11 +41,11 @@
int fn_complete(EditLine *,
char *(*)(const char *, 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 *);
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);
#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.
@ -38,7 +38,7 @@
#include "config.h"
#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 */
#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);
}
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
@ -1432,7 +1442,7 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
(CPFunction *)rl_completion_entry_function,
rl_attempted_completion_function,
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_point, &rl_end);
}