Annotation of 43BSD/contrib/emacs/src/minibuf.c, revision 1.1

1.1     ! root        1: /* Minibuffer input and completion.
        !             2:    Copyright (C) 1985 Richard M. Stallman.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include <ctype.h>
        !            23: #include "config.h"
        !            24: #include "lisp.h"
        !            25: #include "commands.h"
        !            26: #include "buffer.h"
        !            27: #include "window.h"
        !            28: #include "syntax.h"
        !            29: #include "dispextern.h"
        !            30: 
        !            31: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            32: 
        !            33: /* List of buffers for use as minibuffers.
        !            34:   The first element of the list is used for the outermost minibuffer invocation,
        !            35:   the next element is used for a recursive minibuffer invocation, etc.
        !            36:   The list is extended at the end as deeped minibuffer recursions are encountered. */
        !            37: Lisp_Object Vminibuffer_list;
        !            38: 
        !            39: struct minibuf_save_data
        !            40:   {
        !            41:     char *prompt;
        !            42:     int prompt_width;
        !            43:     Lisp_Object help_form;
        !            44:   };
        !            45: 
        !            46: int minibuf_save_vector_size;
        !            47: struct minibuf_save_data *minibuf_save_vector;
        !            48: 
        !            49: int auto_help;         /* Nonzero means display completion help for invalid input */
        !            50: 
        !            51: /* Fread_minibuffer leaves the input, as a string, here */
        !            52: Lisp_Object last_minibuf_string;
        !            53: 
        !            54: /* Nonzero means let functions called when within a minibuffer 
        !            55:    invoke recursive minibuffers (to read arguments, or whatever) */
        !            56: int enable_recursive_minibuffers;
        !            57: 
        !            58: /* help-form is bound to this while in the minibuffer.  */
        !            59: 
        !            60: Lisp_Object Vminibuffer_help_form;
        !            61: 
        !            62: /* Nonzero means completion ignores case.  */
        !            63: 
        !            64: int completion_ignore_case;
        !            65: 
        !            66: Lisp_Object Quser_variable_p;
        !            67: 
        !            68: /* Width in columns of current minibuffer prompt.  */
        !            69: 
        !            70: extern int minibuf_prompt_width;
        !            71: 
        !            72: /* Actual minibuffer invocation. */
        !            73: 
        !            74: void read_minibuf_string_unwind ();
        !            75: Lisp_Object get_minibuffer ();
        !            76: Lisp_Object read_minibuf ();
        !            77: 
        !            78: Lisp_Object
        !            79: read_minibuf_string (map, prefix, prompt)
        !            80:      Lisp_Object map;
        !            81:      Lisp_Object prefix;
        !            82:      Lisp_Object prompt;
        !            83: {
        !            84:   return read_minibuf (map, prefix, prompt, 0);
        !            85: }
        !            86: 
        !            87: 
        !            88: Lisp_Object
        !            89: read_minibuf (map, prefix, prompt, expflag)
        !            90:      Lisp_Object map;
        !            91:      Lisp_Object prefix;
        !            92:      Lisp_Object prompt;
        !            93:      int expflag;
        !            94: {
        !            95:   Lisp_Object val;
        !            96:   int count = specpdl_ptr - specpdl;
        !            97: 
        !            98:   if (!enable_recursive_minibuffers &&
        !            99:       (EQ (selected_window, minibuf_window)))
        !           100:     error ("Command attempted to use minibuffer while in minibuffer");
        !           101: 
        !           102:   if (MinibufDepth == minibuf_save_vector_size)
        !           103:     minibuf_save_vector =
        !           104:      (struct minibuf_save_data *) xrealloc (minibuf_save_vector,
        !           105:                      (minibuf_save_vector_size *= 2) * sizeof (struct minibuf_save_data)); 
        !           106:   minibuf_save_vector[MinibufDepth].prompt = minibuf_prompt;
        !           107:   minibuf_save_vector[MinibufDepth].help_form = Vhelp_form;
        !           108:   minibuf_save_vector[MinibufDepth].prompt_width = minibuf_prompt_width;
        !           109:   minibuf_prompt_width = 0;
        !           110: 
        !           111:   record_unwind_protect (save_window_restore, save_window_save ());
        !           112: 
        !           113:   val = bf_cur->directory;
        !           114:   Fset_buffer (get_minibuffer (MinibufDepth + 1));
        !           115:   bf_cur->directory = val;
        !           116: 
        !           117:   Fshow_buffer (minibuf_window, Fcurrent_buffer ());
        !           118:   Fselect_window (minibuf_window);
        !           119:   XFASTINT (XWINDOW (minibuf_window)->hscroll) = 0;
        !           120: 
        !           121:   Ferase_buffer ();
        !           122:   MinibufDepth++;
        !           123:   record_unwind_protect (read_minibuf_string_unwind, Qnil);
        !           124: 
        !           125:   if (!NULL (prefix))
        !           126:     Finsert (1, &prefix);
        !           127: 
        !           128:   minibuf_prompt = (char *) alloca (XSTRING (prompt)->size + 1);
        !           129:   bcopy (XSTRING (prompt)->data, minibuf_prompt, XSTRING (prompt)->size + 1);
        !           130:   minibuf_message = 0;
        !           131: 
        !           132:   Vhelp_form = Vminibuffer_help_form;
        !           133:   bf_cur->keymap = map;
        !           134:   Frecursive_edit ();
        !           135: 
        !           136:   /* If cursor is on the minibuffer line,
        !           137:      show the user we have exited by putting it in column 0.  */
        !           138:   if (cursY >= XFASTINT (XWINDOW (minibuf_window)->top)
        !           139:       && !noninteractive)
        !           140:     {
        !           141:       cursX = 0;
        !           142:       update_screen (1, 1);
        !           143:     }
        !           144: 
        !           145:   /* Make minibuffer contents into a string */
        !           146:   val = make_string (&CharAt (1), bf_s1 + bf_s2);
        !           147:   bcopy (bf_p2 + bf_s1 + 1,
        !           148:         XSTRING (val)->data + bf_s1,
        !           149:         bf_s2);
        !           150: 
        !           151:   last_minibuf_string = val;
        !           152: 
        !           153:   /* If Lisp form desired instead of string, read buffer contents */
        !           154:   if (expflag)
        !           155:     {
        !           156:       SetPoint (1);
        !           157:       val = Fread (Fcurrent_buffer ());
        !           158:     }
        !           159: 
        !           160:   unbind_to (count);
        !           161:   return val;
        !           162: }
        !           163: 
        !           164: /* Return a buffer to be used as the minibuffer at depth `depth'.
        !           165:  depth = 0 is the lowest allowed argument, and that is the value
        !           166:  used for nonrecursive minibuffer invocations */
        !           167: 
        !           168: Lisp_Object
        !           169: get_minibuffer (depth)
        !           170:      int depth;
        !           171: {
        !           172:   Lisp_Object tail, num, buf;
        !           173:   char name[14];
        !           174:   extern Lisp_Object nconc2 ();
        !           175: 
        !           176:   XFASTINT (num) = depth;
        !           177:   tail = Fnthcdr (num, Vminibuffer_list);
        !           178:   if (NULL (tail))
        !           179:     {
        !           180:       tail = Fcons (Qnil, Qnil);
        !           181:       Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
        !           182:     }
        !           183:   buf = Fcar (tail);
        !           184:   if (NULL (buf) || NULL (XBUFFER (buf)->name))
        !           185:     {
        !           186:       sprintf (name, " *Minibuf-%d*", depth);
        !           187:       buf = Fget_buffer_create (build_string (name));
        !           188:       XCONS (tail)->car = buf;
        !           189:     }
        !           190:   else
        !           191:     reset_buffer (XBUFFER (buf));
        !           192:   return buf;
        !           193: }
        !           194: 
        !           195: /* This function is called on exiting minibuffer, whether normally or not,
        !           196:  and it restores the current window, buffer, etc. */
        !           197: 
        !           198: void
        !           199: read_minibuf_string_unwind ()
        !           200: {
        !           201:   Ferase_buffer ();
        !           202: 
        !           203:   /* If this was a recursive minibuffer,
        !           204:      tie the minibuffer window back to the outer level minibuffer buffer */
        !           205:   MinibufDepth--;
        !           206:   /* Make sure minibuffer window is erased, not ignored */
        !           207:   windows_or_buffers_changed++;
        !           208:   XFASTINT (XWINDOW (minibuf_window)->last_modified) = 0;
        !           209: 
        !           210:   /* Restore prompt from outer minibuffer */
        !           211:   minibuf_prompt = minibuf_save_vector[MinibufDepth].prompt;
        !           212:   minibuf_prompt_width = minibuf_save_vector[MinibufDepth].prompt_width;
        !           213:   Vhelp_form = minibuf_save_vector[MinibufDepth].help_form;
        !           214: }
        !           215: 
        !           216: DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 4, 0,
        !           217:   "Read a string from the minibuffer, prompting with string PROMPT.\n\
        !           218: If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\
        !           219:   to be inserted into the minibuffer before reading input.\n\
        !           220: Third arg KEYMAP is a keymap to use whilst reading; the default is\n\
        !           221:   minibuffer-local-map.\n\
        !           222: If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
        !           223:   and return that object  (ie  (car (read-from-string <input-string>)))")
        !           224:   (prompt, initial_input, keymap, read)
        !           225:      Lisp_Object prompt, initial_input, keymap, read;
        !           226: {
        !           227:   CHECK_STRING (prompt, 0);
        !           228:   if (!NULL (initial_input))
        !           229:     CHECK_STRING (initial_input, 1);
        !           230:   if (NULL (keymap))
        !           231:     keymap = Vminibuffer_local_map;
        !           232:   else
        !           233:     keymap = get_keymap (keymap,2);
        !           234:   return read_minibuf (keymap, initial_input, prompt, !NULL(read));
        !           235: }
        !           236: 
        !           237: DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
        !           238:   "Return a Lisp object read using the minibuffer.\n\
        !           239: Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS\n\
        !           240: is a string to insert in the minibuffer before reading.")
        !           241:   (prompt, initial_contents)
        !           242:      Lisp_Object prompt, initial_contents;
        !           243: {
        !           244:   CHECK_STRING (prompt, 0);
        !           245:   if (!NULL (initial_contents))
        !           246:     CHECK_STRING (initial_contents, 1)
        !           247:   return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, 1);
        !           248: }
        !           249: 
        !           250: DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
        !           251:   "Return value of Lisp expression read using the minibuffer.\n\
        !           252: Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS\n\
        !           253: is a string to insert in the minibuffer before reading.")
        !           254:   (prompt, initial_contents)
        !           255:      Lisp_Object prompt, initial_contents;
        !           256: {
        !           257:   return Feval (Fread_minibuffer (prompt, initial_contents));
        !           258: }
        !           259: 
        !           260: /* Functions that use the minibuffer to read various things. */
        !           261: 
        !           262: DEFUN ("read-string", Fread_string, Sread_string, 1, 2, 0,
        !           263:   "Read a string from the minibuffer, prompting with string PROMPT.\n\
        !           264: If non-nil second arg INITIAL-INPUT is a string to insert before reading.")
        !           265:   (prompt, initial_input)
        !           266:      Lisp_Object prompt, initial_input;
        !           267: {
        !           268:   return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil);
        !           269: }
        !           270: 
        !           271: DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 2, 0,
        !           272:   "Args PROMPT and INIT, strings.  Read a string from the terminal, not allowing blanks.\n\
        !           273: Prompt with PROMPT, and provide INIT as an initial value of the input string.")
        !           274:   (prompt, init)
        !           275:      Lisp_Object prompt, init;
        !           276: {
        !           277:   CHECK_STRING (prompt, 0);
        !           278:   CHECK_STRING (init, 1);
        !           279: 
        !           280:   return read_minibuf_string (Vminibuffer_local_ns_map, init, prompt);
        !           281: }
        !           282: 
        !           283: DEFUN ("read-command", Fread_command, Sread_command, 1, 1, 0,
        !           284:   "One arg PROMPT, a string.  Read the name of a command and return as a symbol.\n\
        !           285: Prompts with PROMPT.")
        !           286:   (prompt)
        !           287:      Lisp_Object prompt;
        !           288: {
        !           289:   return Fintern (Fcompleting_read (prompt, Vobarray, Qcommandp, Qt, Qnil),
        !           290:                  Qnil);
        !           291: }
        !           292: 
        !           293: #ifdef NOTDEF
        !           294: DEFUN ("read-function", Fread_function, Sread_function, 1, 1, 0,
        !           295:   "One arg PROMPT, a string.  Read the name of a function and return as a symbol.\n\
        !           296: Prompts with PROMPT.")
        !           297:   (prompt)
        !           298:      Lisp_Object prompt;
        !           299: {
        !           300:   return Fintern (Fcompleting_read (prompt, Vobarray, Qfboundp, Qt, Qnil),
        !           301:                  Qnil);
        !           302: }
        !           303: #endif /* NOTDEF */
        !           304: 
        !           305: DEFUN ("read-variable", Fread_variable, Sread_variable, 1, 1, 0,
        !           306:   "One arg PROMPT, a string.  Read the name of a user variable and return\n\
        !           307: it as a symbol.  Prompts with PROMPT.\n\
        !           308: A user variable is one whose documentation starts with a \"*\" character.")
        !           309:   (prompt)
        !           310:      Lisp_Object prompt;
        !           311: {
        !           312:   return Fintern (Fcompleting_read (prompt, Vobarray,
        !           313:                                    Quser_variable_p, Qt, Qnil),
        !           314:                  Qnil);
        !           315: }
        !           316: 
        !           317: DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 3, 0,
        !           318:   "One arg PROMPT, a string.  Read the name of a buffer and return as a string.\n\
        !           319: Prompts with PROMPT.\n\
        !           320: Optional second arg is value to return if user enters an empty line.\n\
        !           321: If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are allowed.")
        !           322:   (prompt, def, require_match)
        !           323:      Lisp_Object prompt, def, require_match;
        !           324: {
        !           325:   Lisp_Object tem;
        !           326:   Lisp_Object args[3];
        !           327:   struct gcpro gcpro1;
        !           328: 
        !           329:   if (XTYPE (def) == Lisp_Buffer)
        !           330:     def = XBUFFER (def)->name;
        !           331:   if (!NULL (def))
        !           332:     {
        !           333:       args[0] = build_string ("%s(default %s) ");
        !           334:       args[1] = prompt;
        !           335:       args[2] = def;
        !           336:       prompt = Fformat (3, args);
        !           337:     }
        !           338:   GCPRO1 (def);
        !           339:   tem = Fcompleting_read (prompt, Vbuffer_alist, Qnil, require_match, Qnil);
        !           340:   UNGCPRO;
        !           341:   if (XSTRING (tem)->size)
        !           342:     return tem;
        !           343:   return def;
        !           344: }
        !           345: 
        !           346: DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
        !           347:   "Return common substring of all completions of STRING in ALIST.\n\
        !           348: Each car of each element of ALIST is tested to see if it begins with STRING.\n\
        !           349: All that match are compared together; the longest initial sequence\n\
        !           350: common to all matches is returned as a string.\n\
        !           351: If there is no match at all, nil is returned.\n\
        !           352: For an exact match, t is returned.\n\
        !           353: \n\
        !           354: ALIST can be an obarray instead of an alist.\n\
        !           355: Then the print names of all symbols in the obarray are the possible matches.\n\
        !           356: \n\
        !           357: If optional third argument PREDICATE is non-nil,\n\
        !           358: it is used to test each possible match.\n\
        !           359: The match is a candidate only if PREDICATE returns non-nil.\n\
        !           360: The argument given to PREDICATE is the alist element or the symbol from the obarray.")
        !           361:   (string, alist, pred)
        !           362:      Lisp_Object string, alist, pred;
        !           363: {
        !           364:   Lisp_Object bestmatch, tail, elt, eltstring;
        !           365:   int bestmatchsize;
        !           366:   int compare, matchsize;
        !           367:   int list = LISTP (alist);
        !           368:   int index, obsize;
        !           369:   int matchcount = 0;
        !           370:   Lisp_Object bucket, zero, end, tem;
        !           371: 
        !           372:   CHECK_STRING (string, 0);
        !           373:   if (!list && XTYPE (alist) != Lisp_Vector)
        !           374:     return call3 (alist, string, pred, Qnil);
        !           375: 
        !           376:   bestmatch = Qnil;
        !           377: 
        !           378:   if (list)
        !           379:     tail = alist;
        !           380:   else
        !           381:     {
        !           382:       index = 0;
        !           383:       obsize = XVECTOR (alist)->size;
        !           384:       bucket = XVECTOR (alist)->contents[index];
        !           385:     }
        !           386: 
        !           387:   while (1)
        !           388:     {
        !           389:       /* Get the next element of the alist or obarray. */
        !           390:       /* Exit the loop if the elements are all used up. */
        !           391:       /* elt gets the alist element or symbol.
        !           392:         eltstring gets the name to check as a completion. */
        !           393: 
        !           394:       if (list)
        !           395:        {
        !           396:          if (NULL (tail))
        !           397:            break;
        !           398:          elt = Fcar (tail);
        !           399:          eltstring = Fcar (elt);
        !           400:          tail = Fcdr (tail);
        !           401:        }
        !           402:       else
        !           403:        {
        !           404:          if (XSYMBOL (bucket))
        !           405:            {
        !           406:              elt = bucket;
        !           407:              eltstring = Fsymbol_name (elt);
        !           408:              XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
        !           409:            }
        !           410:          else if (++index >= obsize)
        !           411:            break;
        !           412:          else
        !           413:            {
        !           414:              bucket = XVECTOR (alist)->contents[index];
        !           415:              continue;
        !           416:            }
        !           417:        }
        !           418: 
        !           419:       /* Is this element a possible completion? */
        !           420: 
        !           421:       if (XTYPE (eltstring) == Lisp_String &&
        !           422:          XSTRING (string)->size <= XSTRING (eltstring)->size &&
        !           423:          -1 == scmp (XSTRING (eltstring)->data, XSTRING (string)->data, XSTRING (string)->size))
        !           424:        {
        !           425:          /* Yes. */
        !           426:          /* Ignore this element if there is a predicate and the predicate doesn't like it. */
        !           427: 
        !           428:          if (!NULL (pred))
        !           429:            {
        !           430:              if (EQ (pred, Qcommandp))
        !           431:                tem = Fcommandp (elt);
        !           432:              else
        !           433:                {
        !           434:                  tem = call1 (pred, elt);
        !           435:                }
        !           436:              if (NULL (tem)) continue;
        !           437:            }
        !           438: 
        !           439:          /* Update computation of how much all possible completions match */
        !           440: 
        !           441:          matchcount++;
        !           442:          if (NULL (bestmatch))
        !           443:            bestmatch = eltstring, bestmatchsize = XSTRING (eltstring)->size;
        !           444:          else
        !           445:            {
        !           446:              compare = min (bestmatchsize, XSTRING (eltstring)->size);
        !           447:              matchsize = scmp (XSTRING (bestmatch)->data,
        !           448:                                XSTRING (eltstring)->data,
        !           449:                                compare);
        !           450:              bestmatchsize = (matchsize >= 0) ? matchsize : compare;
        !           451:            }
        !           452:        }
        !           453:     }
        !           454: 
        !           455:   if (NULL (bestmatch))
        !           456:     return Qnil;               /* No completions found */
        !           457:   if (matchcount == 1 && bestmatchsize == XSTRING (string)->size)
        !           458:     return Qt;
        !           459: 
        !           460:   XFASTINT (zero) = 0;         /* Else extract the part in which */
        !           461:   XFASTINT (end) = bestmatchsize;           /* all completions agree */
        !           462:   return Fsubstring (bestmatch, zero, end);
        !           463: }
        !           464: 
        !           465: /* Like strncmp but ignores case differences if appropriate.
        !           466:    Also return value is different:
        !           467:    -1 if strings match,
        !           468:    else number of chars that match at the beginning.  */
        !           469: 
        !           470: #define cvt(c) (islower (c) ? c + 'A' - 'a' : c)
        !           471: 
        !           472: scmp (s1, s2, len)
        !           473:      register char *s1, *s2;
        !           474:      int len;
        !           475: {
        !           476:   register int l = len;
        !           477: 
        !           478:   if (completion_ignore_case)
        !           479:     {
        !           480:       while (l && *s1 && cvt (*s1) == cvt (*s2))
        !           481:        {
        !           482:          l--;
        !           483:          s1++;
        !           484:          s2++;
        !           485:        }
        !           486:     }
        !           487:   else
        !           488:     {
        !           489:       while (l && *s1 && *s1 == *s2)
        !           490:        {
        !           491:          l--;
        !           492:          s1++;
        !           493:          s2++;
        !           494:        }
        !           495:     }
        !           496:   if (l == 0 || (*s1 == 0 && *s2 == 0))
        !           497:     return -1;
        !           498:   else return len - l;
        !           499: }
        !           500: 
        !           501: DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 3, 0,
        !           502:   "Search for partial matches to STRING in ALIST.\n\
        !           503: Each car of each element of ALIST is tested to see if it begins with STRING.\n\
        !           504: The value is a list of all the strings from ALIST that match.\n\
        !           505: ALIST can be an obarray instead of an alist.\n\
        !           506: Then the print names of all symbols in the obarray are the possible matches.\n\
        !           507: \n\
        !           508: If optional third argument PREDICATE is non-nil,\n\
        !           509: it is used to test each possible match.\n\
        !           510: The match is a candidate only if PREDICATE returns non-nil.\n\
        !           511: The argument given to PREDICATE is the alist element or the symbol from the obarray.")
        !           512:   (string, alist, pred)
        !           513:      Lisp_Object string, alist, pred;
        !           514: {
        !           515:   Lisp_Object tail, elt, eltstring;
        !           516:   Lisp_Object allmatches;
        !           517:   int list = LISTP (alist);
        !           518:   int index, obsize;
        !           519:   Lisp_Object bucket, tem;
        !           520: 
        !           521:   CHECK_STRING (string, 0);
        !           522:   if (!list && XTYPE (alist) != Lisp_Vector)
        !           523:     {
        !           524:       return call3 (alist, string, pred, Qt);
        !           525:     }
        !           526:   allmatches = Qnil;
        !           527: 
        !           528:   if (list)
        !           529:     tail = alist;
        !           530:   else
        !           531:     {
        !           532:       index = 0;
        !           533:       obsize = XVECTOR (alist)->size;
        !           534:       bucket = XVECTOR (alist)->contents[index];
        !           535:     }
        !           536: 
        !           537:   while (1)
        !           538:     {
        !           539:       /* Get the next element of the alist or obarray. */
        !           540:       /* Exit the loop if the elements are all used up. */
        !           541:       /* elt gets the alist element or symbol.
        !           542:         eltstring gets the name to check as a completion. */
        !           543: 
        !           544:       if (list)
        !           545:        {
        !           546:          if (NULL (tail))
        !           547:            break;
        !           548:          elt = Fcar (tail);
        !           549:          eltstring = Fcar (elt);
        !           550:          tail = Fcdr (tail);
        !           551:        }
        !           552:       else
        !           553:        {
        !           554:          if (XSYMBOL (bucket))
        !           555:            {
        !           556:              elt = bucket;
        !           557:              eltstring = Fsymbol_name (elt);
        !           558:              XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
        !           559:            }
        !           560:          else if (++index >= obsize)
        !           561:            break;
        !           562:          else
        !           563:            {
        !           564:              bucket = XVECTOR (alist)->contents[index];
        !           565:              continue;
        !           566:            }
        !           567:        }
        !           568: 
        !           569:       /* Is this element a possible completion? */
        !           570: 
        !           571:       if (XTYPE (eltstring) == Lisp_String &&
        !           572:          XSTRING (string)->size <= XSTRING (eltstring)->size &&
        !           573:          XSTRING (eltstring)->data[0] != ' ' &&
        !           574:          -1 == scmp (XSTRING (eltstring)->data, XSTRING (string)->data, XSTRING (string)->size))
        !           575:        {
        !           576:          /* Yes. */
        !           577:          /* Ignore this element if there is a predicate and the predicate doesn't like it. */
        !           578: 
        !           579:          if (!NULL (pred))
        !           580:            {
        !           581:              if (EQ (pred, Qcommandp))
        !           582:                tem = Fcommandp (elt);
        !           583:              else
        !           584:                tem = call1 (pred, elt);
        !           585:              if (NULL (tem)) continue;
        !           586:            }
        !           587:          /* Ok => put it on the list. */
        !           588:          allmatches = Fcons (eltstring, allmatches);
        !           589:        }
        !           590:     }
        !           591: 
        !           592:   return Fnreverse (allmatches);
        !           593: }
        !           594: 
        !           595: Lisp_Object Vminibuffer_completion_table, Qminibuffer_completion_table;
        !           596: Lisp_Object Vminibuffer_completion_predicate, Qminibuffer_completion_predicate;
        !           597: Lisp_Object Vminibuffer_completion_confirm, Qminibuffer_completion_confirm;
        !           598: 
        !           599: DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 5, 0,
        !           600:   "Read a string in the minibuffer, with completion.\n\
        !           601: Args are PROMPT, TABLE, PREDICATE, REQUIRE-MATCH and INITIAL-INPUT.\n\
        !           602: PROMPT is a string to prompt with; normally it ends in a colon and a space.\n\
        !           603: TABLE is an alist whose elements' cars are strings, or an obarray (see try-completion).\n\
        !           604: PREDICATE limits completion to a subset of TABLE; see try-completion for details.\n\
        !           605: If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless\n\
        !           606:  the input is (or completes to) an element of TABLE.\n\
        !           607:  If it is also not t, Return does not exit if it does non-null completion.\n\
        !           608: If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
        !           609: Case is ignored if ambient value of  completion-ignore-case  is non-nil.")
        !           610:   (prompt, table, pred, require_match, init)
        !           611:      Lisp_Object prompt, table, pred, require_match, init;
        !           612: {
        !           613:   Lisp_Object val;
        !           614:   int count = specpdl_ptr - specpdl;
        !           615:   specbind (Qminibuffer_completion_table, table);
        !           616:   specbind (Qminibuffer_completion_predicate, pred);
        !           617:   specbind (Qminibuffer_completion_confirm,
        !           618:            EQ (require_match, Qt) ? Qnil : Qt);
        !           619:   val = read_minibuf_string (NULL (require_match)
        !           620:                             ? Vminibuffer_local_completion_map
        !           621:                             : Vminibuffer_local_must_match_map,
        !           622:                             init, prompt);
        !           623:   unbind_to (count);
        !           624:   return val;
        !           625: }
        !           626: 
        !           627: temp_minibuf_message (m)
        !           628:      char *m;
        !           629: {
        !           630:   int osize = NumCharacters + 1;
        !           631:   Lisp_Object oinhibit;
        !           632:   oinhibit = Vinhibit_quit;
        !           633: 
        !           634:   SetPoint (osize);
        !           635:   InsStr (m);
        !           636:   SetPoint (osize);
        !           637:   Vinhibit_quit = Qt;
        !           638:   Fsit_for (make_number (2));
        !           639:   del_range (point, NumCharacters + 1);
        !           640:   if (!NULL (Vquit_flag))
        !           641:     {
        !           642:       Vquit_flag = Qnil;
        !           643:       unread_command_char = Ctl ('g');
        !           644:     }
        !           645:   Vinhibit_quit = oinhibit;
        !           646: }
        !           647: 
        !           648: Lisp_Object Fminibuffer_completion_help ();
        !           649: 
        !           650: /* returns:
        !           651:  * 0 no possible completion
        !           652:  * 1 was already an exact and unique completion
        !           653:  * 3 was already an exact completion
        !           654:  * 4 completed to an exact completion
        !           655:  * 5 some completion happened
        !           656:  * 6 no completion happened
        !           657:  */
        !           658: int
        !           659: do_completion ()
        !           660: {
        !           661:   Lisp_Object completion, tem;
        !           662:   int completedp = 0;
        !           663: 
        !           664:   completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
        !           665:                                Vminibuffer_completion_predicate);
        !           666:   if (NULL (completion))
        !           667:     {
        !           668:       Ding ();
        !           669:       temp_minibuf_message (" [No match]");
        !           670:       return 0;
        !           671:     }
        !           672: 
        !           673:   if (EQ (completion, Qt))     /* exact and unique match */
        !           674:     return 1;
        !           675: 
        !           676:   /* compiler bug */
        !           677:   tem = Fstring_equal (completion, Fbuffer_string());
        !           678:   if (completedp = NULL (tem))
        !           679:     {
        !           680:       Ferase_buffer ();                /* Some completion happened */
        !           681:       Finsert (1, &completion);
        !           682:     }
        !           683: 
        !           684:   /* It did find a match.  Do we match some possibility exactly now? */
        !           685:   if (LISTP (Vminibuffer_completion_table))
        !           686:     tem = Fassoc (Fbuffer_string (), Vminibuffer_completion_table);
        !           687:   else if (XTYPE (Vminibuffer_completion_table) == Lisp_Vector)
        !           688:     {
        !           689:       /* the primitive used by Fintern_soft */
        !           690:       extern Lisp_Object oblookup ();
        !           691: 
        !           692:       tem = Fbuffer_string ();
        !           693:       /* Bypass intern-soft as that loses for nil */
        !           694:       tem = oblookup (Vminibuffer_completion_table,
        !           695:                      XSTRING (tem)->data, XSTRING (tem)->size);
        !           696:       if (XTYPE (tem) != Lisp_Symbol)
        !           697:        tem = Qnil;
        !           698:       else if (!NULL (Vminibuffer_completion_predicate))
        !           699:        tem = call1 (Vminibuffer_completion_predicate, tem);
        !           700:       else
        !           701:        tem = Qt;
        !           702:     }
        !           703:   else
        !           704:     tem = call3 (Vminibuffer_completion_table,
        !           705:                 Fbuffer_string (),
        !           706:                 Vminibuffer_completion_predicate,
        !           707:                 Qlambda);
        !           708: 
        !           709:   if (NULL (tem))
        !           710:     { /* not an exact match */
        !           711:       if (completedp)
        !           712:        return 5;
        !           713:       else if (auto_help)
        !           714:        Fminibuffer_completion_help ();
        !           715:       else
        !           716:        temp_minibuf_message (" [Next char not unique]");
        !           717:       return 6;
        !           718:     }
        !           719:   else
        !           720:     return (completedp ? 4 : 3);
        !           721: }
        !           722:   
        !           723: 
        !           724: DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
        !           725:   "Complete the minibuffer contents as far as possible.")
        !           726:   ()
        !           727: {
        !           728:   register int i = do_completion ();
        !           729:   switch (i)
        !           730:     {
        !           731:     case 0:
        !           732:       return Qnil;
        !           733: 
        !           734:     case 1:
        !           735:       temp_minibuf_message(" [Sole completion]");
        !           736:       break;
        !           737: 
        !           738:     case 3:
        !           739:       temp_minibuf_message(" [Complete, but not unique]");
        !           740:       break;
        !           741:     }
        !           742:   return Qt;
        !           743: }
        !           744: 
        !           745: DEFUN ("minibuffer-complete-and-exit", Fminibuffer_complete_and_exit,
        !           746:         Sminibuffer_complete_and_exit, 0, 0, "",
        !           747:   "Complete the minibuffer contents, and maybe exit.\n\
        !           748: Exit if the name is valid with no completion needed.\n\
        !           749: If name was completed to a valid match,\n\
        !           750: a repetition of this command will exit.")
        !           751:   ()
        !           752: {
        !           753:   register int i;
        !           754: 
        !           755:   /* Allow user to specify null string */
        !           756:   if (NumCharacters == 0)
        !           757:     goto exit;
        !           758: 
        !           759:   i = do_completion ();
        !           760:   switch (i)
        !           761:     {
        !           762:     case 1:
        !           763:     case 3:
        !           764:       goto exit;
        !           765: 
        !           766:     case 4:
        !           767:       if (!NULL (Vminibuffer_completion_confirm))
        !           768:        {
        !           769:          temp_minibuf_message(" [Confirm]");
        !           770:          return Qnil;
        !           771:        }
        !           772:       else
        !           773:        goto exit;
        !           774: 
        !           775:     default:
        !           776:       return Qnil;
        !           777:     }
        !           778:  exit:
        !           779:   Fthrow (Qexit, Qnil);
        !           780:   /* NOTREACHED */
        !           781: }
        !           782: 
        !           783: DEFUN ("minibuffer-complete-word", Fminibuffer_complete_word, Sminibuffer_complete_word,
        !           784:   0, 0, "",
        !           785:   "Complete the minibuffer contents at most a single word.")
        !           786:   ()
        !           787: {
        !           788:   Lisp_Object completion, tem;
        !           789:   register unsigned char *b;
        !           790:   register unsigned char *p;
        !           791:   register int i;
        !           792: 
        !           793:   /* We keep calling Fbuffer_string
        !           794:      rather than arrange for GC to hold onto a pointer to
        !           795:      one of the strings thus made.  */
        !           796: 
        !           797:   completion = Ftry_completion (Fbuffer_string (),
        !           798:                                Vminibuffer_completion_table,
        !           799:                                Vminibuffer_completion_predicate);
        !           800:   if (NULL (completion))
        !           801:     {
        !           802:       Ding ();
        !           803:       temp_minibuf_message (" [No match]");
        !           804:       return Qnil;
        !           805:     }
        !           806:   if (EQ (completion, Qt))
        !           807:     return Qnil;
        !           808: 
        !           809:   tem = Fbuffer_string ();
        !           810:   b = XSTRING (tem)->data;
        !           811:   i = NumCharacters - XSTRING (completion)->size;
        !           812:   p = XSTRING (completion)->data;
        !           813:   if (i > 0 ||
        !           814:       0 <= scmp (b, p, NumCharacters))
        !           815:     {
        !           816:       i = 1;
        !           817:       /* Set buffer to longest match of buffer tail and completion head. */
        !           818:       while (0 <= scmp (b + i, p, NumCharacters - i))
        !           819:        i++;
        !           820:       del_range (1, i + 1);
        !           821:       SetPoint (NumCharacters + 1);
        !           822:     }
        !           823: 
        !           824:   i = NumCharacters;
        !           825: 
        !           826:   /* If completion finds next char not unique,
        !           827:      consider adding a space or a hyphen */
        !           828:   if (i == XSTRING (completion)->size)
        !           829:     {
        !           830:       tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
        !           831:                             Vminibuffer_completion_table,
        !           832:                             Vminibuffer_completion_predicate);
        !           833:       if (XTYPE (tem) == Lisp_String)
        !           834:        completion = tem;
        !           835:       else
        !           836:        {
        !           837:          tem = Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
        !           838:                                 Vminibuffer_completion_table,
        !           839:                                 Vminibuffer_completion_predicate);
        !           840:          if (XTYPE (tem) == Lisp_String)
        !           841:            completion = tem;
        !           842:        }
        !           843:     }      
        !           844: 
        !           845:   /* Now find first word-break in the stuff found by completion.
        !           846:      i gets index in string of where to stop completing.  */
        !           847:   p = XSTRING (completion)->data;
        !           848: 
        !           849:   for (; i < XSTRING (completion)->size; i++)
        !           850:     if (SYNTAX (p[i]) != Sword) break;
        !           851:   if (i < XSTRING (completion)->size)
        !           852:     i = i + 1;
        !           853: 
        !           854:   /* If got no characters, print help for user.  */
        !           855: 
        !           856:   if (i == NumCharacters)
        !           857:     {
        !           858:       if (auto_help)
        !           859:        Fminibuffer_completion_help ();
        !           860:       return Qnil;
        !           861:     }
        !           862: 
        !           863:   /* Otherwise insert in minibuffer the chars we got */
        !           864: 
        !           865:   Ferase_buffer ();
        !           866:   InsCStr (p, i);
        !           867:   return Qt;
        !           868: }
        !           869: 
        !           870: Lisp_Object
        !           871: minibuffer_completion_help_1 (completions)
        !           872:      Lisp_Object completions;
        !           873: {
        !           874:   register Lisp_Object tail;
        !           875:   register int i;
        !           876:   struct buffer *old = bf_cur;
        !           877:   SetBfp (XBUFFER (Vstandard_output));
        !           878: 
        !           879:   if (NULL (completions))
        !           880:     InsStr ("There are no possible completions of what you have typed.");
        !           881:   else
        !           882:     {
        !           883:       InsStr ("Possible completions are:");
        !           884:       for (tail = completions, i = 0; !NULL (tail); tail = Fcdr (tail), i++)
        !           885:        {
        !           886:          /* this needs fixing for the case of long completions
        !           887:             and/or narrow windows */
        !           888:          /* Sadly, the window it will appear in is not known
        !           889:             until after the text has been made. */
        !           890:          if (i & 1)
        !           891:            Findent_to (make_number (35), make_number (1));
        !           892:          else
        !           893:            Fterpri (Qnil);
        !           894:          Fprinc (Fcar (tail), Qnil);
        !           895:        }
        !           896:     }
        !           897:   SetBfp (old);
        !           898:   return Qnil;
        !           899: }
        !           900: 
        !           901: DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_completion_help,
        !           902:   0, 0, "",
        !           903:   "Display a list of possible completions of the current minibuffer contents.")
        !           904:   ()
        !           905: {
        !           906:   Lisp_Object completions;
        !           907:   message ("Making completion list...");
        !           908:   completions = Fall_completions (Fbuffer_string (), Vminibuffer_completion_table,
        !           909:                                  Vminibuffer_completion_predicate);
        !           910:   minibuf_message = 0;
        !           911:   if (NULL (completions))
        !           912:     { Ding ();
        !           913:       temp_minibuf_message (" [No completions]"); }
        !           914:   else
        !           915:     internal_with_output_to_temp_buffer (" *Completions*",
        !           916:                                         minibuffer_completion_help_1,
        !           917:                                         Fsort (completions, Qstring_lessp));
        !           918:   return Qnil;
        !           919: }
        !           920: 
        !           921: DEFUN ("self-insert-and-exit", Fself_insert_and_exit, Sself_insert_and_exit, 0, 0, "",
        !           922:   "Terminate minibuffer input.")
        !           923:   ()
        !           924: {
        !           925:   SelfInsert (last_command_char);
        !           926:   Fthrow (Qexit, Qnil);
        !           927: }
        !           928: 
        !           929: DEFUN ("exit-minibuffer", Fexit_minibuffer, Sexit_minibuffer, 0, 0, "",
        !           930:   "Terminate this minibuffer argument.")
        !           931:   ()
        !           932: {
        !           933:   Fthrow (Qexit, Qnil);
        !           934: }
        !           935: 
        !           936: init_minibuf_once ()
        !           937: {
        !           938:   Vminibuffer_list = Qnil;
        !           939:   staticpro (&Vminibuffer_list);
        !           940: }
        !           941: 
        !           942: syms_of_minibuf ()
        !           943: {
        !           944:   MinibufDepth = 0;
        !           945:   minibuf_prompt = 0;
        !           946:   minibuf_save_vector_size = 5;
        !           947:   minibuf_save_vector = (struct minibuf_save_data *) malloc (5 * sizeof (struct minibuf_save_data));
        !           948: 
        !           949:   Qminibuffer_completion_table = intern ("minibuffer-completion-table");
        !           950:   staticpro (&Qminibuffer_completion_table);
        !           951: 
        !           952:   Qminibuffer_completion_confirm = intern ("minibuffer-completion-confirm");
        !           953:   staticpro (&Qminibuffer_completion_confirm);
        !           954: 
        !           955:   Qminibuffer_completion_predicate = intern ("minibuffer-completion-predicate");
        !           956:   staticpro (&Qminibuffer_completion_predicate);
        !           957: 
        !           958:   staticpro (&last_minibuf_string);
        !           959:   last_minibuf_string = Qnil;
        !           960: 
        !           961:   Quser_variable_p = intern ("user-variable-p");
        !           962:   staticpro (&Quser_variable_p);
        !           963: 
        !           964: 
        !           965: 
        !           966:   DefBoolVar ("completion-auto-help", &auto_help,
        !           967:     "*Non-nil means automatically provide help for invalid completion input.");
        !           968:   auto_help = 1;
        !           969: 
        !           970:   DefBoolVar ("completion-ignore-case", &completion_ignore_case,
        !           971:     "Non-nil means don't consider case significant in completion.");
        !           972:   completion_ignore_case = 0;
        !           973: 
        !           974:   DefBoolVar ("enable-recursive-minibuffers", &enable_recursive_minibuffers,
        !           975:     "*Non-nil means to allow minibuffers to invoke commands which use\n\
        !           976: recursive minibuffers.");
        !           977:   enable_recursive_minibuffers = 0;
        !           978: 
        !           979:   DefLispVar ("minibuffer-completion-table", &Vminibuffer_completion_table,
        !           980:     "Alist or obarray used for completion in the minibuffer.");
        !           981:   Vminibuffer_completion_table = Qnil;
        !           982: 
        !           983:   DefLispVar ("minibuffer-completion-predicate", &Vminibuffer_completion_predicate,
        !           984:     "Holds PREDICATE argument to completing-read.");
        !           985:   Vminibuffer_completion_predicate = Qnil;
        !           986: 
        !           987:   DefLispVar ("minibuffer-completion-confirm", &Vminibuffer_completion_confirm,
        !           988:     "Non-nil => demand confirmation of completion before exiting minibuffer.");
        !           989:   Vminibuffer_completion_confirm = Qnil;
        !           990: 
        !           991:   DefLispVar ("minibuffer-help-form", &Vminibuffer_help_form,
        !           992:     "Value that help-form takes on inside the minibuffer.");
        !           993:   Vminibuffer_help_form = Qnil;
        !           994: 
        !           995:   defsubr (&Sread_from_minibuffer);
        !           996:   defsubr (&Seval_minibuffer);
        !           997:   defsubr (&Sread_minibuffer);
        !           998:   defsubr (&Sread_string);
        !           999:   defalias (&Sread_string, "read-input");
        !          1000:   defsubr (&Sread_command);
        !          1001:   defsubr (&Sread_variable);
        !          1002:   defsubr (&Sread_buffer);
        !          1003:   defsubr (&Sread_no_blanks_input);
        !          1004: 
        !          1005:   defsubr (&Stry_completion);
        !          1006:   defsubr (&Sall_completions);
        !          1007:   defsubr (&Scompleting_read);
        !          1008:   defsubr (&Sminibuffer_complete);
        !          1009:   defsubr (&Sminibuffer_complete_word);
        !          1010:   defsubr (&Sminibuffer_complete_and_exit);
        !          1011:   defsubr (&Sminibuffer_completion_help);
        !          1012: 
        !          1013:   defsubr (&Sself_insert_and_exit);
        !          1014:   defsubr (&Sexit_minibuffer);
        !          1015: 
        !          1016: }
        !          1017: 
        !          1018: keys_of_minibuf ()
        !          1019: {
        !          1020:   ndefkey (Vminibuffer_local_map, Ctl ('g'), "abort-recursive-edit");
        !          1021:   ndefkey (Vminibuffer_local_map, Ctl ('m'), "exit-minibuffer");
        !          1022:   ndefkey (Vminibuffer_local_map, Ctl ('j'), "exit-minibuffer");
        !          1023: 
        !          1024:   ndefkey (Vminibuffer_local_ns_map, Ctl ('g'), "abort-recursive-edit");
        !          1025:   ndefkey (Vminibuffer_local_ns_map, Ctl ('m'), "exit-minibuffer");
        !          1026:   ndefkey (Vminibuffer_local_ns_map, Ctl ('j'), "exit-minibuffer");
        !          1027: 
        !          1028:   ndefkey (Vminibuffer_local_ns_map, ' ', "exit-minibuffer");
        !          1029:   ndefkey (Vminibuffer_local_ns_map, '\t', "exit-minibuffer");
        !          1030:   ndefkey (Vminibuffer_local_ns_map, '?', "self-insert-and-exit");
        !          1031: 
        !          1032:   ndefkey (Vminibuffer_local_completion_map, Ctl ('g'), "abort-recursive-edit");
        !          1033:   ndefkey (Vminibuffer_local_completion_map, Ctl ('m'), "exit-minibuffer");
        !          1034:   ndefkey (Vminibuffer_local_completion_map, Ctl ('j'), "exit-minibuffer");
        !          1035:   ndefkey (Vminibuffer_local_completion_map, '\t', "minibuffer-complete");
        !          1036:   ndefkey (Vminibuffer_local_completion_map, ' ', "minibuffer-complete-word");
        !          1037:   ndefkey (Vminibuffer_local_completion_map, '?', "minibuffer-completion-help");
        !          1038: 
        !          1039:   ndefkey (Vminibuffer_local_must_match_map, Ctl ('g'), "abort-recursive-edit");
        !          1040:   ndefkey (Vminibuffer_local_must_match_map, Ctl ('m'), "minibuffer-complete-and-exit");
        !          1041:   ndefkey (Vminibuffer_local_must_match_map, Ctl ('j'), "minibuffer-complete-and-exit");
        !          1042:   ndefkey (Vminibuffer_local_must_match_map, '\t', "minibuffer-complete");
        !          1043:   ndefkey (Vminibuffer_local_must_match_map, ' ', "minibuffer-complete-word");
        !          1044:   ndefkey (Vminibuffer_local_must_match_map, '?', "minibuffer-completion-help");
        !          1045: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.