Improve GNU readline compat, patch by Steve Tell in 1997 and 1998

This changeset adds support for:
   * rl_prep_terminal(),
   * rl_deprep_terminal(), both of which are only wrappers to rl_ttyset().
   * rl_getc()

and:
   * (*rl_getc_function), defaults to rl_getc()
   * (*rl_event_hook)
   * (*rl_prep_term_function), defaults to rl_prep_terminal()
   * (*rl_deprep_term_function), defaults to rl_deprep_terminal()

For further details, see http://www.cs.unc.edu/~tell/dist/magic-readline.README

Differences from Steve's commit include: signal safety in rl_getc(), restart
read() on EINTR, and make sure to support "int meta_flag" to rl_prep_terminal()
which is the GNU syntax.  To that end I reused the inverse of rl_meta_chars.
This commit is contained in:
Joachim Nilsson 2010-08-05 01:08:30 +02:00
parent 6a8ecd7e2e
commit 0a75b182b1
3 changed files with 62 additions and 19 deletions

View File

@ -30,14 +30,14 @@ typedef enum {
typedef char* (*rl_complete_func_t)(char*, int*);
typedef int (*rl_list_possib_func_t)(char*, char***);
typedef el_status_t (*el_keymap_func_t)(void);
typedef int (*rl_hook_func_t) (void);
typedef int (*rl_getc_func_t)(void);
typedef void (*rl_voidfunc_t)(void);
typedef void (*rl_vintfunc_t)(int);
/* Display 8-bit chars "as-is" or as `M-x'? Toggle with M-m. (Default:0 - "as-is") */
extern int rl_meta_chars;
/* 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);
@ -59,4 +59,12 @@ extern void add_history(const char *line);
extern int read_history(const char *filename);
extern int write_history(const char *filename);
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);
void rl_prep_terminal(int meta_flag);
void rl_deprep_terminal(void);
int rl_getc(void);
#endif /* __EDITLINE_H__ */

View File

@ -63,6 +63,11 @@ typedef struct {
char **Lines;
} el_hist_t;
rl_getc_func_t rl_getc_function = rl_getc;
rl_hook_func_t rl_event_hook;
rl_vintfunc_t rl_prep_term_function = rl_prep_terminal;
rl_voidfunc_t rl_deprep_term_function = rl_deprep_terminal;
/*
** Globals.
*/
@ -109,6 +114,7 @@ int rl_meta_chars = 0; /* Display 8-bit chars as the actual char(0
char *rl_line_buffer;
const char *rl_prompt;
const char *rl_readline_name;/* Set by calling program, for conditional parsing of ~/.inputrc - Not supported yet! */
FILE *rl_instream;
/* User definable callbacks. */
char **(*rl_attempted_completion_function)(const char *token, int start, int end);
@ -196,11 +202,20 @@ static void tty_push(int c)
el_push_back = c;
}
int rl_getc(void)
{
int r;
char c;
do {
r = read(0, &c, 1);
} while (r == -1 && errno == EINTR);
return r == 1 ? c : EOF;
}
static int tty_get(void)
{
char c;
int r;
tty_flush();
if (el_pushed) {
el_pushed = 0;
@ -208,12 +223,8 @@ static int tty_get(void)
}
if (*el_input)
return *el_input++;
do
{
r = read(0, &c, 1);
} while (r == -1 && errno == EINTR);
return r == 1 ? c : EOF;
return rl_getc_function();
}
#define tty_back() (backspace ? tty_puts(backspace) : tty_put('\b'))
@ -280,6 +291,20 @@ static void tty_info(void)
}
/*
** Glue routines to rl_ttyset()
*/
void rl_prep_terminal(int meta_flag)
{
rl_meta_chars = !meta_flag;
rl_ttyset(0);
}
void rl_deprep_terminal(void)
{
rl_ttyset(1);
}
/*
** Print an array of words in columns.
*/
@ -1104,7 +1129,7 @@ char *readline(const char *prompt)
}
tty_info();
rl_ttyset(0);
rl_prep_term_function(!rl_meta_chars);
hist_add(NILSTR);
ScreenSize = SCREEN_INC;
Screen = malloc(sizeof(char) * ScreenSize);
@ -1129,7 +1154,7 @@ char *readline(const char *prompt)
tty_flush();
}
rl_ttyset(1);
rl_deprep_term_function();
free(Screen);
free(H.Lines[--H.Size]);

View File

@ -43,7 +43,11 @@ void rl_ttyset(int Reset)
new = old;
new.c_lflag &= ~(ECHO | ICANON | ISIG);
new.c_iflag &= ~(ISTRIP | INPCK);
new.c_iflag &= ~INPCK;
if (rl_meta_chars)
new.c_iflag |= ISTRIP;
else
new.c_iflag &= ~ISTRIP;
new.c_cc[VMIN] = 1;
new.c_cc[VTIME] = 0;
if (-1 == tcsetattr(0, TCSADRAIN, &new))
@ -76,7 +80,12 @@ void rl_ttyset(int Reset)
new = old;
new.c_lflag &= ~(ECHO | ICANON | ISIG);
new.c_iflag &= ~(ISTRIP | INPCK);
new.c_iflag &= ~INPCK;
if (rl_meta_chars)
new.c_iflag |= ISTRIP;
else
new.c_iflag &= ~ISTRIP;
new.c_cc[VMIN] = 1;
new.c_cc[VTIME] = 0;
if (-1 == ioctl(0, TCSETAW, &new))
@ -121,9 +130,10 @@ void rl_ttyset(int Reset)
new_sgttyb = old_sgttyb;
new_sgttyb.sg_flags &= ~ECHO;
new_sgttyb.sg_flags |= RAW;
#ifdef PASS8
if (rl_meta_chars)
new_sgttyb.sg_flags &= ~PASS8;
else
new_sgttyb.sg_flags |= PASS8;
#endif
if (-1 == ioctl(0, TIOCSETP, &new_sgttyb))
perror("Failed TIOCSETP");
new_tchars = old_tchars;