📄 minibuf.c
字号:
/* Minibuffer input and completion. Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Emacs is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "config.h"#include "lisp.h"#include "commands.h"#include "buffer.h"#include "window.h"#include "syntax.h"#include "dispextern.h"#define min(a, b) ((a) < (b) ? (a) : (b))/* List of buffers for use as minibuffers. The first element of the list is used for the outermost minibuffer invocation, the next element is used for a recursive minibuffer invocation, etc. The list is extended at the end as deeped minibuffer recursions are encountered. */Lisp_Object Vminibuffer_list;struct minibuf_save_data { char *prompt; int prompt_width; Lisp_Object help_form; Lisp_Object current_prefix_arg; };int minibuf_save_vector_size;struct minibuf_save_data *minibuf_save_vector;/* Depth in minibuffer invocations. */int minibuf_level;/* Nonzero means display completion help for invalid input. */int completion_auto_help;/* Fread_minibuffer leaves the input, as a string, here. */Lisp_Object last_minibuf_string;/* Nonzero means let functions called when within a minibuffer invoke recursive minibuffers (to read arguments, or whatever). */int enable_recursive_minibuffers;/* help-form is bound to this while in the minibuffer. */Lisp_Object Vminibuffer_help_form;/* Nonzero means completion ignores case. */int completion_ignore_case;Lisp_Object Quser_variable_p;/* Width in columns of current minibuffer prompt. */extern int minibuf_prompt_width;/* Actual minibuffer invocation. */void read_minibuf_unwind ();Lisp_Object get_minibuffer ();Lisp_Object read_minibuf ();Lisp_Objectread_minibuf (map, initial, prompt, expflag) Lisp_Object map; Lisp_Object initial; Lisp_Object prompt; int expflag;{ register Lisp_Object val; int count = specpdl_ptr - specpdl; struct gcpro gcpro1, gcpro2; if (XTYPE (prompt) != Lisp_String) prompt = build_string (""); /* Emacs in -batch mode calls minibuffer: print the prompt. */ if (noninteractive) printf ("%s", XSTRING (prompt)->data); if (!enable_recursive_minibuffers && (EQ (selected_window, minibuf_window))) error ("Command attempted to use minibuffer while in minibuffer"); if (minibuf_level == minibuf_save_vector_size) minibuf_save_vector = (struct minibuf_save_data *) xrealloc (minibuf_save_vector, (minibuf_save_vector_size *= 2) * sizeof (struct minibuf_save_data)); minibuf_save_vector[minibuf_level].prompt = minibuf_prompt; minibuf_save_vector[minibuf_level].prompt_width = minibuf_prompt_width; minibuf_prompt_width = 0; /* >> Why is this done this way rather than binding these variables? */ minibuf_save_vector[minibuf_level].help_form = Vhelp_form; minibuf_save_vector[minibuf_level].current_prefix_arg = Vcurrent_prefix_arg; GCPRO2 (minibuf_save_vector[minibuf_level].help_form, minibuf_save_vector[minibuf_level].current_prefix_arg); record_unwind_protect (Fset_window_configuration, Fcurrent_window_configuration ()); val = current_buffer->directory; Fset_buffer (get_minibuffer (minibuf_level)); current_buffer->directory = val; Fset_window_buffer (minibuf_window, Fcurrent_buffer ()); Fselect_window (minibuf_window); XFASTINT (XWINDOW (minibuf_window)->hscroll) = 0; Ferase_buffer (); minibuf_level++; record_unwind_protect (read_minibuf_unwind, Qnil); Vminibuf_scroll_window = Qnil; if (!NULL (initial)) Finsert (1, &initial); minibuf_prompt = (char *) alloca (XSTRING (prompt)->size + 1); bcopy (XSTRING (prompt)->data, minibuf_prompt, XSTRING (prompt)->size + 1); echo_area_contents = 0; Vhelp_form = Vminibuffer_help_form; current_buffer->keymap = map; recursive_edit_1 (); /* If cursor is on the minibuffer line, show the user we have exited by putting it in column 0. */ if (cursor_vpos >= XFASTINT (XWINDOW (minibuf_window)->top) && !noninteractive) { cursor_hpos = 0; update_screen (1, 1); } /* Make minibuffer contents into a string */ val = make_string (BEG_ADDR, Z - BEG); bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT); unbind_to (count); UNGCPRO; /* VAL is the string of minibuffer text. */ last_minibuf_string = val; /* If Lisp form desired instead of string, parse it */ if (expflag) val = Fread (val); return val;}/* Return a buffer to be used as the minibuffer at depth `depth'. depth = 0 is the lowest allowed argument, and that is the value used for nonrecursive minibuffer invocations */Lisp_Objectget_minibuffer (depth) int depth;{ Lisp_Object tail, num, buf; char name[14]; extern Lisp_Object nconc2 (); XFASTINT (num) = depth; tail = Fnthcdr (num, Vminibuffer_list); if (NULL (tail)) { tail = Fcons (Qnil, Qnil); Vminibuffer_list = nconc2 (Vminibuffer_list, tail); } buf = Fcar (tail); if (NULL (buf) || NULL (XBUFFER (buf)->name)) { sprintf (name, " *Minibuf-%d*", depth); buf = Fget_buffer_create (build_string (name)); XCONS (tail)->car = buf; } else reset_buffer (XBUFFER (buf)); return buf;}/* This function is called on exiting minibuffer, whether normally or not, and it restores the current window, buffer, etc. */voidread_minibuf_unwind (){ /* Erase the minibuffer we were using at this level. */ Fset_buffer (XWINDOW (minibuf_window)->buffer); Ferase_buffer (); /* If this was a recursive minibuffer, tie the minibuffer window back to the outer level minibuffer buffer */ minibuf_level--; /* Make sure minibuffer window is erased, not ignored */ windows_or_buffers_changed++; XFASTINT (XWINDOW (minibuf_window)->last_modified) = 0; /* Restore prompt from outer minibuffer */ minibuf_prompt = minibuf_save_vector[minibuf_level].prompt; minibuf_prompt_width = minibuf_save_vector[minibuf_level].prompt_width; Vhelp_form = minibuf_save_vector[minibuf_level].help_form; Vcurrent_prefix_arg = minibuf_save_vector[minibuf_level].current_prefix_arg;}DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 4, 0, "Read a string from the minibuffer, prompting with string PROMPT.\n\If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\ to be inserted into the minibuffer before reading input.\n\Third arg KEYMAP is a keymap to use whilst reading; the default is\n\ minibuffer-local-map.\n\If fourth arg READ is non-nil, then interpret the result as a lisp object\n\ and return that object (ie (car (read-from-string <input-string>)))") (prompt, initial_input, keymap, read) Lisp_Object prompt, initial_input, keymap, read;{ CHECK_STRING (prompt, 0); if (!NULL (initial_input)) CHECK_STRING (initial_input, 1); if (NULL (keymap)) keymap = Vminibuffer_local_map; else keymap = get_keymap (keymap,2); return read_minibuf (keymap, initial_input, prompt, !NULL(read));}DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0, "Return a Lisp object read using the minibuffer.\n\Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS\n\is a string to insert in the minibuffer before reading.") (prompt, initial_contents) Lisp_Object prompt, initial_contents;{ CHECK_STRING (prompt, 0); if (!NULL (initial_contents)) CHECK_STRING (initial_contents, 1) return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, 1);}DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0, "Return value of Lisp expression read using the minibuffer.\n\Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS\n\is a string to insert in the minibuffer before reading.") (prompt, initial_contents) Lisp_Object prompt, initial_contents;{ return Feval (Fread_minibuffer (prompt, initial_contents));}/* Functions that use the minibuffer to read various things. */DEFUN ("read-string", Fread_string, Sread_string, 1, 2, 0, "Read a string from the minibuffer, prompting with string PROMPT.\n\If non-nil second arg INITIAL-INPUT is a string to insert before reading.") (prompt, initial_input) Lisp_Object prompt, initial_input;{ return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil);}DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 2, 0, "Args PROMPT and INIT, strings. Read a string from the terminal, not allowing blanks.\n\Prompt with PROMPT, and provide INIT as an initial value of the input string.") (prompt, init) Lisp_Object prompt, init;{ CHECK_STRING (prompt, 0); CHECK_STRING (init, 1); return read_minibuf (Vminibuffer_local_ns_map, init, prompt, 0);}DEFUN ("read-command", Fread_command, Sread_command, 1, 1, 0, "One arg PROMPT, a string. Read the name of a command and return as a symbol.\n\Prompts with PROMPT.") (prompt) Lisp_Object prompt;{ return Fintern (Fcompleting_read (prompt, Vobarray, Qcommandp, Qt, Qnil), Qnil);}#ifdef NOTDEFDEFUN ("read-function", Fread_function, Sread_function, 1, 1, 0, "One arg PROMPT, a string. Read the name of a function and return as a symbol.\n\Prompts with PROMPT.") (prompt) Lisp_Object prompt;{ return Fintern (Fcompleting_read (prompt, Vobarray, Qfboundp, Qt, Qnil), Qnil);}#endif /* NOTDEF */DEFUN ("read-variable", Fread_variable, Sread_variable, 1, 1, 0, "One arg PROMPT, a string. Read the name of a user variable and return\n\it as a symbol. Prompts with PROMPT.\n\A user variable is one whose documentation starts with a \"*\" character.") (prompt) Lisp_Object prompt;{ return Fintern (Fcompleting_read (prompt, Vobarray, Quser_variable_p, Qt, Qnil), Qnil);}DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 3, 0, "One arg PROMPT, a string. Read the name of a buffer and return as a string.\n\Prompts with PROMPT.\n\Optional second arg is value to return if user enters an empty line.\n\If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are allowed.") (prompt, def, require_match) Lisp_Object prompt, def, require_match;{ Lisp_Object tem; Lisp_Object args[3]; struct gcpro gcpro1; if (XTYPE (def) == Lisp_Buffer) def = XBUFFER (def)->name; if (!NULL (def)) { args[0] = build_string ("%s(default %s) "); args[1] = prompt; args[2] = def; prompt = Fformat (3, args); } GCPRO1 (def); tem = Fcompleting_read (prompt, Vbuffer_alist, Qnil, require_match, Qnil); UNGCPRO; if (XSTRING (tem)->size) return tem; return def;}DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0, "Return common substring of all completions of STRING in ALIST.\n\Each car of each element of ALIST is tested to see if it begins with STRING.\n\All that match are compared together; the longest initial sequence\n\common to all matches is returned as a string.\n\If there is no match at all, nil is returned.\n\For an exact match, t is returned.\n\\n\ALIST can be an obarray instead of an alist.\n\Then the print names of all symbols in the obarray are the possible matches.\n\\n\If optional third argument PREDICATE is non-nil,\n\it is used to test each possible match.\n\The match is a candidate only if PREDICATE returns non-nil.\n\The argument given to PREDICATE is the alist element or the symbol from the obarray.") (string, alist, pred) Lisp_Object string, alist, pred;{ Lisp_Object bestmatch, tail, elt, eltstring;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -