⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vi_mode.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi_mode.c -- A vi emulation mode for Bash.   Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  *//* Copyright (C) 1988, 1991 Free Software Foundation, Inc.   This file is part of the GNU Readline Library (the Library), a set of   routines for providing Emacs style line input to programs that ask   for it.   The 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 of the License, or   (at your option) any later version.   The 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.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  *//* **************************************************************** *//*								    *//*			VI Emulation Mode			    *//*								    *//* **************************************************************** */#if defined (VI_MODE)/* Some standard library routines. */#include "sysdep.h"#include <stdio.h>#include "readline.h"#include "history.h"#ifndef digit#define digit(c)  ((c) >= '0' && (c) <= '9')#endif#ifndef isletter#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))#endif#ifndef digit_value#define digit_value(c) ((c) - '0')#endif#ifndef member#define member(c, s) ((c) ? index ((s), (c)) : 0)#endif#ifndef isident#define isident(c) ((isletter(c) || digit(c) || c == '_'))#endif#ifndef exchange#define exchange(x, y) {int temp = x; x = y; y = temp;}#endif/* Variables imported from readline.c */extern int rl_point, rl_end, rl_mark, rl_done;extern FILE *rl_instream;extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;extern Keymap keymap;extern char *rl_prompt;extern char *rl_line_buffer;extern int rl_arg_sign;extern char *xmalloc (), *xrealloc ();extern void rl_extend_line_buffer ();/* Last string searched for from `/' or `?'. */static char *vi_last_search = (char *)NULL;static int vi_histpos;/* Non-zero means enter insertion mode. */int vi_doing_insert = 0;/* String inserted into the line by rl_vi_comment (). */char *rl_vi_comment_begin = (char *)NULL;/* *** UNCLEAN *** *//* Command keys which do movement for xxx_to commands. */static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";/* Keymap used for vi replace characters.  Created dynamically since   rarely used. */static Keymap vi_replace_map = (Keymap)NULL;/* The number of characters inserted in the last replace operation. */static int vi_replace_count = 0;/* Yank the nth arg from the previous line into this line at point. */rl_vi_yank_arg (count)     int count;{  /* Readline thinks that the first word on a line is the 0th, while vi     thinks the first word on a line is the 1st.  Compensate. */  if (rl_explicit_arg)    rl_yank_nth_arg (count - 1, 0);  else    rl_yank_nth_arg ('$', 0);}/* With an argument, move back that many history lines, else move to the   beginning of history. */rl_vi_fetch_history (count, c)     int count, c;{  extern int rl_explicit_arg;  int current = where_history ();  /* Giving an argument of n means we want the nth command in the history     file.  The command number is interpreted the same way that the bash     `history' command does it -- that is, giving an argument count of 450     to this command would get the command listed as number 450 in the     output of `history'. */  if (rl_explicit_arg)    {      int wanted = history_base + current - count;      if (wanted <= 0)        rl_beginning_of_history (0, 0);      else        rl_get_previous_history (wanted);    }  else    rl_beginning_of_history (count, 0);}/* Search again for the last thing searched for. */rl_vi_search_again (ignore, key)     int ignore, key;{  switch (key)    {    case 'n':      rl_vi_dosearch (vi_last_search, -1);      break;    case 'N':      rl_vi_dosearch (vi_last_search, 1);      break;    }}/* Do a vi style search. */rl_vi_search (count, key)     int count, key;{  int dir, c, save_pos;  char *p;  switch (key)    {    case '?':      dir = 1;      break;    case '/':      dir = -1;      break;    default:      ding ();      return;    }  vi_histpos = where_history ();  maybe_save_line ();  save_pos = rl_point;  /* Reuse the line input buffer to read the search string. */  rl_line_buffer[0] = 0;  rl_end = rl_point = 0;  p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));  sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);  rl_message (p, 0, 0);  while (c = rl_read_key ())    {      switch (c)	{	case CTRL('H'):	case RUBOUT:	  if (rl_point == 0)	    {	      maybe_unsave_line ();	      rl_clear_message ();	      rl_point = save_pos;	      return;	    }	case CTRL('W'):	case CTRL('U'):	  rl_dispatch (c, keymap);	  break;	case ESC:	case RETURN:	case NEWLINE:	  goto dosearch;	  break;	case CTRL('C'):	  maybe_unsave_line ();	  rl_clear_message ();	  rl_point = 0;	  ding ();	  return;	default:	  rl_insert (1, c);	  break;	}      rl_redisplay ();    } dosearch:  if (vi_last_search)    free (vi_last_search);  vi_last_search = savestring (rl_line_buffer);  rl_vi_dosearch (rl_line_buffer, dir);}/* Search for STRING in the history list.  DIR is < 0 for searching   backwards.  POS is an absolute index into the history list at   which point to begin searching.  If the first character of STRING   is `^', the string must match a prefix of a history line, otherwise   a full substring match is performed. */static intvi_history_search_pos (string, dir, pos)     char *string;     int dir, pos;{  int ret, old = where_history ();  history_set_pos (pos);  if (*string == '^')    ret = history_search_prefix (string + 1, dir);  else    ret = history_search (string, dir);      if (ret == -1)    {      history_set_pos (old);      return (-1);    }  ret = where_history ();  history_set_pos (old);  return ret;}rl_vi_dosearch (string, dir)     char *string;     int dir;{  int old, save = vi_histpos;  HIST_ENTRY *h;  if (string == 0 || *string == 0 || vi_histpos < 0)    {      ding ();      return;    }  if ((save = vi_history_search_pos (string, dir, vi_histpos + dir)) == -1)    {      maybe_unsave_line ();      rl_clear_message ();      rl_point = 0;      ding ();      return;    }  vi_histpos = save;  old = where_history ();  history_set_pos (vi_histpos);  h = current_history ();  history_set_pos (old);  {    int line_len = strlen (h->line);    if (line_len >= rl_line_buffer_len)      rl_extend_line_buffer (line_len);    strcpy (rl_line_buffer, h->line);  }  rl_undo_list = (UNDO_LIST *)h->data;  rl_end = strlen (rl_line_buffer);  rl_point = 0;  rl_clear_message ();}/* Completion, from vi's point of view. */rl_vi_complete (ignore, key)     int ignore, key;{  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))    {      if (!whitespace (rl_line_buffer[rl_point + 1]))	rl_vi_end_word (1, 'E');      rl_point++;    }  if (key == '*')    rl_complete_internal ('*');	/* Expansion and replacement. */  else if (key == '=')    rl_complete_internal ('?');	/* List possible completions. */  else if (key == '\\')    rl_complete_internal (TAB);	/* Standard Readline completion. */  else    rl_complete (0, key);}/* Previous word in vi mode. */rl_vi_prev_word (count, key)     int count, key;{  if (count < 0)    {      rl_vi_next_word (-count, key);      return;    }  if (rl_point == 0)    {      ding ();      return;    }  if (uppercase_p (key))    rl_vi_bWord (count);  else    rl_vi_bword (count);}/* Next word in vi mode. */rl_vi_next_word (count, key)     int count;{  if (count < 0)    {      rl_vi_prev_word (-count, key);      return;    }  if (rl_point >= (rl_end - 1))    {      ding ();      return;    }  if (uppercase_p (key))    rl_vi_fWord (count);  else    rl_vi_fword (count);}/* Move to the end of the ?next? word. */rl_vi_end_word (count, key)     int count, key;{  if (count < 0)    {      ding ();      return;    }  if (uppercase_p (key))    rl_vi_eWord (count);  else    rl_vi_eword (count);}/* Move forward a word the way that 'W' does. */rl_vi_fWord (count)     int count;{  while (count-- && rl_point < (rl_end - 1))    {      /* Skip until whitespace. */      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)	rl_point++;      /* Now skip whitespace. */      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)	rl_point++;    }}rl_vi_bWord (count)     int count;{  while (count-- && rl_point > 0)    {      /* If we are at the start of a word, move back to whitespace so	 we will go back to the start of the previous word. */      if (!whitespace (rl_line_buffer[rl_point]) &&	  whitespace (rl_line_buffer[rl_point - 1]))	rl_point--;      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))	rl_point--;      if (rl_point > 0)	{	  while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));	  rl_point++;	}    }}rl_vi_eWord (count)     int count;{  while (count-- && rl_point < (rl_end - 1))    {      if (!whitespace (rl_line_buffer[rl_point]))	rl_point++;      /* Move to the next non-whitespace character (to the start of the	 next word). */      while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));      if (rl_point && rl_point < rl_end)	{	  /* Skip whitespace. */	  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))	    rl_point++;	  /* Skip until whitespace. */	  while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))	    rl_point++;	  /* Move back to the last character of the word. */	  rl_point--;	}    }}rl_vi_fword (count)     int count;{  while (count-- && rl_point < (rl_end - 1))    {      /* Move to white space (really non-identifer). */      if (isident (rl_line_buffer[rl_point]))	{	  while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)	    rl_point++;	}      else /* if (!whitespace (rl_line_buffer[rl_point])) */	{	  while (!isident (rl_line_buffer[rl_point]) &&		 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)	    rl_point++;	}      /* Move past whitespace. */      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)	rl_point++;    }}rl_vi_bword (count)     int count;{  while (count-- && rl_point > 0)    {      int last_is_ident;      /* If we are at the start of a word, move back to whitespace	 so we will go back to the start of the previous word. */      if (!whitespace (rl_line_buffer[rl_point]) &&	  whitespace (rl_line_buffer[rl_point - 1]))	rl_point--;      /* If this character and the previous character are `opposite', move	 back so we don't get messed up by the rl_point++ down there in	 the while loop.  Without this code, words like `l;' screw up the	 function. */      last_is_ident = isident (rl_line_buffer[rl_point - 1]);      if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||	  (!isident (rl_line_buffer[rl_point]) && last_is_ident))	rl_point--;      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))	rl_point--;      if (rl_point > 0)	{	  if (isident (rl_line_buffer[rl_point]))	    while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));	  else	    while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&		   !whitespace (rl_line_buffer[rl_point]));	  rl_point++;	}    }}rl_vi_eword (count)     int count;{  while (count-- && rl_point < rl_end - 1)    {      if (!whitespace (rl_line_buffer[rl_point]))	rl_point++;      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))	rl_point++;      if (rl_point < rl_end)	{	  if (isident (rl_line_buffer[rl_point]))	    while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));	  else	    while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])		   && !whitespace (rl_line_buffer[rl_point]));	}      rl_point--;    }}rl_vi_insert_beg (){  rl_beg_of_line ();  rl_vi_insertion_mode ();  return 0;}rl_vi_append_mode (){  if (rl_point < rl_end)    rl_point += 1;  rl_vi_insertion_mode ();  return 0;}rl_vi_append_eol (){  rl_end_of_line ();  rl_vi_append_mode ();  return 0;}/* What to do in the case of C-d. */rl_vi_eof_maybe (count, c)     int count, c;{  rl_newline (1, '\n');}/* Insertion mode stuff. *//* Switching from one mode to the other really just involves   switching keymaps. */rl_vi_insertion_mode (){  keymap = vi_insertion_keymap;}rl_vi_movement_mode (){  if (rl_point > 0)    rl_backward (1);  keymap = vi_movement_keymap;  vi_done_inserting ();}vi_done_inserting (){  if (vi_doing_insert)    {      rl_end_undo_group ();      vi_doing_insert = 0;    }}rl_vi_arg_digit (count, c)     int count, c;{  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)    rl_beg_of_line ();  else    rl_digit_argument (count, c);}rl_vi_change_case (count, ignore)     int count, ignore;{  char c = 0;  /* Don't try this on an empty line. */  if (rl_point >= rl_end)    return;  while (count-- && rl_point < rl_end)    {      if (uppercase_p (rl_line_buffer[rl_point]))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -