📄 readline.c
字号:
/* readline.c -- a general facility for reading lines of input with emacs style editing and completion. *//* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. The GNU Readline Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. The GNU Readline Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is often shipped with GNU software, and is generally kept in a file called COPYING or LICENSE. If you do not have a copy of the license, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#define READLINE_LIBRARY#include <stdio.h>#include <sys/types.h>#include <fcntl.h>#if !defined (NO_SYS_FILE)# include <sys/file.h>#endif /* !NO_SYS_FILE */#include <signal.h>#if defined (HAVE_UNISTD_H)# include <unistd.h>#endif /* HAVE_UNISTD_H */#if defined (HAVE_STDLIB_H)# include <stdlib.h>#else# include "ansi_stdlib.h"#endif /* HAVE_STDLIB_H */#include <errno.h>/* Not all systems declare ERRNO in errno.h... and some systems #define it! */#if !defined (errno)extern int errno;#endif /* !errno */#include <setjmp.h>#include "posixstat.h"/* System-specific feature definitions and include files. */#include "rldefs.h"#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4))# include <sys/ioctl.h>#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS *//* Some standard library routines. */#include "readline.h"#include "history.h"/* NOTE: Functions and variables prefixed with `_rl_' are pseudo-global: they are global so they can be shared between files in the readline library, but are not intended to be visible to readline callers. *//* Functions imported from other files in the library. */extern char *tgetstr ();extern void rl_prep_terminal (), rl_deprep_terminal ();extern void _rl_bind_if_unbound ();/* External redisplay functions and variables from display.c */extern void _rl_move_vert ();extern void _rl_update_final ();extern void _rl_erase_at_end_of_line ();extern void _rl_move_cursor_relative ();extern int _rl_vis_botlin;extern int _rl_last_c_pos;extern int _rl_horizontal_scroll_mode;extern int rl_display_fixed;extern char *rl_display_prompt;/* Variables imported from complete.c. */extern char *rl_completer_word_break_characters;extern char *rl_basic_word_break_characters;extern int rl_completion_query_items;extern int rl_complete_with_tilde_expansion;#if defined (VI_MODE)extern void _rl_vi_set_last ();extern void _rl_vi_reset_last ();extern void _rl_vi_done_inserting ();#endif /* VI_MODE *//* Forward declarations used in this file. */void _rl_free_history_entry ();int _rl_dispatch ();void _rl_set_screen_size ();int _rl_output_character_function ();static char *readline_internal ();static void readline_initialize_everything ();static int init_terminal_io ();static void start_using_history ();static void bind_arrow_keys ();#if !defined (__GO32__)static void readline_default_bindings ();#endif /* !__GO32__ */#if defined (__GO32__)# include <sys/pc.h># undef HANDLE_SIGNALS#endif /* __GO32__ */#if defined (STATIC_MALLOC)static char *xmalloc (), *xrealloc ();#elseextern char *xmalloc (), *xrealloc ();#endif /* STATIC_MALLOC *//* **************************************************************** *//* *//* Line editing input utility *//* *//* **************************************************************** */static char *LibraryVersion = "2.0";/* A pointer to the keymap that is currently in use. By default, it is the standard emacs keymap. */Keymap _rl_keymap = emacs_standard_keymap;/* The current style of editing. */int rl_editing_mode = emacs_mode;/* Non-zero if the previous command was a kill command. */static int last_command_was_kill = 0;/* The current value of the numeric argument specified by the user. */int rl_numeric_arg = 1;/* Non-zero if an argument was typed. */int rl_explicit_arg = 0;/* Temporary value used while generating the argument. */int rl_arg_sign = 1;/* Non-zero means we have been called at least once before. */static int rl_initialized = 0;/* If non-zero, this program is running in an EMACS buffer. */static int running_in_emacs = 0;/* The current offset in the current input line. */int rl_point;/* Mark in the current input line. */int rl_mark;/* Length of the current input line. */int rl_end;/* Make this non-zero to return the current input_line. */int rl_done;/* The last function executed by readline. */Function *rl_last_func = (Function *)NULL;/* Top level environment for readline_internal (). */static jmp_buf readline_top_level;/* The streams we interact with. */static FILE *in_stream, *out_stream;/* The names of the streams that we do input and output to. */FILE *rl_instream = (FILE *)NULL;FILE *rl_outstream = (FILE *)NULL;/* Non-zero means echo characters as they are read. */int readline_echoing_p = 1;/* Current prompt. */char *rl_prompt;int rl_visible_prompt_length = 0;/* The number of characters read in order to type this complete command. */int rl_key_sequence_length = 0;/* If non-zero, then this is the address of a function to call just before readline_internal () prints the first prompt. */Function *rl_startup_hook = (Function *)NULL;/* What we use internally. You should always refer to RL_LINE_BUFFER. */static char *the_line;/* The character that can generate an EOF. Really read from the terminal driver... just defaulted here. */int _rl_eof_char = CTRL ('D');/* Non-zero makes this the next keystroke to read. */int rl_pending_input = 0;/* Pointer to a useful terminal name. */char *rl_terminal_name = (char *)NULL;/* Non-zero means to always use horizontal scrolling in line display. */int _rl_horizontal_scroll_mode = 0;/* Non-zero means to display an asterisk at the starts of history lines which have been modified. */int _rl_mark_modified_lines = 0; /* The style of `bell' notification preferred. This can be set to NO_BELL, AUDIBLE_BELL, or VISIBLE_BELL. */int _rl_bell_preference = AUDIBLE_BELL; /* Line buffer and maintenence. */char *rl_line_buffer = (char *)NULL;int rl_line_buffer_len = 0;#define DEFAULT_BUFFER_SIZE 256/* Forward declarations used by the display and termcap code. */int term_xn;int screenwidth, screenheight, screenchars;/* **************************************************************** *//* *//* `Forward' declarations *//* *//* **************************************************************** *//* Non-zero means do not parse any lines other than comments and parser directives. */unsigned char _rl_parsing_conditionalized_out = 0;/* Non-zero means to save keys that we dispatch on in a kbd macro. */static int defining_kbd_macro = 0;/* Non-zero means to convert characters with the meta bit set to escape-prefixed characters so we can indirect through emacs_meta_keymap or vi_escape_keymap. */int _rl_convert_meta_chars_to_ascii = 1;/* Non-zero means to output characters with the meta bit set directly rather than as a meta-prefixed escape sequence. */int _rl_output_meta_chars = 0;/* Non-zero tells rl_delete_text and rl_insert_text to not add to the undo list. */static int doing_an_undo = 0;/* **************************************************************** *//* *//* Top Level Functions *//* *//* **************************************************************** *//* Non-zero means treat 0200 bit in terminal input as Meta bit. */int _rl_meta_flag = 0; /* Forward declaration *//* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. A return value of NULL means that EOF was encountered. */char *readline (prompt) char *prompt;{ char *value; rl_prompt = prompt; /* If we are at EOF return a NULL string. */ if (rl_pending_input == EOF) { rl_pending_input = 0; return ((char *)NULL); } rl_visible_prompt_length = rl_expand_prompt (rl_prompt); rl_initialize (); rl_prep_terminal (_rl_meta_flag);#if defined (HANDLE_SIGNALS) rl_set_signals ();#endif value = readline_internal (); rl_deprep_terminal ();#if defined (HANDLE_SIGNALS) rl_clear_signals ();#endif return (value);}/* Read a line of input from the global rl_instream, doing output on the global rl_outstream. If rl_prompt is non-null, then that is our prompt. */static char *readline_internal (){ int lastc, c, eof_found; in_stream = rl_instream; out_stream = rl_outstream; lastc = -1; eof_found = 0; if (rl_startup_hook) (*rl_startup_hook) (); if (!readline_echoing_p) { if (rl_prompt) { fprintf (out_stream, "%s", rl_prompt); fflush (out_stream); } } else { rl_on_new_line (); rl_redisplay ();#if defined (VI_MODE) if (rl_editing_mode == vi_mode) rl_vi_insertion_mode ();#endif /* VI_MODE */ } while (!rl_done) { int lk = last_command_was_kill; int code; code = setjmp (readline_top_level); if (code) rl_redisplay (); if (!rl_pending_input) { /* Then initialize the argument and number of keys read. */ rl_init_argument (); rl_key_sequence_length = 0; } c = rl_read_key (); /* EOF typed to a non-blank line is a <NL>. */ if (c == EOF && rl_end) c = NEWLINE; /* The character _rl_eof_char typed to blank line, and not as the previous character is interpreted as EOF. */ if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) { eof_found = 1; break; } lastc = c; _rl_dispatch (c, _rl_keymap); /* If there was no change in last_command_was_kill, then no kill has taken place. Note that if input is pending we are reading a prefix command, so nothing has changed yet. */ if (!rl_pending_input) { if (lk == last_command_was_kill) last_command_was_kill = 0; }#if defined (VI_MODE) /* In vi mode, when you exit insert mode, the cursor moves back over the previous character. We explicitly check for that here. */ if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) rl_vi_check ();#endif /* VI_MODE */ if (!rl_done) rl_redisplay (); } /* Restore the original of this history line, iff the line that we are editing was originally in the history, AND the line has changed. */ { HIST_ENTRY *entry = current_history (); if (entry && rl_undo_list) { char *temp = savestring (the_line); rl_revert_line (); entry = replace_history_entry (where_history (), the_line, (HIST_ENTRY *)NULL); _rl_free_history_entry (entry); strcpy (the_line, temp); free (temp); } } /* At any rate, it is highly likely that this line has an undo list. Get rid of it now. */ if (rl_undo_list) free_undo_list (); if (eof_found) return (char *)NULL; else return (savestring (the_line));}/* **************************************************************** *//* *//* Character Input Buffering *//* *//* **************************************************************** */static int pop_index = 0, push_index = 0, ibuffer_len = 511;static unsigned char ibuffer[512];/* Non-null means it is a pointer to a function to run while waiting for character input. */Function *rl_event_hook = (Function *)NULL;#define any_typein (push_index != pop_index)/* Add KEY to the buffer of characters to be read. */rl_stuff_char (key) int key;{ if (key == EOF) { key = NEWLINE; rl_pending_input = EOF; } ibuffer[push_index++] = key; if (push_index >= ibuffer_len) push_index = 0; return push_index;}/* Return the amount of space available in the buffer for stuffing characters. */intibuffer_space (){ if (pop_index > push_index) return (pop_index - push_index); else return (ibuffer_len - (push_index - pop_index));}/* Get a key from the buffer of characters to be read. Return the key in KEY. Result is KEY if there was a key, or 0 if there wasn't. */intrl_get_char (key) int *key;{ if (push_index == pop_index) return (0); *key = ibuffer[pop_index++]; if (pop_index >= ibuffer_len) pop_index = 0; return (1);}/* Stuff KEY into the *front* of the input buffer. Returns non-zero if successful, zero if there is no space left in the buffer. */intrl_unget_char (key) int key;{ if (ibuffer_space ()) { pop_index--; if (pop_index < 0) pop_index = ibuffer_len - 1; ibuffer[pop_index] = key; return (1); } return (0);}/* If a character is available to be read, then read it and stuff it into IBUFFER. Otherwise, just return. */voidrl_gather_tyi (){#if defined (__GO32__) char input; if (isatty (0)) { int i = rl_getc (); if (i != EOF) rl_stuff_char (i); } else if (kbhit () && ibuffer_space ()) rl_stuff_char (getkey ());#else /* !__GO32__ */ int tty = fileno (in_stream); register int tem, result = -1; int chars_avail; char input;#if defined (FIONREAD) result = ioctl (tty, FIONREAD, &chars_avail);#endif#if defined (O_NDELAY) if (result == -1) { int flags; flags = fcntl (tty, F_GETFL, 0); fcntl (tty, F_SETFL, (flags | O_NDELAY)); chars_avail = read (tty, &input, 1); fcntl (tty, F_SETFL, flags); if (chars_avail == -1 && errno == EAGAIN) return; }#endif /* O_NDELAY */ /* If there's nothing available, don't waste time trying to read something. */ if (chars_avail == 0) return; tem = ibuffer_space (); if (chars_avail > tem) chars_avail = tem; /* One cannot read all of the available input. I can only read a single character at a time, or else programs which require input can be thwarted. If the buffer is larger than one character, I lose. Damn! */ if (tem < ibuffer_len) chars_avail = 0; if (result != -1) { while (chars_avail--) rl_stuff_char (rl_getc (in_stream)); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -