/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999
- Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "buffer.h"
#include "charset.h"
#include "dispextern.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
#include "syntax.h"
-#include "keyboard.h"
+#include "intervals.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
/* Nonzero means display completion help for invalid input. */
-int auto_help;
+Lisp_Object Vcompletion_auto_help;
/* The maximum length of a minibuffer history. */
Lisp_Object Vminibuffer_history_position;
+/* Text properties that are added to minibuffer prompts.
+ These are in addition to the basic `field' property, and stickiness
+ properties. */
+
+Lisp_Object Vminibuffer_prompt_properties;
+
Lisp_Object Qminibuffer_history, Qbuffer_name_history;
Lisp_Object Qread_file_name_internal;
{
int size, len;
char *line, *s;
- struct gcpro gcpro1, gcpro2;
Lisp_Object val;
fprintf (stdout, "%s", XSTRING (prompt)->data);
fflush (stdout);
+ val = Qnil;
size = 100;
len = 0;
line = (char *) xmalloc (size * sizeof *line);
specbind (Qminibuffer_default, defalt);
single_kboard_state ();
+#ifdef HAVE_X_WINDOWS
+ if (display_hourglass_p)
+ cancel_hourglass ();
+#endif
val = Qnil;
ambient_dir = current_buffer->directory;
}
if (noninteractive)
- return read_minibuf_noninteractive (map, initial, prompt, backup_n,
- expflag, histvar, histpos, defalt,
- allow_props, inherit_input_method);
+ {
+ val = read_minibuf_noninteractive (map, initial, prompt, backup_n,
+ expflag, histvar, histpos, defalt,
+ allow_props, inherit_input_method);
+ return unbind_to (count, val);
+ }
/* Choose the minibuffer window and frame, and take action on them. */
Qrear_nonsticky, Qt, Qnil);
Fput_text_property (make_number (BEG), make_number (PT),
Qfield, Qt, Qnil);
- Fput_text_property (make_number (BEG), make_number (PT),
- Qread_only, Qt, Qnil);
+ Fadd_text_properties (make_number (BEG), make_number (PT),
+ Vminibuffer_prompt_properties, Qnil);
}
minibuf_prompt_width = current_column ();
&& !NILP (Vrun_hooks))
call1 (Vrun_hooks, Qminibuffer_setup_hook);
+ /* Don't allow the user to undo past this point. */
+ current_buffer->undo_list = Qnil;
+
recursive_edit_1 ();
/* If cursor is on the minibuffer line,
/* Make minibuffer contents into a string. */
Fset_buffer (minibuffer);
- val = Ffield_string (make_number (ZV), allow_props ? Qt : Qnil);
+ if (allow_props)
+ val = Ffield_string (make_number (ZV));
+ else
+ val = Ffield_string_no_properties (make_number (ZV));
/* VAL is the string of minibuffer text. */
if (NILP (keymap))
keymap = Vminibuffer_local_map;
else
- keymap = get_keymap (keymap);
+ keymap = get_keymap (keymap, 1, 0);
if (SYMBOLP (hist))
{
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\
+For a unique match which is exact, 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\
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\n\
-or the symbol from the obarray.")
+or the symbol from the obarray.\n\
+Additionally to this predicate, `completion-regexp-list'\n\
+is used to further constrain the set of candidates.")
(string, alist, predicate)
Lisp_Object string, alist, predicate;
{
Lisp_Object bestmatch, tail, elt, eltstring;
/* Size in bytes of BESTMATCH. */
- int bestmatchsize;
+ int bestmatchsize = 0;
/* These are in bytes, too. */
int compare, matchsize;
int list = CONSP (alist) || NILP (alist);
- int index, obsize;
+ int index = 0, obsize = 0;
int matchcount = 0;
Lisp_Object bucket, zero, end, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
if (!list && !VECTORP (alist))
return call3 (alist, string, predicate, Qnil);
- bestmatch = Qnil;
+ bestmatch = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
\n\
ALIST can also be a function to do the completion itself.\n\
It receives three arguments: the values STRING, PREDICATE and t.\n\
-Whatever it returns becomes the value of `all-completion'.\n\
+Whatever it returns becomes the value of `all-completions'.\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\n\
or the symbol from the obarray.\n\
+Additionally to this predicate, `completion-regexp-list'\n\
+is used to further constrain the set of candidates.\n\
\n\
If the optional fourth argument HIDE-SPACES is non-nil,\n\
strings in ALIST that start with a space\n\
Lisp_Object tail, elt, eltstring;
Lisp_Object allmatches;
int list = CONSP (alist) || NILP (alist);
- int index, obsize;
+ int index = 0, obsize = 0;
Lisp_Object bucket, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
{
return call3 (alist, string, predicate, Qt);
}
- allmatches = Qnil;
+ allmatches = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
"Read a string in the minibuffer, with completion.\n\
PROMPT is a string to prompt with; normally it ends in a colon and a space.\n\
TABLE is an alist whose elements' cars are strings, or an obarray.\n\
+TABLE can also be a function to do the completion itself.\n\
PREDICATE limits completion to a subset of TABLE.\n\
See `try-completion' and `all-completions' for more details\n\
on completion, TABLE, and PREDICATE.\n\
If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
If it is (STRING . POSITION), the initial input\n\
is STRING, but point is placed POSITION characters into the string.\n\
+ This feature is deprecated--it is best to pass nil for INITIAL.\n\
HIST, if non-nil, specifies a history list\n\
and optionally the initial position in the list.\n\
It can be a symbol, which is the history list variable to use,\n\
*/
DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 8, 0,
0 /* See immediately above */)
- (prompt, table, predicate, require_match, init, hist, def, inherit_input_method)
- Lisp_Object prompt, table, predicate, require_match, init, hist, def;
- Lisp_Object inherit_input_method;
+ (prompt, table, predicate, require_match, initial_input, hist, def, inherit_input_method)
+ Lisp_Object prompt, table, predicate, require_match, initial_input;
+ Lisp_Object hist, def, inherit_input_method;
{
Lisp_Object val, histvar, histpos, position;
+ Lisp_Object init;
int pos = 0;
int count = specpdl_ptr - specpdl;
struct gcpro gcpro1;
+ init = initial_input;
GCPRO1 (def);
specbind (Qminibuffer_completion_table, table);
int
do_completion ()
{
- Lisp_Object completion, tem;
+ Lisp_Object completion, string, tem;
int completedp;
Lisp_Object last;
struct gcpro gcpro1, gcpro2;
- completion = Ftry_completion (Ffield_string (ZV),
+ completion = Ftry_completion (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
last = last_exact_completion;
return 1;
}
- /* compiler bug */
- tem = Fstring_equal (completion, Ffield_string(ZV));
- completedp = NILP (tem);
- if (completedp)
+ string = Ffield_string (make_number (ZV));
+
+ /* COMPLETEDP should be true if some completion was done, which
+ doesn't include simply changing the case of the entered string.
+ However, for appearance, the string is rewritten if the case
+ changes. */
+ tem = Fcompare_strings (completion, Qnil, Qnil, string, Qnil, Qnil, Qt);
+ completedp = !EQ (tem, Qt);
+
+ tem = Fcompare_strings (completion, Qnil, Qnil, string, Qnil, Qnil, Qnil);
+ if (!EQ (tem, Qt))
+ /* Rewrite the user's input. */
{
- Ferase_field (make_number (ZV)); /* Some completion happened */
+ Fdelete_field (make_number (ZV)); /* Some completion happened */
Finsert (1, &completion);
+
+ if (! completedp)
+ /* The case of the string changed, but that's all. We're not
+ sure whether this is a unique completion or not, so try again
+ using the real case (this shouldn't recurse again, because
+ the next time try-completion will return either `t' or the
+ exact string). */
+ {
+ UNGCPRO;
+ return do_completion ();
+ }
}
/* It did find a match. Do we match some possibility exactly now? */
- tem = test_completion (Ffield_string(ZV));
+ tem = test_completion (Ffield_string (make_number (ZV)));
if (NILP (tem))
{
/* not an exact match */
UNGCPRO;
if (completedp)
return 5;
- else if (auto_help)
+ else if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
else
temp_echo_area_glyphs (" [Next char not unique]");
last_exact_completion = completion;
if (!NILP (last))
{
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
if (!NILP (Fequal (tem, last)))
Fminibuffer_completion_help ();
}
struct buffer *obuf = current_buffer;
Fset_buffer (XWINDOW (window)->buffer);
- tem = Fpos_visible_in_window_p (make_number (ZV), window);
+ tem = Fpos_visible_in_window_p (make_number (ZV), window, Qnil);
if (! NILP (tem))
/* If end is in view, scroll up to the beginning. */
Fset_window_start (window, make_number (BEGV), Qnil);
return Qnil;
case 1:
+ if (PT != ZV)
+ Fgoto_char (make_number (ZV));
temp_echo_area_glyphs (" [Sole completion]");
break;
case 3:
+ if (PT != ZV)
+ Fgoto_char (make_number (ZV));
temp_echo_area_glyphs (" [Complete, but not unique]");
break;
}
Lisp_Object val;
/* Allow user to specify null string */
- if (Ffield_beginning (ZV, Qnil) == ZV)
+ if (XINT (Ffield_beginning (make_number (ZV), Qnil)) == ZV)
goto exit;
- if (!NILP (test_completion (Ffield_string (ZV))))
+ if (!NILP (test_completion (Ffield_string (make_number (ZV)))))
goto exit;
/* Call do_completion, but ignore errors. */
return Qnil;
}
exit:
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
/* NOTREACHED */
}
/* 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 (Ffield_string (ZV),
+ completion = Ftry_completion (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
if (NILP (completion))
return Qnil;
#if 0 /* How the below code used to look, for reference. */
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
b = XSTRING (tem)->data;
i = ZV - 1 - XSTRING (completion)->size;
p = XSTRING (completion)->data;
int buffer_nchars, completion_nchars;
CHECK_STRING (completion, 0);
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
GCPRO2 (completion, tem);
/* If reading a file name,
expand any $ENVVAR refs in the buffer and in TEM. */
if (! EQ (substituted, tem))
{
tem = substituted;
- Ferase_field (make_number (ZV));
+ Fdelete_field (make_number (ZV));
insert_from_string (tem, 0, 0, XSTRING (tem)->size,
STRING_BYTES (XSTRING (tem)), 0);
}
}
#endif /* Rewritten code */
- prompt_end_charpos = Ffield_beginning (make_number (ZV), Qnil);
+ prompt_end_charpos = XINT (Ffield_beginning (make_number (ZV), Qnil));
{
int prompt_end_bytepos;
if (i == XSTRING (completion)->size)
{
GCPRO1 (completion);
- tem = Ftry_completion (concat2 (Ffield_string (ZV), build_string (" ")),
+ tem = Ftry_completion (concat2 (Ffield_string (make_number (ZV)), build_string (" ")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
{
GCPRO1 (completion);
tem =
- Ftry_completion (concat2 (Ffield_string (ZV), build_string ("-")),
+ Ftry_completion (concat2 (Ffield_string (make_number (ZV)), build_string ("-")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
if (i == ZV - prompt_end_charpos)
{
- if (auto_help)
+ if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
return Qnil;
}
/* Otherwise insert in minibuffer the chars we got */
- Ferase_field (make_number (ZV));
+ Fdelete_field (make_number (ZV));
insert_from_string (completion, 0, 0, i, i_byte, 1);
return Qt;
}
int length;
Lisp_Object startpos, endpos;
+ startpos = Qnil;
+
elt = Fcar (tail);
/* Compute the length of this element. */
if (CONSP (elt))
Lisp_Object completions;
message ("Making completion list...");
- completions = Fall_completions (Ffield_string (ZV),
+ completions = Fall_completions (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate,
Qt);
else
bitch_at_user ();
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
}
DEFUN ("exit-minibuffer", Fexit_minibuffer, Sexit_minibuffer, 0, 0, "",
"Terminate this minibuffer argument.")
()
{
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
}
DEFUN ("minibuffer-depth", Fminibuffer_depth, Sminibuffer_depth, 0, 0, 0,
property of a history variable overrides this default.");
XSETFASTINT (Vhistory_length, 30);
- DEFVAR_BOOL ("completion-auto-help", &auto_help,
+ DEFVAR_LISP ("completion-auto-help", &Vcompletion_auto_help,
"*Non-nil means automatically provide help for invalid completion input.");
- auto_help = 1;
+ Vcompletion_auto_help = Qt;
DEFVAR_BOOL ("completion-ignore-case", &completion_ignore_case,
"Non-nil means don't consider case significant in completion.");
with completion; they always discard text properties.");
minibuffer_allow_text_properties = 0;
+ DEFVAR_LISP ("minibuffer-prompt-properties", &Vminibuffer_prompt_properties,
+ "Text properties that are added to minibuffer prompts.\n\
+These are in addition to the basic `field' property, and stickiness\n\
+properties.");
+ /* We use `intern' here instead of Qread_only to avoid
+ initialization-order problems. */
+ Vminibuffer_prompt_properties
+ = Fcons (intern ("read-only"), Fcons (Qt, Qnil));
+
defsubr (&Sset_minibuffer_window);
defsubr (&Sread_from_minibuffer);
defsubr (&Seval_minibuffer);