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:
parent
0320b64715
commit
3cfbfdb2ef
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user