Merge branch 'master' into readline-compat-for-fileman

This commit is contained in:
Joachim Nilsson 2010-07-30 03:10:11 +02:00
parent 45bae5b240
commit c0d7a14490
11 changed files with 526 additions and 379 deletions

5
TODO
View File

@ -1,8 +1,11 @@
TODO TODO
* Port "fileman" example from BSD editline * Port "fileman" example from BSD libedit, http://www.thrysoee.dk/editline/
* Add support for rl_bind_key(), currently one needs to "hack" the Map[] * Add support for rl_bind_key(), currently one needs to "hack" the Map[]
* Add support for inhibiting completion: rl_inhibit_completion * Add support for inhibiting completion: rl_inhibit_completion
* Make "char *rl_prompt" globally visible. * Make "char *rl_prompt" globally visible.
* Add support for rl_set_prompt(). * Add support for rl_set_prompt().
* Add support for --enable-utf8 to configure
* Use strcmp(nl_langinfo(CODESET), "UTF-8") to look for utf8 capable terminal.
* Implement simple UTF-8 parser according to http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8

2
configure vendored
View File

@ -11274,7 +11274,7 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS="$saved_cflags" CFLAGS="$saved_cflags"
AM_CFLAGS="-std=gnu99 $inline_cflags -W -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" AM_CFLAGS="-std=gnu99 $inline_cflags -W -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow -Wcast-qual"
### The following magic for determining the location of termcap library is from GNU Texinfo ### The following magic for determining the location of termcap library is from GNU Texinfo

View File

@ -111,7 +111,7 @@ AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),
nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="") nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="")
CFLAGS="$saved_cflags" CFLAGS="$saved_cflags"
AM_CFLAGS="-std=gnu99 $inline_cflags -W -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" AM_CFLAGS="-std=gnu99 $inline_cflags -W -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow -Wcast-qual"
AC_SUBST(AM_CFLAGS) AC_SUBST(AM_CFLAGS)
### The following magic for determining the location of termcap library is from GNU Texinfo ### The following magic for determining the location of termcap library is from GNU Texinfo

View File

@ -84,11 +84,11 @@ int main(int ac __attribute__ ((unused)), char *av[] __attribute__ ((unused)))
char *prompt = "cli> "; char *prompt = "cli> ";
/* Setup callbacks */ /* Setup callbacks */
rl_complete = &my_rl_complete; rl_set_complete_func(&my_rl_complete);
rl_list_possib = &my_rl_list_possib; rl_set_list_possib_func(&my_rl_list_possib);
while ((line = readline(prompt)) != NULL) { while ((line = readline(prompt)) != NULL) {
(void)printf("\t\t\t|%s|\n", line); printf("\t\t\t|%s|\n", line);
free(line); free(line);
} }

View File

@ -33,39 +33,44 @@
#include "editline.h" #include "editline.h"
#ifndef HAVE_PERROR #ifndef HAVE_PERROR
extern int errno;
void perror(char *s) void perror(char *s)
{ {
extern int errno; fprintf(stderr, "%s: error %d\n", s, errno);
(void)fprintf(stderr, "%s: error %d\n", s, errno);
} }
#endif /* !HAVE_PERROR */ #endif /* !HAVE_PERROR */
int main(int argc, char *argv[] __attribute__ ((unused))) int main(int argc, char *argv[] __attribute__ ((unused)))
{ {
char *prompt; int doit;
char *p; char *prompt, *p;
int doit;
doit = argc == 1; doit = argc == 1;
if ((prompt = getenv("TESTPROMPT")) == NULL) if ((prompt = getenv("TESTPROMPT")) == NULL)
prompt = "testit> "; prompt = "testit> ";
while ((p = readline(prompt)) != NULL) { while ((p = readline(prompt)) != NULL) {
(void)printf("\t\t\t|%s|\n", p); printf("\t\t\t|%s|\n", p);
if (doit) { if (doit) {
if (strncmp(p, "cd ", 3) == 0) { if (strncmp(p, "cd ", 3) == 0) {
if (chdir(&p[3]) < 0) { if (chdir(&p[3]) < 0)
perror(&p[3]); perror(&p[3]);
} } else if (system(p) != 0) {
}
else if (system(p) != 0) {
perror(p); perror(p);
} }
} }
add_history(p); add_history(p);
free(p); free(p);
} }
return 0; return 0;
} }
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-basic-offset: 4
* End:
*/

View File

@ -21,12 +21,18 @@
#ifndef __EDITLINE_H__ #ifndef __EDITLINE_H__
#define __EDITLINE_H__ #define __EDITLINE_H__
/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? (Default:1) */ /* Command status codes. */
extern int rl_meta_chars; typedef enum {
CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
} el_status_t;
/* Assign these to get command completion, see cli.c for example usage. */ /* Editline specific types, despite rl_ prefix. From Heimdal project. */
extern char *(*rl_complete) (char *token, int *match); typedef char* (*rl_complete_func_t)(char*, int*);
extern int (*rl_list_possib)(char *token, char ***av); typedef int (*rl_list_possib_func_t)(char*, char***);
typedef el_status_t (*el_keymap_func_t)(void);
/* Display 8-bit chars "as-is" or as `M-x'? Toggle with M-m. (Default:0 - "as-is") */
extern int rl_meta_chars;
/* For compatibility with GNU Readline. */ /* For compatibility with GNU Readline. */
extern char *(*rl_completion_entry_function)(const char *text, int state); extern char *(*rl_completion_entry_function)(const char *text, int state);
@ -35,14 +41,22 @@ extern char *rl_filename_completion_function(const char *text, int state);
extern int rl_attempted_completion_over; extern int rl_attempted_completion_over;
extern char **(*rl_attempted_completion_function)(const char *text, int start, int end); extern char **(*rl_attempted_completion_function)(const char *text, int start, int end);
/* Use these functions to set custom command/file completion, see cli.c for example usage. */
rl_complete_func_t rl_set_complete_func(rl_complete_func_t func);
rl_list_possib_func_t rl_set_list_possib_func(rl_list_possib_func_t func);
/* Editline specific functions. */
void el_bind_key_in_metamap(char c, el_keymap_func_t func);
/* For compatibility with FSF readline. */
extern int rl_point; extern int rl_point;
extern int rl_mark; extern int rl_mark;
extern int rl_end; extern int rl_end;
extern char *rl_line_buffer; extern char *rl_line_buffer;
extern const char *rl_readline_name; extern const char *rl_readline_name;
extern int el_no_echo; /* e.g under emacs, don't echo except prompt */
extern void rl_initialize(void);
extern void rl_reset_terminal(char *p); extern void rl_reset_terminal(char *p);
extern void rl_initialize(void);
extern char *readline(const char *prompt); extern char *readline(const char *prompt);
extern void add_history(char *line); /* OBSOLETE: Made part of readline(). -- kjb */ extern void add_history(char *line); /* OBSOLETE: Made part of readline(). -- kjb */

View File

@ -102,7 +102,7 @@ ESC\ ^H Delete previous word (backspace key) [n]
ESC\ DEL Delete previous word (delete key) [n] ESC\ DEL Delete previous word (delete key) [n]
ESC\ SP Set the mark (space key); see ^X^X and ^Y above ESC\ SP Set the mark (space key); see ^X^X and ^Y above
ESC\ \. Get the last (or [n]'th) word from previous line ESC\ \. Get the last (or [n]'th) word from previous line
ESC\ \? Show possible completions; see below ESC\ ? Show possible completions; see below
ESC\ < Move to start of history ESC\ < Move to start of history
ESC\ > Move to end of history ESC\ > Move to end of history
ESC\ b Move backward a word [n] ESC\ b Move backward a word [n]

View File

@ -23,24 +23,11 @@
#define MAX_TOTAL_MATCHES (256 << sizeof(char *)) #define MAX_TOTAL_MATCHES (256 << sizeof(char *))
#ifndef HAVE_STRDUP /* Wrap strcmp() for qsort() -- weird construct to pass -Wcast-qual */
/* Return an allocated copy of a string. */
char *strdup(const char *p)
{
char *new;
if ((new = NEW(char, strlen(p) + 1)) != NULL)
(void)strcpy(new, p);
return new;
}
#endif
/* Wrap strcmp() for qsort() */
static int compare(const void *p1, const void *p2) static int compare(const void *p1, const void *p2)
{ {
char **v1 = (char **)p1; char *const *v1 = (char *const *)p1;
char **v2 = (char **)p2; char *const *v2 = (char *const *)p2;
return strcmp(*v1, *v2); return strcmp(*v1, *v2);
} }
@ -54,10 +41,10 @@ static int FindMatches(char *dir, char *file, char ***avp)
char *p; char *p;
DIR *dp; DIR *dp;
DIRENTRY *ep; DIRENTRY *ep;
SIZE_T ac; size_t ac;
SIZE_T len; size_t len;
SIZE_T choices; size_t choices;
SIZE_T total; size_t total;
if ((dp = opendir(dir)) == NULL) if ((dp = opendir(dir)) == NULL)
return 0; return 0;
@ -77,25 +64,26 @@ static int FindMatches(char *dir, char *file, char ***avp)
choices++; choices++;
if ((total += strlen(p)) > MAX_TOTAL_MATCHES) { if ((total += strlen(p)) > MAX_TOTAL_MATCHES) {
/* This is a bit too much. */ /* This is a bit too much. */
while (ac > 0) DISPOSE(av[--ac]); while (ac > 0) free(av[--ac]);
continue; continue;
} }
if ((ac % MEM_INC) == 0) { if ((ac % MEM_INC) == 0) {
if ((new = NEW(char*, ac + MEM_INC)) == NULL) { new = malloc(sizeof(char *) * (ac + MEM_INC));
if (!new) {
total = 0; total = 0;
break; break;
} }
if (ac) { if (ac) {
COPYFROMTO(new, av, ac * sizeof (char **)); memcpy(new, av, ac * sizeof(char **));
DISPOSE(av); free(av);
} }
*avp = av = new; *avp = av = new;
} }
if ((av[ac] = strdup(p)) == NULL) { if ((av[ac] = strdup(p)) == NULL) {
if (ac == 0) if (ac == 0)
DISPOSE(av); free(av);
total = 0; total = 0;
break; break;
} }
@ -134,16 +122,15 @@ static int SplitPath(char *path, char **dirpart, char **filepart)
if ((dpart = strdup(DOT)) == NULL) if ((dpart = strdup(DOT)) == NULL)
return -1; return -1;
if ((fpart = strdup(path)) == NULL) { if ((fpart = strdup(path)) == NULL) {
DISPOSE(dpart); free(dpart);
return -1; return -1;
} }
} } else {
else {
if ((dpart = strdup(path)) == NULL) if ((dpart = strdup(path)) == NULL)
return -1; return -1;
dpart[fpart - path + 1] = '\0'; dpart[fpart - path + 1] = '\0';
if ((fpart = strdup(++fpart)) == NULL) { if ((fpart = strdup(fpart + 1)) == NULL) {
DISPOSE(dpart); free(dpart);
return -1; return -1;
} }
} }
@ -153,27 +140,37 @@ static int SplitPath(char *path, char **dirpart, char **filepart)
return 0; return 0;
} }
static rl_complete_func_t el_complete_func = NULL;
/* For compatibility with the Heimdal project. */
rl_complete_func_t rl_set_complete_func(rl_complete_func_t func)
{
rl_complete_func_t old = el_complete_func;
el_complete_func = func;
return old;
}
/* Attempt to complete the pathname, returning an allocated copy. /* Attempt to complete the pathname, returning an allocated copy.
* Fill in *unique if we completed it, or set it to 0 if ambiguous. */ * Fill in *match if we completed it, or set it to 0 if ambiguous. */
char *default_rl_complete(char *pathname, int *unique) char *el_filename_complete(char *pathname, int *match)
{ {
char **av; char **av;
char *dir; char *dir;
char *file; char *file;
char *new; char *new;
char *p; char *p;
SIZE_T ac; size_t ac;
SIZE_T end; size_t end;
SIZE_T i; size_t i;
SIZE_T j; size_t j;
SIZE_T len; size_t len;
if (SplitPath(pathname, &dir, &file) < 0) if (SplitPath(pathname, &dir, &file) < 0)
return NULL; return NULL;
if ((ac = FindMatches(dir, file, &av)) == 0) { if ((ac = FindMatches(dir, file, &av)) == 0) {
DISPOSE(dir); free(dir);
DISPOSE(file); free(file);
return NULL; return NULL;
} }
@ -182,21 +179,21 @@ char *default_rl_complete(char *pathname, int *unique)
len = strlen(file); len = strlen(file);
if (ac == 1) { if (ac == 1) {
/* Exactly one match -- finish it off. */ /* Exactly one match -- finish it off. */
*unique = 1; *match = 1;
j = strlen(av[0]) - len + 2; j = strlen(av[0]) - len + 2;
if ((p = NEW(char, j + 1)) != NULL) { p = malloc(sizeof(char) * (j + 1));
COPYFROMTO(p, av[0] + len, j); if (p) {
if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) { memcpy(p, av[0] + len, j);
(void)strcpy(new, dir); len = strlen(dir) + strlen(av[0]) + 2;
(void)strcat(new, "/"); new = malloc(sizeof(char) * len);
(void)strcat(new, av[0]); if (new) {
snprintf(new, len, "%s/%s", dir, av[0]);
rl_add_slash(new, p); rl_add_slash(new, p);
DISPOSE(new); free(new);
} }
} }
} } else {
else { *match = 0;
*unique = 0;
if (len) { if (len) {
/* Find largest matching substring. */ /* Find largest matching substring. */
for (i = len, end = strlen(av[0]); i < end; i++) for (i = len, end = strlen(av[0]); i < end; i++)
@ -206,8 +203,9 @@ char *default_rl_complete(char *pathname, int *unique)
breakout: breakout:
if (i > len) { if (i > len) {
j = i - len + 1; j = i - len + 1;
if ((p = NEW(char, j)) != NULL) { p = malloc(sizeof(char) * j);
COPYFROMTO(p, av[0] + len, j); if (p) {
memcpy(p, av[0] + len, j);
p[j - 1] = '\0'; p[j - 1] = '\0';
} }
} }
@ -215,17 +213,39 @@ char *default_rl_complete(char *pathname, int *unique)
} }
/* Clean up and return. */ /* Clean up and return. */
DISPOSE(dir); free(dir);
DISPOSE(file); free(file);
for (i = 0; i < ac; i++) for (i = 0; i < ac; i++)
DISPOSE(av[i]); free(av[i]);
DISPOSE(av); free(av);
return p; return p;
} }
/* Return all possible completions. */ char *rl_complete(char *token, int *match)
int default_rl_list_possib(char *pathname, char ***avp) {
if (el_complete_func)
return el_complete_func(token, match);
#ifdef CONFIG_DEFAULT_COMPLETE
return el_filename_complete(token, match);
#else
return NULL;
#endif
}
static rl_list_possib_func_t el_list_possib_func = NULL;
/* For compatibility with the Heimdal project. */
rl_list_possib_func_t rl_set_list_possib_func(rl_list_possib_func_t func)
{
rl_list_possib_func_t old = el_list_possib_func;
el_list_possib_func = func;
return old;
}
/* Default possible completions. */
int el_filename_list_possib(char *pathname, char ***av)
{ {
char *dir; char *dir;
char *file; char *file;
@ -234,13 +254,27 @@ int default_rl_list_possib(char *pathname, char ***avp)
if (SplitPath(pathname, &dir, &file) < 0) if (SplitPath(pathname, &dir, &file) < 0)
return 0; return 0;
ac = FindMatches(dir, file, avp); ac = FindMatches(dir, file, av);
DISPOSE(dir); free(dir);
DISPOSE(file); free(file);
return ac; return ac;
} }
/* Return all possible completions. */
int rl_list_possib(char *token, char ***av)
{
if (el_list_possib_func)
return el_list_possib_func(token, av);
#ifdef CONFIG_DEFAULT_COMPLETE
return el_filename_list_possib(token, av);
#else
return 0;
#endif
}
/** /**
* Local Variables: * Local Variables:
* version-control: t * version-control: t

File diff suppressed because it is too large Load Diff

View File

@ -53,20 +53,9 @@
# include <sys/ioctl.h> # include <sys/ioctl.h>
#endif #endif
#ifndef SIZE_T
#define SIZE_T unsigned int
#endif
typedef unsigned char CHAR;
#define MEM_INC 64 #define MEM_INC 64
#define SCREEN_INC 256 #define SCREEN_INC 256
#define DISPOSE(p) free((char *)(p))
#define NEW(T, c) ((T *)malloc((unsigned int)(sizeof (T) * (c))))
#define RENEW(p, T, c) (p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c))))
#define COPYFROMTO(new, p, len) (void)memcpy((char *)(new), (char *)(p), (int)(len))
/* /*
** Variables and routines internal to this package. ** Variables and routines internal to this package.
*/ */
@ -78,12 +67,10 @@ extern int rl_quit;
#ifdef CONFIG_SIGSTOP #ifdef CONFIG_SIGSTOP
extern int rl_susp; extern int rl_susp;
#endif #endif
#ifdef CONFIG_DEFAULT_COMPLETE void rl_ttyset(int Reset);
extern char *default_rl_complete(char *pathname, int *unique); void rl_add_slash(char *path, char *p);
extern int default_rl_list_possib(char *pathname, char ***avp); char *rl_complete(char *token, int *match);
#endif int rl_list_possib(char *token, char ***av);
extern void rl_ttyset(int Reset);
extern void rl_add_slash(char *path, char *p);
#ifndef HAVE_STDLIB_H #ifndef HAVE_STDLIB_H
extern char *getenv(const char *name); extern char *getenv(const char *name);

View File

@ -142,6 +142,21 @@ void rl_ttyset(int Reset)
#error Unsupported platform, missing tcgetattr(), termio.h and sgtty.h #error Unsupported platform, missing tcgetattr(), termio.h and sgtty.h
#endif /* Neither HAVE_SGTTY_H, HAVE_TERMIO_H or HAVE_TCGETATTR */ #endif /* Neither HAVE_SGTTY_H, HAVE_TERMIO_H or HAVE_TCGETATTR */
#ifndef HAVE_STRDUP
/* Return an allocated copy of a string. */
char *strdup(const char *p)
{
char *new = malloc(sizeof(char) * strlen(p));
if (new) {
strcpy(new, p);
return new;
}
return NULL;
}
#endif
void rl_add_slash(char *path, char *p) void rl_add_slash(char *path, char *p)
{ {
struct stat Sb; struct stat Sb;