📄 misc.c
字号:
/* misc.c -- miscellaneous bindable readline functions. *//* Copyright (C) 1987-2004 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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */#define READLINE_LIBRARY#if defined (HAVE_CONFIG_H)# include <config.h>#endif#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 */#if defined (HAVE_LOCALE_H)# include <locale.h>#endif#include <stdio.h>/* System-specific feature definitions and include files. */#include "rldefs.h"#include "rlmbutil.h"/* Some standard library routines. */#include "readline.h"#include "history.h"#include "rlprivate.h"#include "rlshell.h"#include "xmalloc.h"static int rl_digit_loop PARAMS((void));static void _rl_history_set_point PARAMS((void));/* Forward declarations used in this file */void _rl_free_history_entry PARAMS((HIST_ENTRY *));/* If non-zero, rl_get_previous_history and rl_get_next_history attempt to preserve the value of rl_point from line to line. */int _rl_history_preserve_point = 0;/* Saved target point for when _rl_history_preserve_point is set. Special value of -1 means that point is at the end of the line. */int _rl_history_saved_point = -1;/* **************************************************************** *//* *//* Numeric Arguments *//* *//* **************************************************************** *//* Handle C-u style numeric args, as well as M--, and M-digits. */static intrl_digit_loop (){ int key, c, sawminus, sawdigits; rl_save_prompt (); RL_SETSTATE(RL_STATE_NUMERICARG); sawminus = sawdigits = 0; while (1) { if (rl_numeric_arg > 1000000) { sawdigits = rl_explicit_arg = rl_numeric_arg = 0; rl_ding (); rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); return 1; } rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); RL_SETSTATE(RL_STATE_MOREINPUT); key = c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); if (c < 0) { _rl_abort_internal (); return -1; } /* If we see a key bound to `universal-argument' after seeing digits, it ends the argument but is otherwise ignored. */ if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { if (sawdigits == 0) { rl_numeric_arg *= 4; continue; } else { RL_SETSTATE(RL_STATE_MOREINPUT); key = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); return (_rl_dispatch (key, _rl_keymap)); } } c = UNMETA (c); if (_rl_digit_p (c)) { rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; sawdigits = rl_explicit_arg = 1; } else if (c == '-' && rl_explicit_arg == 0) { rl_numeric_arg = sawminus = 1; rl_arg_sign = -1; } else { /* Make M-- command equivalent to M--1 command. */ if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) rl_explicit_arg = 1; rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); return (_rl_dispatch (key, _rl_keymap)); } } /*NOTREACHED*/}/* Add the current digit to the argument in progress. */intrl_digit_argument (ignore, key) int ignore, key;{ rl_execute_next (key); return (rl_digit_loop ());}/* What to do when you abort reading an argument. */intrl_discard_argument (){ rl_ding (); rl_clear_message (); _rl_init_argument (); return 0;}/* Create a default argument. */int_rl_init_argument (){ rl_numeric_arg = rl_arg_sign = 1; rl_explicit_arg = 0; return 0;}/* C-u, universal argument. Multiply the current argument by 4. Read a key. If the key has nothing to do with arguments, then dispatch on it. If the key is the abort character then abort. */intrl_universal_argument (count, key) int count, key;{ rl_numeric_arg *= 4; return (rl_digit_loop ());}/* **************************************************************** *//* *//* History Utilities *//* *//* **************************************************************** *//* We already have a history library, and that is what we use to control the history features of readline. This is our local interface to the history mechanism. *//* While we are editing the history, this is the saved version of the original line. */HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;/* Set the history pointer back to the last entry in the history. */void_rl_start_using_history (){ using_history (); if (_rl_saved_line_for_history) _rl_free_history_entry (_rl_saved_line_for_history); _rl_saved_line_for_history = (HIST_ENTRY *)NULL;}/* Free the contents (and containing structure) of a HIST_ENTRY. */void_rl_free_history_entry (entry) HIST_ENTRY *entry;{ if (entry == 0) return; if (entry->line) free (entry->line); free (entry);}/* Perhaps put back the current line if it has changed. */intrl_maybe_replace_line (){ HIST_ENTRY *temp; temp = current_history (); /* If the current line has changed, save the changes. */ if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) { temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); free (temp->line); free (temp); } return 0;}/* Restore the _rl_saved_line_for_history if there is one. */intrl_maybe_unsave_line (){ if (_rl_saved_line_for_history) { /* Can't call with `1' because rl_undo_list might point to an undo list from a history entry, as in rl_replace_from_history() below. */ rl_replace_line (_rl_saved_line_for_history->line, 0); rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data; _rl_free_history_entry (_rl_saved_line_for_history); _rl_saved_line_for_history = (HIST_ENTRY *)NULL; rl_point = rl_end; /* rl_replace_line sets rl_end */ } else rl_ding (); return 0;}/* Save the current line in _rl_saved_line_for_history. */intrl_maybe_save_line (){ if (_rl_saved_line_for_history == 0) { _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); _rl_saved_line_for_history->line = savestring (rl_line_buffer); _rl_saved_line_for_history->data = (char *)rl_undo_list; } else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0) { free (_rl_saved_line_for_history->line); _rl_saved_line_for_history->line = savestring (rl_line_buffer); _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */ } return 0;}int_rl_free_saved_history_line (){ if (_rl_saved_line_for_history) { _rl_free_history_entry (_rl_saved_line_for_history); _rl_saved_line_for_history = (HIST_ENTRY *)NULL; } return 0;}static void_rl_history_set_point (){ rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1) ? _rl_history_saved_point : rl_end; if (rl_point > rl_end) rl_point = rl_end;#if defined (VI_MODE) if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap) rl_point = 0;#endif /* VI_MODE */ if (rl_editing_mode == emacs_mode) rl_mark = (rl_point == rl_end ? 0 : rl_end);}voidrl_replace_from_history (entry, flags) HIST_ENTRY *entry; int flags; /* currently unused */{ /* Can't call with `1' because rl_undo_list might point to an undo list from a history entry, just like we're setting up here. */ rl_replace_line (entry->line, 0); rl_undo_list = (UNDO_LIST *)entry->data; rl_point = rl_end; rl_mark = 0;#if defined (VI_MODE) if (rl_editing_mode == vi_mode) { rl_point = 0; rl_mark = rl_end; }#endif} /* **************************************************************** *//* *//* History Commands *//* *//* **************************************************************** *//* Meta-< goes to the start of the history. */intrl_beginning_of_history (count, key) int count, key;{ return (rl_get_previous_history (1 + where_history (), key));}/* Meta-> goes to the end of the history. (The current line). */intrl_end_of_history (count, key) int count, key;{ rl_maybe_replace_line (); using_history (); rl_maybe_unsave_line (); return 0;}/* Move down to the next history line. */intrl_get_next_history (count, key) int count, key;{ HIST_ENTRY *temp; if (count < 0) return (rl_get_previous_history (-count, key)); if (count == 0) return 0; rl_maybe_replace_line (); /* either not saved by rl_newline or at end of line, so set appropriately. */ if (_rl_history_saved_point == -1 && (rl_point || rl_end)) _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; temp = (HIST_ENTRY *)NULL; while (count) { temp = next_history (); if (!temp) break; --count; } if (temp == 0) rl_maybe_unsave_line (); else { rl_replace_from_history (temp, 0); _rl_history_set_point (); } return 0;}/* Get the previous item out of our interactive history, making it the current line. If there is no previous history, just ding. */intrl_get_previous_history (count, key) int count, key;{ HIST_ENTRY *old_temp, *temp; if (count < 0) return (rl_get_next_history (-count, key)); if (count == 0) return 0; /* either not saved by rl_newline or at end of line, so set appropriately. */ if (_rl_history_saved_point == -1 && (rl_point || rl_end)) _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; /* If we don't have a line saved, then save this one. */ rl_maybe_save_line (); /* If the current line has changed, save the changes. */ rl_maybe_replace_line (); temp = old_temp = (HIST_ENTRY *)NULL; while (count) { temp = previous_history (); if (temp == 0) break; old_temp = temp; --count; } /* If there was a large argument, and we moved back to the start of the history, that is not an error. So use the last value found. */ if (!temp && old_temp) temp = old_temp; if (temp == 0) rl_ding (); else { rl_replace_from_history (temp, 0); _rl_history_set_point (); } return 0;}/* **************************************************************** *//* *//* Editing Modes *//* *//* **************************************************************** *//* How to toggle back and forth between editing modes. */intrl_vi_editing_mode (count, key) int count, key;{#if defined (VI_MODE) _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ rl_editing_mode = vi_mode; rl_vi_insertion_mode (1, key);#endif /* VI_MODE */ return 0;}intrl_emacs_editing_mode (count, key) int count, key;{ rl_editing_mode = emacs_mode; _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ _rl_keymap = emacs_standard_keymap; return 0;}/* Function for the rest of the library to use to set insert/overwrite mode. */void_rl_set_insert_mode (im, force) int im, force;{#ifdef CURSOR_MODE _rl_set_cursor (im, force);#endif rl_insert_mode = im;}/* Toggle overwrite mode. A positive explicit argument selects overwrite mode. A negative or zero explicit argument selects insert mode. */intrl_overwrite_mode (count, key) int count, key;{ if (rl_explicit_arg == 0) _rl_set_insert_mode (rl_insert_mode ^ 1, 0); else if (count > 0) _rl_set_insert_mode (RL_IM_OVERWRITE, 0); else _rl_set_insert_mode (RL_IM_INSERT, 0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -