/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
This file is part of GNU Emacs.
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include "config.h"
+#include <config.h>
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
+extern int quit_char;
+
/* 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.
/* Nonzero means display completion help for invalid input */
int auto_help;
-/* Fread_minibuffer leaves the input, as a string, here */
+/* Fread_minibuffer leaves the input here as a string. */
Lisp_Object last_minibuf_string;
/* Nonzero means let functions called when within a minibuffer
Lisp_Object Qminibuffer_history;
+Lisp_Object Qread_file_name_internal;
+
+/* Normal hooks for entry to and exit from minibuffer. */
+
+Lisp_Object Qminibuffer_setup_hook, Vminibuffer_setup_hook;
+Lisp_Object Qminibuffer_exit_hook, Vminibuffer_exit_hook;
+
/* Nonzero means completion ignores case. */
int completion_ignore_case;
+/* List of regexps that should restrict possible completions. */
+
+Lisp_Object Vcompletion_regexp_list;
+
+/* Nonzero means raise the minibuffer frame when the minibuffer
+ is entered. */
+
+int minibuffer_auto_raise;
+
/* If last completion attempt reported "Complete but not unique"
then this is the string completed then; otherwise this is nil. */
Lisp_Object Quser_variable_p;
+/* Non-nil means it is the window for C-M-v to scroll
+ when the minibuffer is selected. */
+extern Lisp_Object Vminibuf_scroll_window;
\f
/* Actual minibuffer invocation. */
with initial position HISTPOS. (BACKUP_N should be <= 0.)
Normally return the result as a string (the text that was read),
- but if EXPFLAG is non-nil, read it and return the object read. */
+ but if EXPFLAG is non-nil, read it and return the object read.
+ If HISTVAR is given, save the value read on that history only if it doesn't
+ match the front of that history list exactly. The value is pushed onto
+ the list as the string that was read, or as the object that resulted iff
+ EXPFLAG is non-nil. */
Lisp_Object
read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
Lisp_Object map;
Lisp_Object initial;
Lisp_Object prompt;
- int backup_n;
+ Lisp_Object backup_n;
int expflag;
Lisp_Object histvar;
Lisp_Object histpos;
{
register Lisp_Object val;
int count = specpdl_ptr - specpdl;
- Lisp_Object mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
+ Lisp_Object mini_frame;
struct gcpro gcpro1, gcpro2;
if (XTYPE (prompt) != Lisp_String)
/* If the minibuffer window is on a different frame, save that
frame's configuration too. */
+#ifdef MULTI_FRAME
+ XSET (mini_frame, Lisp_Frame, WINDOW_FRAME (XWINDOW (minibuf_window)));
if (XFRAME (mini_frame) != selected_frame)
- {
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (mini_frame));
- }
+ record_unwind_protect (Fset_window_configuration,
+ Fcurrent_window_configuration (mini_frame));
+
+ /* If the minibuffer is on an iconified or invisible frame,
+ make it visible now. */
+ Fmake_frame_visible (mini_frame);
+
+ if (minibuffer_auto_raise)
+ Fraise_frame (mini_frame);
+#endif
val = current_buffer->directory;
Fset_buffer (get_minibuffer (minibuf_level));
- current_buffer->directory = val;
- Fredirect_frame_focus (Fselected_frame (), mini_frame);
+
+ /* The current buffer's default directory is usually the right thing
+ for our minibuffer here. However, if you're typing a command at
+ a minibuffer-only frame when minibuf_level is zero, then buf IS
+ the current_buffer, so reset_buffer leaves buf's default
+ directory unchanged. This is a bummer when you've just started
+ up Emacs and buf's default directory is Qnil. Here's a hack; can
+ you think of something better to do? Find another buffer with a
+ better directory, and use that one instead. */
+ if (XTYPE (val) == Lisp_String)
+ current_buffer->directory = val;
+ else
+ {
+ Lisp_Object buf_list;
+
+ for (buf_list = Vbuffer_alist;
+ CONSP (buf_list);
+ buf_list = XCONS (buf_list)->cdr)
+ {
+ Lisp_Object other_buf;
+
+ other_buf = XCONS (XCONS (buf_list)->car)->cdr;
+ if (XTYPE (XBUFFER (other_buf)->directory) == Lisp_String)
+ {
+ current_buffer->directory = XBUFFER (other_buf)->directory;
+ break;
+ }
+ }
+ }
+
+#ifdef MULTI_FRAME
+ if (XFRAME (mini_frame) != selected_frame)
+ Fredirect_frame_focus (Fselected_frame (), mini_frame);
+#endif
Fmake_local_variable (Qprint_escape_newlines);
print_escape_newlines = 1;
minibuf_prompt = (char *) alloca (XSTRING (prompt)->size + 1);
bcopy (XSTRING (prompt)->data, minibuf_prompt, XSTRING (prompt)->size + 1);
echo_area_glyphs = 0;
+ /* This is in case the minibuffer-setup-hook calls Fsit_for. */
+ previous_echo_glyphs = 0;
Vhelp_form = Vminibuffer_help_form;
current_buffer->keymap = map;
Vminibuffer_history_position = histpos;
Vminibuffer_history_variable = histvar;
+ /* Run our hook, but not if it is empty.
+ (run-hooks would do nothing if it is empty,
+ but it's important to save time here in the usual case. */
+ if (!NILP (Vminibuffer_setup_hook) && !EQ (Vminibuffer_setup_hook, Qunbound)
+ && !NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qminibuffer_setup_hook);
+
/* ??? MCC did redraw_screen here if switching screens. */
recursive_edit_1 ();
+ if (!NILP (Vminibuffer_exit_hook) && !EQ (Vminibuffer_exit_hook, Qunbound)
+ && !NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qminibuffer_exit_hook);
+
/* If cursor is on the minibuffer line,
show the user we have exited by putting it in column 0. */
if ((FRAME_CURSOR_Y (selected_frame)
val = make_buffer_string (1, Z);
bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
+ /* VAL is the string of minibuffer text. */
+ last_minibuf_string = val;
+
/* Add the value to the appropriate history list. */
if (XTYPE (Vminibuffer_history_variable) == Lisp_Symbol
&& ! EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
- Fset (Vminibuffer_history_variable,
- Fcons (val, Fsymbol_value (Vminibuffer_history_variable)));
-
- unbind_to (count, Qnil); /* The appropriate frame will get selected
- in set-window-configuration. */
-
- UNGCPRO;
-
- /* VAL is the string of minibuffer text. */
- last_minibuf_string = val;
+ {
+ /* If the caller wanted to save the value read on a history list,
+ then do so if the value is not already the front of the list. */
+ Lisp_Object histval;
+ histval = Fsymbol_value (Vminibuffer_history_variable);
+
+ /* The value of the history variable must be a cons or nil. Other
+ values are unacceptable. We silently ignore these values. */
+ if (NILP (histval)
+ || (CONSP (histval)
+ && NILP (Fequal (last_minibuf_string, Fcar (histval)))))
+ Fset (Vminibuffer_history_variable,
+ Fcons (last_minibuf_string, histval));
+ }
- /* If Lisp form desired instead of string, parse it */
+ /* If Lisp form desired instead of string, parse it. */
if (expflag)
- val = Fread (val);
+ {
+ Lisp_Object expr_and_pos;
+ unsigned char *p;
+
+ expr_and_pos = Fread_from_string (val, Qnil, Qnil);
+ /* Ignore trailing whitespace; any other trailing junk is an error. */
+ for (p = XSTRING (val)->data + XINT (Fcdr (expr_and_pos)); *p; p++)
+ if (*p != ' ' && *p != '\t' && *p != '\n')
+ error ("Trailing garbage following expression");
+ val = Fcar (expr_and_pos);
+ }
- return val;
+ UNGCPRO;
+ return unbind_to (count, val); /* The appropriate frame will get selected
+ in set-window-configuration. */
}
/* Return a buffer to be used as the minibuffer at depth `depth'.
int depth;
{
Lisp_Object tail, num, buf;
- char name[14];
+ char name[24];
extern Lisp_Object nconc2 ();
XFASTINT (num) = depth;
}
else
reset_buffer (XBUFFER (buf));
+
return buf;
}
DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 5, 0,
0 /* See immediately above */)
- (prompt, initial_input, keymap, read, hist)
- Lisp_Object prompt, initial_input, keymap, read, hist;
+ (prompt, initial_contents, keymap, read, hist)
+ Lisp_Object prompt, initial_contents, keymap, read, hist;
{
int pos = 0;
Lisp_Object histvar, histpos, position;
position = Qnil;
CHECK_STRING (prompt, 0);
- if (!NILP (initial_input))
+ if (!NILP (initial_contents))
{
- if (XTYPE (initial_input) == Lisp_Cons)
+ if (XTYPE (initial_contents) == Lisp_Cons)
{
- position = Fcdr (initial_input);
- initial_input = Fcar (initial_input);
+ position = Fcdr (initial_contents);
+ initial_contents = Fcar (initial_contents);
}
- CHECK_STRING (initial_input, 1);
+ CHECK_STRING (initial_contents, 1);
if (!NILP (position))
{
CHECK_NUMBER (position, 0);
/* Convert to distance from end of input. */
- pos = XINT (position) - 1 - XSTRING (initial_input)->size;
+ pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
}
}
if (NILP (histpos))
XFASTINT (histpos) = 0;
- return read_minibuf (keymap, initial_input, prompt,
+ return read_minibuf (keymap, initial_contents, prompt,
make_number (pos), !NILP (read), histvar, histpos);
}
{
CHECK_STRING (prompt, 0);
if (!NILP (initial_contents))
- CHECK_STRING (initial_contents, 1)
+ CHECK_STRING (initial_contents, 1);
return read_minibuf (Vminibuffer_local_map, initial_contents,
prompt, Qnil, 1, Qminibuffer_history, make_number (0));
}
return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil, Qnil);
}
-DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 2, 0,
+DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 1, 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)
/* Is this element a possible completion? */
- if (XTYPE (eltstring) == Lisp_String &&
- XSTRING (string)->size <= XSTRING (eltstring)->size &&
- 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
+ if (XTYPE (eltstring) == Lisp_String
+ && XSTRING (string)->size <= XSTRING (eltstring)->size
+ && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+ XSTRING (string)->size))
{
/* Yes. */
+ Lisp_Object regexps;
+ Lisp_Object zero;
+ XFASTINT (zero) = 0;
+
+ /* Ignore this element if it fails to match all the regexps. */
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCONS (regexps)->cdr)
+ {
+ tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+ if (NILP (tem))
+ break;
+ }
+ if (CONSP (regexps))
+ continue;
+
/* Ignore this element if there is a predicate
and the predicate doesn't like it. */
/* Is this element a possible completion? */
- if (XTYPE (eltstring) == Lisp_String &&
- XSTRING (string)->size <= XSTRING (eltstring)->size &&
- XSTRING (eltstring)->data[0] != ' ' &&
- 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
+ if (XTYPE (eltstring) == Lisp_String
+ && XSTRING (string)->size <= XSTRING (eltstring)->size
+ /* Reject alternatives that start with space
+ unless the input starts with space. */
+ && ((XSTRING (string)->size > 0 && XSTRING (string)->data[0] == ' ')
+ || XSTRING (eltstring)->data[0] != ' ')
+ && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+ XSTRING (string)->size))
{
/* Yes. */
+ Lisp_Object regexps;
+ Lisp_Object zero;
+ XFASTINT (zero) = 0;
+
+ /* Ignore this element if it fails to match all the regexps. */
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCONS (regexps)->cdr)
+ {
+ tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+ if (NILP (tem))
+ break;
+ }
+ if (CONSP (regexps))
+ continue;
+
/* Ignore this element if there is a predicate
and the predicate doesn't like it. */
SET_PT (osize);
Vinhibit_quit = Qt;
Fsit_for (make_number (2), Qnil, Qnil);
- del_range (point, ZV);
+ del_range (PT, ZV);
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
- XFASTINT (unread_command_char) = Ctl ('g');
+ Vunread_command_events = Fcons (make_number (quit_char), Qnil);
}
Vinhibit_quit = oinhibit;
}
Lisp_Object completion, tem;
int completedp;
Lisp_Object last;
+ struct gcpro gcpro1, gcpro2;
completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
last = last_exact_completion;
last_exact_completion = Qnil;
+ GCPRO2 (completion, last);
+
if (NILP (completion))
{
bitch_at_user ();
temp_echo_area_glyphs (" [No match]");
+ UNGCPRO;
return 0;
}
if (EQ (completion, Qt)) /* exact and unique match */
- return 1;
+ {
+ UNGCPRO;
+ return 1;
+ }
/* compiler bug */
tem = Fstring_equal (completion, Fbuffer_string());
Qlambda);
if (NILP (tem))
- { /* not an exact match */
+ {
+ /* not an exact match */
+ UNGCPRO;
if (completedp)
return 5;
else if (auto_help)
return 6;
}
else if (completedp)
- return 4;
+ {
+ UNGCPRO;
+ return 4;
+ }
/* If the last exact completion and this one were the same,
it means we've already given a "Complete but not unique"
message and the user's hit TAB again, so now we give him help. */
if (!NILP (Fequal (tem, last)))
Fminibuffer_completion_help ();
}
+ UNGCPRO;
return 3;
}
-
+
/* Like assoc but assumes KEY is a string, and ignores case if appropriate. */
Lisp_Object
}
DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
- "Complete the minibuffer contents as far as possible.")
+ "Complete the minibuffer contents as far as possible.\n\
+Return nil if there is no valid completion, else t.\n\
+If no characters can be completed, display a list of possible completions.\n\
+If you repeat this command after it displayed such a list,\n\
+scroll the window of possible completions.")
()
{
- register int i = do_completion ();
+ register int i;
+ Lisp_Object window, tem;
+
+ /* If the previous command was not this, then mark the completion
+ buffer obsolete. */
+ if (! EQ (last_command, this_command))
+ Vminibuf_scroll_window = Qnil;
+
+ window = Vminibuf_scroll_window;
+ /* If there's a fresh completion window with a live buffer,
+ and this command is repeated, scroll that window. */
+ if (! NILP (window) && ! NILP (XWINDOW (window)->buffer)
+ && !NILP (XBUFFER (XWINDOW (window)->buffer)->name))
+ {
+ struct buffer *obuf = current_buffer;
+
+ Fset_buffer (XWINDOW (window)->buffer);
+ tem = Fpos_visible_in_window_p (make_number (ZV), window);
+ if (! NILP (tem))
+ /* If end is in view, scroll up to the beginning. */
+ Fset_window_start (window, BEGV, Qnil);
+ else
+ /* Else scroll down one screen. */
+ Fscroll_other_window (Qnil);
+
+ set_buffer_internal (obuf);
+ return Qnil;
+ }
+
+ i = do_completion ();
switch (i)
{
case 0:
0, 0, "",
"Complete the minibuffer contents at most a single word.\n\
After one word is completed as much as possible, a space or hyphen\n\
-is added, provided that matches some possible completion.")
+is added, provided that matches some possible completion.\n\
+Return nil if there is no valid completion, else t.")
()
{
Lisp_Object completion, tem;
register int i;
register unsigned char *completion_string;
- /* We keep calling Fbuffer_string
- rather than arrange for GC to hold onto a pointer to
- one of the strings thus made. */
+ struct gcpro gcpro1;
+
+ /* We keep calling Fbuffer_string rather than arrange for GC to
+ hold onto a pointer to one of the strings thus made. */
completion = Ftry_completion (Fbuffer_string (),
Vminibuffer_completion_table,
if (EQ (completion, Qt))
return Qnil;
-#if 0 /* How the below code used to look, for reference */
+#if 0 /* How the below code used to look, for reference. */
tem = Fbuffer_string ();
b = XSTRING (tem)->data;
i = ZV - 1 - XSTRING (completion)->size;
int buffer_length, completion_length;
tem = Fbuffer_string ();
+ /* If reading a file name,
+ expand any $ENVVAR refs in the buffer and in TEM. */
+ if (EQ (Vminibuffer_completion_table, Qread_file_name_internal))
+ {
+ Lisp_Object substituted;
+ substituted = Fsubstitute_in_file_name (tem);
+ if (! EQ (substituted, tem))
+ {
+ tem = substituted;
+ Ferase_buffer ();
+ insert_from_string (tem, 0, XSTRING (tem)->size, 0);
+ }
+ }
buffer_string = XSTRING (tem)->data;
completion_string = XSTRING (completion)->data;
buffer_length = XSTRING (tem)->size; /* ie ZV - BEGV */
i = ZV - BEGV;
/* If completion finds next char not unique,
- consider adding a space or a hyphen */
+ consider adding a space or a hyphen. */
if (i == XSTRING (completion)->size)
{
+ GCPRO1 (completion);
tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
+ UNGCPRO;
+
if (XTYPE (tem) == Lisp_String)
completion = tem;
else
{
- tem = Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
- Vminibuffer_completion_table,
- Vminibuffer_completion_predicate);
+ GCPRO1 (completion);
+ tem =
+ Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
+ UNGCPRO;
+
if (XTYPE (tem) == Lisp_String)
completion = tem;
}
/* Now find first word-break in the stuff found by completion.
i gets index in string of where to stop completing. */
+
completion_string = XSTRING (completion)->data;
for (; i < XSTRING (completion)->size; i++)
/* Otherwise insert in minibuffer the chars we got */
Ferase_buffer ();
- insert_from_string (completion, 0, i);
+ insert_from_string (completion, 0, i, 1);
return Qt;
}
\f
1, 1, 0,
"Display the list of completions, COMPLETIONS, using `standard-output'.\n\
Each element may be just a symbol or string\n\
-or may be a list of two strings to be printed as if concatenated.")
+or may be a list of two strings to be printed as if concatenated.\n\
+`standard-output' must be a buffer.\n\
+At the end, run the normal hook `completion-setup-hook'.\n\
+It can find the completion buffer in `standard-output'.")
(completions)
Lisp_Object completions;
{
set_buffer_internal (XBUFFER (Vstandard_output));
if (NILP (completions))
- write_string ("There are no possible completions of what you have typed.", -1);
+ write_string ("There are no possible completions of what you have typed.",
+ -1);
else
{
write_string ("Possible completions are:", -1);
if (XTYPE (Vstandard_output) != Lisp_Buffer)
{
Lisp_Object tem;
- tem = Flength (elt, Qt);
+ tem = Flength (elt);
column += XINT (tem);
}
Fprinc (elt, Qnil);
if (XTYPE (Vstandard_output) == Lisp_Buffer)
set_buffer_internal (old);
+
+ if (!NILP (Vrun_hooks))
+ call1 (Vrun_hooks, intern ("completion-setup-hook"));
+
return Qnil;
}
return make_number (minibuf_level);
}
+DEFUN ("minibuffer-prompt", Fminibuffer_prompt, Sminibuffer_prompt, 0, 0, 0,
+ "Return the prompt string of the currently-active minibuffer.\n\
+If no minibuffer is active, return nil.")
+ ()
+{
+ if (!minibuf_prompt)
+ return Qnil;
+ return build_string (minibuf_prompt);
+}
+
+DEFUN ("minibuffer-prompt-width", Fminibuffer_prompt_width,
+ Sminibuffer_prompt_width, 0, 0, 0,
+ "Return the display width of the minibuffer prompt.")
+ ()
+{
+ Lisp_Object width;
+ XFASTINT (width) = minibuf_prompt_width;
+ return width;
+}
\f
init_minibuf_once ()
{
minibuf_save_vector_size = 5;
minibuf_save_vector = (struct minibuf_save_data *) malloc (5 * sizeof (struct minibuf_save_data));
+ Qread_file_name_internal = intern ("read-file-name-internal");
+ staticpro (&Qread_file_name_internal);
+
Qminibuffer_completion_table = intern ("minibuffer-completion-table");
staticpro (&Qminibuffer_completion_table);
Qminibuffer_completion_predicate = intern ("minibuffer-completion-predicate");
staticpro (&Qminibuffer_completion_predicate);
+ staticpro (&last_exact_completion);
+ last_exact_completion = Qnil;
+
staticpro (&last_minibuf_string);
last_minibuf_string = Qnil;
Qminibuffer_history = intern ("minibuffer-history");
staticpro (&Qminibuffer_history);
+ Qminibuffer_setup_hook = intern ("minibuffer-setup-hook");
+ staticpro (&Qminibuffer_setup_hook);
+
+ Qminibuffer_exit_hook = intern ("minibuffer-exit-hook");
+ staticpro (&Qminibuffer_exit_hook);
+
+ DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook,
+ "Normal hook run just after entry to minibuffer.");
+ Vminibuffer_setup_hook = Qnil;
+
+ DEFVAR_LISP ("minibuffer-exit-hook", &Vminibuffer_exit_hook,
+ "Normal hook run just after exit from minibuffer.");
+ Vminibuffer_exit_hook = Qnil;
+
DEFVAR_BOOL ("completion-auto-help", &auto_help,
"*Non-nil means automatically provide help for invalid completion input.");
auto_help = 1;
"Current position of redoing in the history list.");
Vminibuffer_history_position = Qnil;
+ DEFVAR_BOOL ("minibuffer-auto-raise", &minibuffer_auto_raise,
+ "*Non-nil means entering the minibuffer raises the minibuffer's frame.");
+ minibuffer_auto_raise = 0;
+
+ DEFVAR_LISP ("completion-regexp-list", &Vcompletion_regexp_list,
+ "List of regexps that should restrict possible completions.");
+ Vcompletion_regexp_list = Qnil;
+
defsubr (&Sread_from_minibuffer);
defsubr (&Seval_minibuffer);
defsubr (&Sread_minibuffer);
defsubr (&Sread_buffer);
defsubr (&Sread_no_blanks_input);
defsubr (&Sminibuffer_depth);
+ defsubr (&Sminibuffer_prompt);
+ defsubr (&Sminibuffer_prompt_width);
defsubr (&Stry_completion);
defsubr (&Sall_completions);