Programming with GNU Readline
时间:2006-09-23 来源:linxh
This chapter describes the interface between the GNU Readline Library and other programs. If you are a programmer, and you wish to include the features found in GNU Readline such as completion, line editing, and interactive history manipulation in your own programs, this section is for you.
1 Basic Behavior
Many programs provide a command line interface, such as mail, ftp, and sh. For such programs, the default behaviour of Readline is sufficient[充分的, 足够的]. This section describes how to use Readline in the simplest way possible, perhaps to replace calls in your code to gets() or fgets().
The function readline() prints a prompt prompt and then reads and returns a single line of text from the user. If prompt is NULL or the empty string, no prompt is displayed. The line readline returns is allocated with malloc(); the caller should free() the line when it has finished with it. The declaration for readline in ANSI C is
char *readline (const char *prompt); |
char *line = readline ("Enter a line: "); |
If readline encounters an EOF while reading the line, and the line is empty at that point, then (char *)NULL is returned. Otherwise, the line is ended just as if a newline had been typed.
If you want the user to be able to get at the line later, (with C-p for example), you must call add_history() to save the line away in a history list of such lines.
add_history (line); |
It is preferable to avoid saving empty lines on the history list, since users rarely have a burning need to reuse a blank line. Here is a function which usefully replaces the standard gets() library function, and has the advantage of no static buffer to overflow:
/* A static variable for holding the line. */ static char *line_read = (char *)NULL; /* Read a string, and return a pointer to it. Returns NULL on EOF. */ char * rl_gets () { /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline (""); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) add_history (line_read); return (line_read); } |
This function gives the user the default behaviour of TAB completion: completion on file names. If you do not want Readline to complete on filenames, you can change the binding of the TAB key with rl_bind_key().
int rl_bind_key (int key, rl_command_func_t *function); |
rl_bind_key() takes two arguments: key is the character that you want to bind, and function is the address of the function to call when key is pressed. Binding TAB to rl_insert() makes TAB insert itself. rl_bind_key() returns non-zero if key is not a valid ASCII character code (between 0 and 255).
Thus, to disable the default TAB behavior, the following suffices:
rl_bind_key ('\t', rl_insert); |
This code should be executed once at the start of your program; you might write a function called initialize_readline() which performs this and other desired initializations, such as installing custom completers .
2 Custom Functions
Readline provides many functions for manipulating the text of the line, but it isn't possible to anticipate the needs of all programs. This section describes the various functions and variables defined within the Readline library which allow a user program to add customized functionality to Readline.
Before declaring any functions that customize Readline's behavior, or using any functionality Readline provides in other code, an application writer should include the file <readline/readline.h> in any file that uses Readline's features. Since some of the definitions in readline.h use the stdio library, the file <stdio.h> should be included before readline.h.
readline.h defines a C preprocessor variable that should be treated as an integer, RL_READLINE_VERSION, which may be used to conditionally compile application code depending on the installed Readline version. The value is a hexadecimal encoding of the major and minor version numbers of the library, of the form 0xMMmm. MM is the two-digit major version number; mm is the two-digit minor version number. For Readline 4.2, for example, the value of RL_READLINE_VERSION would be 0x0402.
2.1 Readline Typedefs
For readabilty, we declare a number of new object types, all pointers to functions.
The reason for declaring these new types is to make it easier to write code describing pointers to C functions with appropriately prototyped arguments and return values.
For instance, say we want to declare a variable func as a pointer to a function which takes two int arguments and returns an int (this is the type of all of the Readline bindable functions). Instead of the classic C declaration
int (*func)();
or the ANSI-C style declaration
int (*func)(int, int);
we may write
rl_command_func_t *func;
The full list of function pointer types available is
typedef int rl_command_func_t (int, int);
typedef char *rl_compentry_func_t (const char *, int); typedef char **rl_completion_func_t (const char *, int, int); typedef char *rl_quote_func_t (char *, int, char *); typedef char *rl_dequote_func_t (char *, int); typedef int rl_compignore_func_t (char **); typedef void rl_compdisp_func_t (char **, int, int); typedef int rl_hook_func_t (void); typedef int rl_getc_func_t (FILE *); typedef int rl_linebuf_func_t (char *, int); typedef int rl_intfunc_t (int); #define rl_ivoidfunc_t rl_hook_func_t typedef int rl_icpfunc_t (char *); typedef int rl_icppfunc_t (char **); typedef void rl_voidfunc_t (void); typedef void rl_vintfunc_t (int); typedef void rl_vcpfunc_t (char *); typedef void rl_vcppfunc_t (char **);
2.2 Writing a New Function
In order to write new functions for Readline, you need to know the calling conventions for keyboard-invoked functions, and the names of the variables that describe the current state of the line read so far.
The calling sequence for a command foo looks like
foo (int count, int key) |
where count is the numeric argument (or 1 if defaulted) and key is the key that invoked this function.
It is completely up to the function as to what should be done with the numeric argument. Some functions use it as a repeat count, some as a flag, and others to choose alternate behavior (refreshing the current line as opposed to refreshing the screen, for example). Some choose to ignore it. In general, if a function uses the numeric argument as a repeat count, it should be able to do something useful with both negative and positive arguments. At the very least, it should be aware that it can be passed a negative argument.
3 Readline Variables
These variables are available to function writers.
Variable: char * rl_line_buffer This is the line gathered so far. You are welcome to modify the contents of the line, The function rl_extend_line_buffer is available to increase the memory allocated to rl_line_buffer.
Variable: int rl_point The offset of the current cursor position in rl_line_buffer (the point).
Variable: int rl_end The number of characters present in rl_line_buffer. When rl_point is at the end of the line, rl_point and rl_end are equal.
Variable: int rl_mark The mark (saved position) in the current line. If set, the mark and point define a region.
Variable: int rl_done Setting this to a non-zero value causes Readline to return the current line immediately.
Variable: int rl_num_chars_to_read Setting this to a positive value before calling readline() causes Readline to return after accepting that many characters, rather than reading up to a character bound to accept-line.
Variable: int rl_pending_input Setting this to a value makes it the next keystroke read. This is a way to stuff a single character into the input stream.
Variable: int rl_dispatching Set to a non-zero value if a function is being called from a key binding; zero otherwise. Application functions can test this to discover whether they were called directly or by Readline's dispatching mechanism.
Variable: int rl_erase_empty_line Setting this to a non-zero value causes Readline to completely erase the current line, including any prompt, any time a newline is typed as the only character on an otherwise-empty line. The cursor is moved to the beginning of the newly-blank line.
Variable: char * rl_prompt The prompt Readline uses. This is set from the argument to readline(), and should not be assigned to directly. The rl_set_prompt() function. may be used to modify the prompt string after calling readline().
Variable: int rl_already_prompted If an application wishes to display the prompt itself, rather than have Readline do it the first time readline() is called, it should set this variable to a non-zero value after displaying the prompt. The prompt must also be passed as the argument to readline() so the redisplay functions can update the display properly. The calling application is responsible for managing the value; Readline never sets it.
Variable: const char * rl_library_version The version number of this revision of the library.
Variable: int rl_readline_version An integer encoding the current version of the library. The encoding is of the form 0xMMmm, where MM is the two-digit major version number, and mm is the two-digit minor version number. For example, for Readline-4.2, rl_readline_version would have the value 0x0402.
Variable: int rl_gnu_readline_p Always set to 1, denoting that this is GNU readline rather than some emulation.
Variable: const char * rl_terminal_name The terminal type, used for initialization. If not set by the application, Readline sets this to the value of the TERM environment variable the first time it is called.
Variable: const char * rl_readline_name This variable is set to a unique name by each application using Readline. The value allows conditional parsing of the inputrc file .
Variable: FILE * rl_instream The stdio stream from which Readline reads input.
Variable: FILE * rl_outstream The stdio stream to which Readline performs output.
Variable: rl_command_func_t * rl_last_func The address of the last command function Readline executed. May be used to test whether or not a function is being executed twice in succession, for example.
Variable: rl_hook_func_t * rl_startup_hook If non-zero, this is the address of a function to call just before readline prints the first prompt.
Variable: rl_hook_func_t * rl_pre_input_hook If non-zero, this is the address of a function to call after the first prompt has been printed and just before readline starts reading input characters.
Variable: rl_hook_func_t * rl_event_hook If non-zero, this is the address of a function to call periodically when Readline is waiting for terminal input. By default, this will be called at most ten times a second if there is no keyboard input.
Variable: rl_getc_func_t * rl_getc_function If non-zero, Readline will call indirectly through this pointer to get a character from the input stream. By default, it is set to rl_getc, the default Readline character input function .
Variable: rl_voidfunc_t * rl_redisplay_function If non-zero, Readline will call indirectly through this pointer to update the display with the current contents of the editing buffer. By default, it is set to rl_redisplay, the default Readline redisplay function.
Variable: rl_vintfunc_t * rl_prep_term_function If non-zero, Readline will call indirectly through this pointer to initialize the terminal. The function takes a single argument, an int flag that says whether or not to use eight-bit characters. By default, this is set to rl_prep_terminal.
Variable: rl_voidfunc_t * rl_deprep_term_function If non-zero, Readline will call indirectly through this pointer to reset the terminal. This function should undo the effects of rl_prep_term_function. By default, this is set to rl_deprep_terminal.
Variable: Keymap rl_executing_keymap This variable is set to the keymap in which the currently executing readline function was found.
Variable: Keymap rl_binding_keymap This variable is set to the keymap in which the last key binding occurred.
Variable: char * rl_executing_macro This variable is set to the text of any currently-executing macro.
Variable: int rl_readline_state A variable with bit values that encapsulate the current Readline state. A bit is set with the RL_SETSTATE macro, and unset with the RL_UNSETSTATE macro. Use the RL_ISSTATE macro to test whether a particular state bit is set. Current state bits include:
RL_STATE_NONE Readline has not yet been called, nor has it begun to intialize. RL_STATE_INITIALIZING Readline is initializing its internal data structures. RL_STATE_INITIALIZED Readline has completed its initialization. RL_STATE_TERMPREPPED Readline has modified the terminal modes to do its own input and redisplay. RL_STATE_READCMD Readline is reading a command from the keyboard. RL_STATE_METANEXT Readline is reading more input after reading the meta-prefix character. RL_STATE_DISPATCHING Readline is dispatching to a command. RL_STATE_MOREINPUT Readline is reading more input while executing an editing command. RL_STATE_ISEARCH Readline is performing an incremental history search. RL_STATE_NSEARCH Readline is performing a non-incremental history search. RL_STATE_SEARCH Readline is searching backward or forward through the history for a string. RL_STATE_NUMERICARG Readline is reading a numeric argument. RL_STATE_MACROINPUT Readline is currently getting its input from a previously-defined keyboard macro. RL_STATE_MACRODEF Readline is currently reading characters defining a keyboard macro. RL_STATE_OVERWRITE Readline is in overwrite mode. RL_STATE_COMPLETING Readline is performing word completion. RL_STATE_SIGHANDLER Readline is currently executing the readline signal handler. RL_STATE_UNDOING Readline is performing an undo. RL_STATE_DONE Readline has read a key sequence bound to accept-line and is about to return the line to the caller.
Variable: int rl_explicit_arg Set to a non-zero value if an explicit numeric argument was specified by the user. Only valid in a bindable command function.
Variable: int rl_numeric_arg Set to the value of any numeric argument explicitly specified by the user before executing the current Readline function. Only valid in a bindable command function.
Variable: int rl_editing_mode Set to a value denoting Readline's current editing mode. A value of 1 means Readline is currently in emacs mode; 0 means that vi mode is active.
|