/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,93,94,95,96,97,98,99,2000,01,03
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
Lisp_Object last_minibuf_string;
-/* Nonzero means let functions called when within a minibuffer
+/* Nonzero means let functions called when within a minibuffer
invoke recursive minibuffers (to read arguments, or whatever) */
int enable_recursive_minibuffers;
Lisp_Object Qminibuffer_exit_hook, Vminibuffer_exit_hook;
/* Function to call to read a buffer name. */
-Lisp_Object Vread_buffer_function;
+Lisp_Object Vread_buffer_function;
/* Nonzero means completion ignores case. */
{
struct frame *sf = XFRAME (selected_frame);
Lisp_Object buffer;
-
+
/* I don't think that any frames may validly have a null minibuffer
window anymore. */
if (NILP (sf->minibuffer_window))
init_window_once. That window doesn't have a buffer. */
buffer = XWINDOW (minibuf_window)->buffer;
if (BUFFERP (buffer))
- Fset_window_buffer (sf->minibuffer_window, buffer);
+ Fset_window_buffer (sf->minibuffer_window, buffer, Qnil);
minibuf_window = sf->minibuffer_window;
}
struct gcpro gcpro1, gcpro2;
Lisp_Object expr_and_pos;
int pos;
-
+
GCPRO2 (val, defalt);
-
- if (STRINGP (val) && XSTRING (val)->size == 0
+
+ if (STRINGP (val) && SCHARS (val) == 0
&& STRINGP (defalt))
val = defalt;
-
+
expr_and_pos = Fread_from_string (val, Qnil, Qnil);
pos = XINT (Fcdr (expr_and_pos));
- if (pos != XSTRING (val)->size)
+ if (pos != SCHARS (val))
{
/* Ignore trailing whitespace; any other trailing junk
is an error. */
int i;
pos = string_char_to_byte (val, pos);
- for (i = pos; i < STRING_BYTES (XSTRING (val)); i++)
+ for (i = pos; i < SBYTES (val); i++)
{
- int c = XSTRING (val)->data[i];
+ int c = SREF (val, i);
if (c != ' ' && c != '\t' && c != '\n')
error ("Trailing garbage following expression");
}
}
-
+
val = Fcar (expr_and_pos);
RETURN_UNGCPRO (val);
}
char *line, *s;
Lisp_Object val;
- fprintf (stdout, "%s", XSTRING (prompt)->data);
+ fprintf (stdout, "%s", SDATA (prompt));
fflush (stdout);
val = Qnil;
if (s)
{
len = strlen (line);
-
+
if (len > 0 && line[len - 1] == '\n')
line[--len] = '\0';
-
+
val = build_string (line);
xfree (line);
}
xfree (line);
error ("Error reading from stdin");
}
-
+
/* If Lisp form desired instead of string, parse it. */
if (expflag)
val = string_to_object (val, defalt);
-
+
return val;
}
+\f
+DEFUN ("minibufferp", Fminibufferp,
+ Sminibufferp, 0, 1, 0,
+ doc: /* Return t if BUFFER is a minibuffer.
+No argument or nil as argument means use current buffer as BUFFER.*/)
+ (buffer)
+ Lisp_Object buffer;
+{
+ Lisp_Object tem;
+
+ if (NILP (buffer))
+ buffer = Fcurrent_buffer ();
+ else if (STRINGP (buffer))
+ buffer = Fget_buffer (buffer);
+ else
+ CHECK_BUFFER (buffer);
+ tem = Fmemq (buffer, Vminibuffer_list);
+ return ! NILP (tem) ? Qt : Qnil;
+}
DEFUN ("minibuffer-prompt-end", Fminibuffer_prompt_end,
Sminibuffer_prompt_end, 0, 0, 0,
()
{
/* This function is written to be most efficient when there's a prompt. */
- Lisp_Object beg = make_number (BEGV);
- Lisp_Object end = Ffield_end (beg, Qnil, Qnil);
-
+ Lisp_Object beg, end, tem;
+ beg = make_number (BEGV);
+
+ tem = Fmemq (Fcurrent_buffer (), Vminibuffer_list);
+ if (NILP (tem))
+ return beg;
+
+ end = Ffield_end (beg, Qnil, Qnil);
+
if (XINT (end) == ZV && NILP (Fget_char_property (beg, Qfield, Qnil)))
return beg;
else
return Qnil;
}
+/* Get the text in the minibuffer before point.
+ That is what completion commands operate on. */
+Lisp_Object
+minibuffer_completion_contents ()
+{
+ int prompt_end = XINT (Fminibuffer_prompt_end ());
+ if (PT < prompt_end)
+ error ("Cannot do completion in the prompt");
+ return make_buffer_string (prompt_end, PT, 1);
+}
+\f
/* Read from the minibuffer using keymap MAP, initial contents INITIAL
(a string), putting point minus BACKUP_N bytes from the end of INITIAL,
prompting with PROMPT (a string), using history list HISTVAR
match the front of that history list exactly. The value is pushed onto
the list as the string that was read.
- DEFALT specifies te default value for the sake of history commands.
+ DEFALT specifies the default value for the sake of history commands.
If ALLOW_PROPS is nonzero, we do not throw away text properties.
int inherit_input_method;
{
Lisp_Object val;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
Lisp_Object enable_multibyte;
+
+ /* String to add to the history. */
+ Lisp_Object histstring;
+
extern Lisp_Object Qfront_sticky;
extern Lisp_Object Qrear_nonsticky;
GCPRO5 (map, initial, val, ambient_dir, input_method);
if (!STRINGP (prompt))
- prompt = build_string ("");
+ prompt = empty_string;
if (!enable_recursive_minibuffers
&& minibuf_level > 0)
val = read_minibuf_noninteractive (map, initial, prompt, backup_n,
expflag, histvar, histpos, defalt,
allow_props, inherit_input_method);
+ UNGCPRO;
return unbind_to (count, val);
}
Vminibuf_scroll_window = selected_window;
if (minibuf_level == 1 || !EQ (minibuf_window, selected_window))
- Vminibuf_selected_window = selected_window;
- Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
- Fselect_window (minibuf_window);
+ minibuf_selected_window = selected_window;
+ Fset_window_buffer (minibuf_window, Fcurrent_buffer (), Qnil);
+ Fselect_window (minibuf_window, Qnil);
XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0);
Fmake_local_variable (Qprint_escape_newlines);
/* Erase the buffer. */
{
- int count1 = BINDING_STACK_SIZE ();
+ int count1 = SPECPDL_INDEX ();
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
Ferase_buffer ();
Fadd_text_properties (make_number (BEG), make_number (PT),
Vminibuffer_prompt_properties, Qnil);
}
-
- minibuf_prompt_width = current_column ();
-
+
+ minibuf_prompt_width = (int) current_column (); /* iftc */
+
/* If appropriate, copy enable-multibyte-characters into the minibuffer. */
if (inherit_input_method)
current_buffer->enable_multibyte_characters = enable_multibyte;
last_minibuf_string = val;
- /* Add the value to the appropriate history list unless it is empty. */
- if (XSTRING (val)->size != 0
- && SYMBOLP (Vminibuffer_history_variable))
+ /* Choose the string to add to the history. */
+ if (SCHARS (val) != 0)
+ histstring = val;
+ else if (STRINGP (defalt))
+ histstring = defalt;
+ else
+ histstring = Qnil;
+
+ /* Add the value to the appropriate history list, if any. */
+ if (SYMBOLP (Vminibuffer_history_variable)
+ && !NILP (histstring))
{
/* 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. */
/* 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)))))
+ /* Don't duplicate the most recent entry in the history. */
+ && NILP (Fequal (histstring, Fcar (histval)))))
{
Lisp_Object length;
- histval = Fcons (last_minibuf_string, histval);
+ histval = Fcons (histstring, histval);
Fset (Vminibuffer_history_variable, histval);
/* Truncate if requested. */
/* The appropriate frame will get selected
in set-window-configuration. */
- RETURN_UNGCPRO (unbind_to (count, val));
+ UNGCPRO;
+ return unbind_to (count, val);
}
/* Return a buffer to be used as the minibuffer at depth `depth'.
}
else
{
- int count = specpdl_ptr - specpdl;
-
+ int count = SPECPDL_INDEX ();
+ /* `reset_buffer' blindly sets the list of overlays to NULL, so we
+ have to empty the list, otherwise we end up with overlays that
+ think they belong to this buffer while the buffer doesn't know about
+ them any more. */
+ delete_all_overlays (XBUFFER (buf));
reset_buffer (XBUFFER (buf));
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
Fset_buffer (buf);
/* Erase the minibuffer we were using at this level. */
{
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
/* Prevent error in erase-buffer. */
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
/* Convert to distance from end of input. */
if (XINT (position) < 1)
/* A number too small means the beginning of the string. */
- pos = - XSTRING (initial_contents)->size;
+ pos = - SCHARS (initial_contents);
else
- pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
+ pos = XINT (position) - 1 - SCHARS (initial_contents);
}
}
val = Fread_from_minibuffer (prompt, initial_input, Qnil,
Qnil, history, default_value,
inherit_input_method);
- if (STRINGP (val) && XSTRING (val)->size == 0 && ! NILP (default_value))
+ if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (default_value))
val = default_value;
return val;
}
if (NILP (default_value))
default_string = Qnil;
else if (SYMBOLP (default_value))
- XSETSTRING (default_string, XSYMBOL (default_value)->name);
+ default_string = SYMBOL_NAME (default_value);
else
default_string = default_value;
-
+
name = Fcompleting_read (prompt, Vobarray, Qcommandp, Qt,
Qnil, Qnil, default_string, Qnil);
if (NILP (name))
DEFUN ("read-variable", Fread_variable, Sread_variable, 1, 2, 0,
doc: /* Read the name of a user variable and return it as a symbol.
Prompt with PROMPT. By default, return DEFAULT-VALUE.
-A user variable is one whose documentation starts with a `*' character. */)
+A user variable is one for which `user-variable-p' returns non-nil. */)
(prompt, default_value)
Lisp_Object prompt, default_value;
{
if (NILP (default_value))
default_string = Qnil;
else if (SYMBOLP (default_value))
- XSETSTRING (default_string, XSYMBOL (default_value)->name);
+ default_string = SYMBOL_NAME (default_value);
else
default_string = default_value;
-
+
name = Fcompleting_read (prompt, Vobarray,
Quser_variable_p, Qt,
Qnil, Qnil, default_string, Qnil);
Lisp_Object prompt, def, require_match;
{
Lisp_Object args[4];
-
+
if (BUFFERP (def))
def = XBUFFER (def)->name;
DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
doc: /* Return common substring of all completions of STRING in ALIST.
-Each car of each element of ALIST is tested to see if it begins with STRING.
+Each car of each element of ALIST (or each element if it is not a cons cell)
+is tested to see if it begins with STRING.
All that match are compared together; the longest initial sequence
common to all matches is returned as a string.
If there is no match at all, nil is returned.
For a unique match which is exact, t is returned.
-ALIST can be an obarray instead of an alist.
-Then the print names of all symbols in the obarray are the possible matches.
+If ALIST is a hash-table, all the string keys are the possible matches.
+If ALIST is an obarray, the names of all symbols in the obarray
+are the possible matches.
ALIST can also be a function to do the completion itself.
It receives three arguments: the values STRING, PREDICATE and nil.
it is used to test each possible match.
The match is a candidate only if PREDICATE returns non-nil.
The argument given to PREDICATE is the alist element
-or the symbol from the obarray.
+or the symbol from the obarray. If ALIST is a hash-table,
+predicate is called with two arguments: the key and the value.
Additionally to this predicate, `completion-regexp-list'
is used to further constrain the set of candidates. */)
(string, alist, predicate)
int bestmatchsize = 0;
/* These are in bytes, too. */
int compare, matchsize;
- int list = CONSP (alist) || NILP (alist);
+ int type = HASH_TABLE_P (alist) ? 3
+ : VECTORP (alist) ? 2
+ : NILP (alist) || (CONSP (alist)
+ && (!SYMBOLP (XCAR (alist))
+ || NILP (XCAR (alist))));
int index = 0, obsize = 0;
int matchcount = 0;
Lisp_Object bucket, zero, end, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
CHECK_STRING (string);
- if (!list && !VECTORP (alist))
+ if (type == 0)
return call3 (alist, string, predicate, Qnil);
bestmatch = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
- if (! list)
+ if (type == 2)
{
- index = 0;
obsize = XVECTOR (alist)->size;
bucket = XVECTOR (alist)->contents[index];
}
while (1)
{
- /* Get the next element of the alist or obarray. */
+ /* Get the next element of the alist, obarray, or hash-table. */
/* Exit the loop if the elements are all used up. */
/* elt gets the alist element or symbol.
eltstring gets the name to check as a completion. */
- if (list)
+ if (type == 1)
{
- if (NILP (tail))
+ if (!CONSP (tail))
break;
- elt = Fcar (tail);
- eltstring = Fcar (elt);
- tail = Fcdr (tail);
+ elt = XCAR (tail);
+ eltstring = CONSP (elt) ? XCAR (elt) : elt;
+ tail = XCDR (tail);
}
- else
+ else if (type == 2)
{
if (XFASTINT (bucket) != 0)
{
continue;
}
}
+ else /* if (type == 3) */
+ {
+ while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist))
+ && NILP (HASH_HASH (XHASH_TABLE (alist), index)))
+ index++;
+ if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist)))
+ break;
+ else
+ elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++);
+ }
/* Is this element a possible completion? */
if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
+ && SCHARS (string) <= SCHARS (eltstring)
&& (tem = Fcompare_strings (eltstring, make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
string, make_number (0), Qnil,
completion_ignore_case ?Qt : Qnil),
EQ (Qt, tem)))
if (!NILP (predicate))
{
if (EQ (predicate, Qcommandp))
- tem = Fcommandp (elt);
+ tem = Fcommandp (elt, Qnil);
else
{
GCPRO4 (tail, string, eltstring, bestmatch);
- tem = call1 (predicate, elt);
+ tem = type == 3
+ ? call2 (predicate, elt,
+ HASH_VALUE (XHASH_TABLE (alist), index - 1))
+ : call1 (predicate, elt);
UNGCPRO;
}
if (NILP (tem)) continue;
/* Update computation of how much all possible completions match */
- matchcount++;
if (NILP (bestmatch))
{
+ matchcount = 1;
bestmatch = eltstring;
- bestmatchsize = XSTRING (eltstring)->size;
+ bestmatchsize = SCHARS (eltstring);
}
else
{
- compare = min (bestmatchsize, XSTRING (eltstring)->size);
+ compare = min (bestmatchsize, SCHARS (eltstring));
tem = Fcompare_strings (bestmatch, make_number (0),
make_number (compare),
eltstring, make_number (0),
matchsize = XINT (tem) - 1;
if (matchsize < 0)
+ /* When can this happen ? -stef */
matchsize = compare;
if (completion_ignore_case)
{
use it as the best match rather than one that is not an
exact match. This way, we get the case pattern
of the actual match. */
- if ((matchsize == XSTRING (eltstring)->size
- && matchsize < XSTRING (bestmatch)->size)
+ if ((matchsize == SCHARS (eltstring)
+ && matchsize < SCHARS (bestmatch))
||
/* If there is more than one exact match ignoring case,
and one of them is exact including case,
/* If there is no exact match ignoring case,
prefer a match that does not change the case
of the input. */
- ((matchsize == XSTRING (eltstring)->size)
+ ((matchsize == SCHARS (eltstring))
==
- (matchsize == XSTRING (bestmatch)->size)
+ (matchsize == SCHARS (bestmatch))
&& (tem = Fcompare_strings (eltstring, make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
string, make_number (0),
Qnil,
Qnil),
EQ (Qt, tem))
&& (tem = Fcompare_strings (bestmatch, make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
string, make_number (0),
Qnil,
Qnil),
! EQ (Qt, tem))))
bestmatch = eltstring;
}
+ if (bestmatchsize != SCHARS (eltstring)
+ || bestmatchsize != matchsize)
+ /* Don't count the same string multiple times. */
+ matchcount++;
bestmatchsize = matchsize;
+ if (matchsize <= SCHARS (string)
+ && matchcount > 1)
+ /* No need to look any further. */
+ break;
}
}
}
/* If we are ignoring case, and there is no exact match,
and no additional text was supplied,
don't change the case of what the user typed. */
- if (completion_ignore_case && bestmatchsize == XSTRING (string)->size
- && XSTRING (bestmatch)->size > bestmatchsize)
+ if (completion_ignore_case && bestmatchsize == SCHARS (string)
+ && SCHARS (bestmatch) > bestmatchsize)
return minibuf_conform_representation (string, bestmatch);
/* Return t if the supplied string is an exact match (counting case);
it does not require any change to be made. */
- if (matchcount == 1 && bestmatchsize == XSTRING (string)->size
+ if (matchcount == 1 && bestmatchsize == SCHARS (string)
&& (tem = Fcompare_strings (bestmatch, make_number (0),
make_number (bestmatchsize),
string, make_number (0),
\f
DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 4, 0,
doc: /* Search for partial matches to STRING in ALIST.
-Each car of each element of ALIST is tested to see if it begins with STRING.
+Each car of each element of ALIST (or each element if it is not a cons cell)
+is tested to see if it begins with STRING.
The value is a list of all the strings from ALIST that match.
-ALIST can be an obarray instead of an alist.
-Then the print names of all symbols in the obarray are the possible matches.
+If ALIST is a hash-table, all the string keys are the possible matches.
+If ALIST is an obarray, the names of all symbols in the obarray
+are the possible matches.
ALIST can also be a function to do the completion itself.
It receives three arguments: the values STRING, PREDICATE and t.
it is used to test each possible match.
The match is a candidate only if PREDICATE returns non-nil.
The argument given to PREDICATE is the alist element
-or the symbol from the obarray.
+or the symbol from the obarray. If ALIST is a hash-table,
+predicate is called with two arguments: the key and the value.
Additionally to this predicate, `completion-regexp-list'
is used to further constrain the set of candidates.
{
Lisp_Object tail, elt, eltstring;
Lisp_Object allmatches;
- int list = CONSP (alist) || NILP (alist);
+ int type = HASH_TABLE_P (alist) ? 3
+ : VECTORP (alist) ? 2
+ : NILP (alist) || (CONSP (alist)
+ && (!SYMBOLP (XCAR (alist))
+ || NILP (XCAR (alist))));
int index = 0, obsize = 0;
Lisp_Object bucket, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
CHECK_STRING (string);
- if (!list && !VECTORP (alist))
- {
- return call3 (alist, string, predicate, Qt);
- }
+ if (type == 0)
+ return call3 (alist, string, predicate, Qt);
allmatches = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
- if (! list)
+ if (type == 2)
{
- index = 0;
obsize = XVECTOR (alist)->size;
bucket = XVECTOR (alist)->contents[index];
}
while (1)
{
- /* Get the next element of the alist or obarray. */
+ /* Get the next element of the alist, obarray, or hash-table. */
/* Exit the loop if the elements are all used up. */
/* elt gets the alist element or symbol.
eltstring gets the name to check as a completion. */
- if (list)
+ if (type == 1)
{
- if (NILP (tail))
+ if (!CONSP (tail))
break;
- elt = Fcar (tail);
- eltstring = Fcar (elt);
- tail = Fcdr (tail);
+ elt = XCAR (tail);
+ eltstring = CONSP (elt) ? XCAR (elt) : elt;
+ tail = XCDR (tail);
}
- else
+ else if (type == 2)
{
if (XFASTINT (bucket) != 0)
{
continue;
}
}
+ else /* if (type == 3) */
+ {
+ while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist))
+ && NILP (HASH_HASH (XHASH_TABLE (alist), index)))
+ index++;
+ if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist)))
+ break;
+ else
+ elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++);
+ }
/* Is this element a possible completion? */
if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
+ && SCHARS (string) <= SCHARS (eltstring)
/* If HIDE_SPACES, reject alternatives that start with space
unless the input starts with space. */
- && ((STRING_BYTES (XSTRING (string)) > 0
- && XSTRING (string)->data[0] == ' ')
- || XSTRING (eltstring)->data[0] != ' '
+ && ((SBYTES (string) > 0
+ && SREF (string, 0) == ' ')
+ || SREF (eltstring, 0) != ' '
|| NILP (hide_spaces))
&& (tem = Fcompare_strings (eltstring, make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
string, make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
completion_ignore_case ? Qt : Qnil),
EQ (Qt, tem)))
{
if (!NILP (predicate))
{
if (EQ (predicate, Qcommandp))
- tem = Fcommandp (elt);
+ tem = Fcommandp (elt, Qnil);
else
{
GCPRO4 (tail, eltstring, allmatches, string);
- tem = call1 (predicate, elt);
+ tem = type == 3
+ ? call2 (predicate, elt,
+ HASH_VALUE (XHASH_TABLE (alist), index - 1))
+ : call1 (predicate, elt);
UNGCPRO;
}
if (NILP (tem)) continue;
This feature is deprecated--it is best to pass nil for INITIAL-INPUT
and supply the default value DEF instead. The user can yank the
default value into the minibuffer easily using \\[next-history-element].
-
+
HIST, if non-nil, specifies a history list
and optionally the initial position in the list.
It can be a symbol, which is the history list variable to use,
and HISTPOS is the initial position (the position in the list
which INITIAL-INPUT corresponds to).
Positions are counted starting from 1 at the beginning of the list.
+ The variable `history-length' controls the maximum length of a
+ history list.
+
DEF, if non-nil, is the default value.
If INHERIT-INPUT-METHOD is non-nil, the minibuffer inherits
Lisp_Object val, histvar, histpos, position;
Lisp_Object init;
int pos = 0;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
struct gcpro gcpro1;
init = initial_input;
specbind (Qminibuffer_completion_table, table);
specbind (Qminibuffer_completion_predicate, predicate);
specbind (Qminibuffer_completion_confirm,
- EQ (require_match, Qt) ? Qnil : Qt);
+ EQ (require_match, Qt) ? Qnil : require_match);
last_exact_completion = Qnil;
position = Qnil;
{
CHECK_NUMBER (position);
/* Convert to distance from end of input. */
- pos = XINT (position) - XSTRING (init)->size;
+ pos = XINT (position) - SCHARS (init);
}
}
histvar, histpos, def, 0,
!NILP (inherit_input_method));
- if (STRINGP (val) && XSTRING (val)->size == 0 && ! NILP (def))
+ if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (def))
val = def;
RETURN_UNGCPRO (unbind_to (count, val));
}
\f
Lisp_Object Fminibuffer_completion_help ();
-Lisp_Object assoc_for_completion ();
+Lisp_Object Fassoc_string ();
/* Test whether TXT is an exact completion. */
-Lisp_Object
-test_completion (txt)
- Lisp_Object txt;
+DEFUN ("test-completion", Ftest_completion, Stest_completion, 2, 3, 0,
+ doc: /* Return non-nil if STRING is a valid completion.
+Takes the same arguments as `all-completions' and `try-completion'.
+If ALIST is a function, it is called with three arguments:
+the values STRING, PREDICATE and `lambda'. */)
+ (string, alist, predicate)
+ Lisp_Object string, alist, predicate;
{
- Lisp_Object tem;
+ Lisp_Object regexps, tem = Qnil;
+ int i = 0;
+
+ CHECK_STRING (string);
- if (CONSP (Vminibuffer_completion_table)
- || NILP (Vminibuffer_completion_table))
- return assoc_for_completion (txt, Vminibuffer_completion_table);
- else if (VECTORP (Vminibuffer_completion_table))
+ if ((CONSP (alist) && (!SYMBOLP (XCAR (alist)) || NILP (XCAR (alist))))
+ || NILP (alist))
{
- /* Bypass intern-soft as that loses for nil */
- tem = oblookup (Vminibuffer_completion_table,
- XSTRING (txt)->data,
- XSTRING (txt)->size,
- STRING_BYTES (XSTRING (txt)));
+ tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil);
+ if NILP (tem)
+ return Qnil;
+ }
+ else if (VECTORP (alist))
+ {
+ /* Bypass intern-soft as that loses for nil. */
+ tem = oblookup (alist,
+ SDATA (string),
+ SCHARS (string),
+ SBYTES (string));
if (!SYMBOLP (tem))
{
- if (STRING_MULTIBYTE (txt))
- txt = Fstring_make_unibyte (txt);
+ if (STRING_MULTIBYTE (string))
+ string = Fstring_make_unibyte (string);
else
- txt = Fstring_make_multibyte (txt);
+ string = Fstring_make_multibyte (string);
tem = oblookup (Vminibuffer_completion_table,
- XSTRING (txt)->data,
- XSTRING (txt)->size,
- STRING_BYTES (XSTRING (txt)));
+ SDATA (string),
+ SCHARS (string),
+ SBYTES (string));
if (!SYMBOLP (tem))
return Qnil;
}
- if (!NILP (Vminibuffer_completion_predicate))
- return call1 (Vminibuffer_completion_predicate, tem);
+ }
+ else if (HASH_TABLE_P (alist))
+ {
+ i = hash_lookup (XHASH_TABLE (alist), string, NULL);
+ if (i >= 0)
+ tem = HASH_KEY (XHASH_TABLE (alist), i);
else
- return Qt;
+ return Qnil;
+ }
+ else
+ return call3 (alist, string, predicate, Qlambda);
+
+ /* Reject this element if it fails to match all the regexps. */
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCDR (regexps))
+ {
+ if (NILP (Fstring_match (XCAR (regexps),
+ SYMBOLP (tem) ? string : tem,
+ Qnil)))
+ return Qnil;
}
+
+ /* Finally, check the predicate. */
+ if (!NILP (predicate))
+ return HASH_TABLE_P (alist)
+ ? call2 (predicate, tem, HASH_VALUE (XHASH_TABLE (alist), i))
+ : call1 (predicate, tem);
else
- return call3 (Vminibuffer_completion_table, txt,
- Vminibuffer_completion_predicate, Qlambda);
+ return Qt;
}
/* returns:
Lisp_Object last;
struct gcpro gcpro1, gcpro2;
- completion = Ftry_completion (Fminibuffer_contents (),
+ completion = Ftry_completion (minibuffer_completion_contents (),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
last = last_exact_completion;
if (NILP (completion))
{
bitch_at_user ();
- temp_echo_area_glyphs (" [No match]");
+ temp_echo_area_glyphs (build_string (" [No match]"));
UNGCPRO;
return 0;
}
return 1;
}
- string = Fminibuffer_contents ();
+ string = minibuffer_completion_contents ();
/* COMPLETEDP should be true if some completion was done, which
doesn't include simply changing the case of the entered string.
if (!EQ (tem, Qt))
/* Rewrite the user's input. */
{
- Fdelete_minibuffer_contents (); /* Some completion happened */
+ int prompt_end = XINT (Fminibuffer_prompt_end ());
+ /* Some completion happened */
+
+ if (! NILP (Vminibuffer_completing_file_name)
+ && SREF (completion, SBYTES (completion) - 1) == '/'
+ && PT < ZV
+ && FETCH_CHAR (PT_BYTE) == '/')
+ {
+ del_range (prompt_end, PT + 1);
+ }
+ else
+ del_range (prompt_end, PT);
+
Finsert (1, &completion);
if (! completedp)
}
/* It did find a match. Do we match some possibility exactly now? */
- tem = test_completion (Fminibuffer_contents ());
+ tem = Ftest_completion (Fminibuffer_contents (),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate);
if (NILP (tem))
{
/* not an exact match */
else if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
else
- temp_echo_area_glyphs (" [Next char not unique]");
+ temp_echo_area_glyphs (build_string (" [Next char not unique]"));
return 6;
}
else if (completedp)
last_exact_completion = completion;
if (!NILP (last))
{
- tem = Fminibuffer_contents ();
+ tem = minibuffer_completion_contents ();
if (!NILP (Fequal (tem, last)))
Fminibuffer_completion_help ();
}
/* Like assoc but assumes KEY is a string, and ignores case if appropriate. */
-Lisp_Object
-assoc_for_completion (key, list)
+DEFUN ("assoc-string", Fassoc_string, Sassoc_string, 2, 3, 0,
+ doc: /* Like `assoc' but specifically for strings.
+Unibyte strings are converted to multibyte for comparison.
+And case is ignored if CASE-FOLD is non-nil.
+As opposed to `assoc', it will also match an entry consisting of a single
+string rather than a cons cell whose car is a string. */)
+ (key, list, case_fold)
register Lisp_Object key;
- Lisp_Object list;
+ Lisp_Object list, case_fold;
{
register Lisp_Object tail;
{
register Lisp_Object elt, tem, thiscar;
elt = Fcar (tail);
- if (!CONSP (elt)) continue;
- thiscar = Fcar (elt);
+ thiscar = CONSP (elt) ? XCAR (elt) : elt;
if (!STRINGP (thiscar))
continue;
tem = Fcompare_strings (thiscar, make_number (0), Qnil,
key, make_number (0), Qnil,
- completion_ignore_case ? Qt : Qnil);
+ case_fold);
if (EQ (tem, Qt))
return elt;
QUIT;
case 1:
if (PT != ZV)
Fgoto_char (make_number (ZV));
- temp_echo_area_glyphs (" [Sole completion]");
+ temp_echo_area_glyphs (build_string (" [Sole completion]"));
break;
case 3:
if (PT != ZV)
Fgoto_char (make_number (ZV));
- temp_echo_area_glyphs (" [Complete, but not unique]");
+ temp_echo_area_glyphs (build_string (" [Complete, but not unique]"));
break;
}
if (XINT (Fminibuffer_prompt_end ()) == ZV)
goto exit;
- if (!NILP (test_completion (Fminibuffer_contents ())))
+ if (!NILP (Ftest_completion (Fminibuffer_contents (),
+ Vminibuffer_completion_table,
+ Vminibuffer_completion_predicate)))
goto exit;
/* Call do_completion, but ignore errors. */
+ SET_PT (ZV);
val = internal_condition_case (complete_and_exit_1, Qerror,
complete_and_exit_2);
case 4:
if (!NILP (Vminibuffer_completion_confirm))
{
- temp_echo_area_glyphs (" [Confirm]");
+ temp_echo_area_glyphs (build_string (" [Confirm]"));
return Qnil;
}
else
{
Lisp_Object completion, tem, tem1;
register int i, i_byte;
- register unsigned char *completion_string;
+ register const unsigned char *completion_string;
struct gcpro gcpro1, gcpro2;
- int prompt_end_charpos;
+ int prompt_end_charpos = XINT (Fminibuffer_prompt_end ());
/* 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 (Fminibuffer_contents (),
+ completion = Ftry_completion (minibuffer_completion_contents (),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
if (NILP (completion))
{
bitch_at_user ();
- temp_echo_area_glyphs (" [No match]");
+ temp_echo_area_glyphs (build_string (" [No match]"));
return Qnil;
}
if (EQ (completion, Qt))
#if 0 /* How the below code used to look, for reference. */
tem = Fminibuffer_contents ();
- b = XSTRING (tem)->data;
- i = ZV - 1 - XSTRING (completion)->size;
- p = XSTRING (completion)->data;
+ b = SDATA (tem);
+ i = ZV - 1 - SCHARS (completion);
+ p = SDATA (completion);
if (i > 0 ||
0 <= scmp (b, p, ZV - 1))
{
int buffer_nchars, completion_nchars;
CHECK_STRING (completion);
- tem = Fminibuffer_contents ();
+ tem = minibuffer_completion_contents ();
GCPRO2 (completion, tem);
/* If reading a file name,
expand any $ENVVAR refs in the buffer and in TEM. */
if (! EQ (substituted, tem))
{
tem = substituted;
- Fdelete_minibuffer_contents ();
- insert_from_string (tem, 0, 0, XSTRING (tem)->size,
- STRING_BYTES (XSTRING (tem)), 0);
+ del_range (prompt_end_charpos, PT);
+ Finsert (1, &tem);
}
}
- buffer_nchars = XSTRING (tem)->size; /* ie ZV - BEGV */
- completion_nchars = XSTRING (completion)->size;
+ buffer_nchars = SCHARS (tem); /* # chars in what we completed. */
+ completion_nchars = SCHARS (completion);
i = buffer_nchars - completion_nchars;
if (i > 0
||
{
int start_pos;
- /* Set buffer to longest match of buffer tail and completion head. */
+ /* Make buffer (before point) contain the longest match
+ of TEM's tail and COMPLETION's head. */
if (i <= 0) i = 1;
start_pos= i;
buffer_nchars -= i;
i++;
buffer_nchars--;
}
- del_range (1, i + 1);
- SET_PT_BOTH (ZV, ZV_BYTE);
+ del_range (start_pos, start_pos + buffer_nchars);
}
UNGCPRO;
}
#endif /* Rewritten code */
-
- prompt_end_charpos = XINT (Fminibuffer_prompt_end ());
{
int prompt_end_bytepos;
prompt_end_bytepos = CHAR_TO_BYTE (prompt_end_charpos);
- i = ZV - prompt_end_charpos;
- i_byte = ZV_BYTE - prompt_end_bytepos;
+ i = PT - prompt_end_charpos;
+ i_byte = PT_BYTE - prompt_end_bytepos;
}
/* If completion finds next char not unique,
consider adding a space or a hyphen. */
- if (i == XSTRING (completion)->size)
+ if (i == SCHARS (completion))
{
GCPRO1 (completion);
- tem = Ftry_completion (concat2 (Fminibuffer_contents (), build_string (" ")),
+ tem = Ftry_completion (concat2 (minibuffer_completion_contents (),
+ build_string (" ")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
{
GCPRO1 (completion);
tem =
- Ftry_completion (concat2 (Fminibuffer_contents (), build_string ("-")),
+ Ftry_completion (concat2 (minibuffer_completion_contents (),
+ build_string ("-")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
if (STRINGP (tem))
completion = tem;
}
- }
+ }
/* Now find first word-break in the stuff found by completion.
i gets index in string of where to stop completing. */
- while (i_byte < STRING_BYTES (XSTRING (completion)))
+ while (i_byte < SBYTES (completion))
{
int c;
/* If got no characters, print help for user. */
- if (i == ZV - prompt_end_charpos)
+ if (i == PT - prompt_end_charpos)
{
if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
/* Otherwise insert in minibuffer the chars we got */
- Fdelete_minibuffer_contents ();
+ if (! NILP (Vminibuffer_completing_file_name)
+ && SREF (completion, SBYTES (completion) - 1) == '/'
+ && PT < ZV
+ && FETCH_CHAR (PT_BYTE) == '/')
+ {
+ del_range (prompt_end_charpos, PT + 1);
+ }
+ else
+ del_range (prompt_end_charpos, PT);
+
insert_from_string (completion, 0, 0, i, i_byte, 1);
return Qt;
}
{
tem = XCAR (elt);
CHECK_STRING (tem);
- length = XSTRING (tem)->size;
+ length = SCHARS (tem);
tem = Fcar (XCDR (elt));
CHECK_STRING (tem);
- length += XSTRING (tem)->size;
+ length += SCHARS (tem);
}
else
{
CHECK_STRING (elt);
- length = XSTRING (elt)->size;
+ length = SCHARS (elt);
}
/* This does a bad job for narrower than usual windows.
if (BUFFERP (Vstandard_output))
{
tem = Findent_to (make_number (35), make_number (2));
-
+
column = XINT (tem);
}
else
Lisp_Object completions;
message ("Making completion list...");
- completions = Fall_completions (Fminibuffer_contents (),
+ completions = Fall_completions (minibuffer_completion_contents (),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate,
Qt);
if (NILP (completions))
{
bitch_at_user ();
- temp_echo_area_glyphs (" [No completions]");
+ temp_echo_area_glyphs (build_string (" [No completions]"));
}
else
internal_with_output_to_temp_buffer ("*Completions*",
}
\f
-/* Temporarily display the string M at the end of the current
+/* Temporarily display STRING at the end of the current
minibuffer contents. This is used to display things like
"[No Match]" when the user requests a completion for a prefix
that has no possible completions, and other quick, unobtrusive
messages. */
void
-temp_echo_area_glyphs (m)
- char *m;
+temp_echo_area_glyphs (string)
+ Lisp_Object string;
{
int osize = ZV;
int osize_byte = ZV_BYTE;
message (0);
SET_PT_BOTH (osize, osize_byte);
- insert_string (m);
+ insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), 0);
SET_PT_BOTH (opoint, opoint_byte);
Vinhibit_quit = Qt;
Fsit_for (make_number (2), Qnil, Qnil);
(string)
Lisp_Object string;
{
- temp_echo_area_glyphs (XSTRING (string)->data);
+ CHECK_STRING (string);
+ temp_echo_area_glyphs (string);
return Qnil;
}
\f
defsubr (&Sminibuffer_depth);
defsubr (&Sminibuffer_prompt);
+ defsubr (&Sminibufferp);
defsubr (&Sminibuffer_prompt_end);
defsubr (&Sminibuffer_contents);
defsubr (&Sminibuffer_contents_no_properties);
defsubr (&Stry_completion);
defsubr (&Sall_completions);
+ defsubr (&Stest_completion);
+ defsubr (&Sassoc_string);
defsubr (&Scompleting_read);
defsubr (&Sminibuffer_complete);
defsubr (&Sminibuffer_complete_word);