Lisp_Object Qread_file_name_internal;
-/* Normal hook for entry to minibuffer. */
+/* 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. */
static Lisp_Object last_exact_completion;
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. */
if (XFRAME (mini_frame) != selected_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
CONSP (buf_list);
buf_list = XCONS (buf_list)->cdr)
{
- Lisp_Object other_buf = XCONS (XCONS (buf_list)->car)->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;
}
#ifdef MULTI_FRAME
- Fredirect_frame_focus (Fselected_frame (), mini_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;
/* ??? 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)
/* If Lisp form desired instead of string, parse it. */
if (expflag)
- val = Fread (val);
-
- unbind_to (count, Qnil); /* The appropriate frame will get selected
- in set-window-configuration. */
+ {
+ 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);
+ }
UNGCPRO;
-
- return val;
+ 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;
/* 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. */
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;
Lisp_Object completion, tem;
int completedp;
Lisp_Object last;
+ struct gcpro gcpro1, gcpro2;
+ GCPRO2 (completion, last);
completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
last = last_exact_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.\n\
-Return nil if there is no valid completion, else t.")
+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);
+ else
+ /* Else scroll down one screen. */
+ Fscroll_other_window (Qnil);
+
+ set_buffer_internal (obuf);
+ return Qnil;
+ }
+
+ i = do_completion ();
switch (i)
{
case 0:
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 ()
{
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_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;
"*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);