summaryrefslogtreecommitdiff
path: root/lisp/complete.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2010-04-12 23:29:38 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2010-04-12 23:29:38 -0400
commit0e90e61b44d2e4d2d97d05d77a73ae74b0605fe9 (patch)
tree9f2479ee38194ead92c22ca851ac26b0aee22074 /lisp/complete.el
parent67c250041d306867a00b8eb2147fb3eb50befef7 (diff)
downloademacs-0e90e61b44d2e4d2d97d05d77a73ae74b0605fe9.tar.gz
Move complete.el to lisp/obsolete.
Diffstat (limited to 'lisp/complete.el')
-rw-r--r--lisp/complete.el1123
1 files changed, 0 insertions, 1123 deletions
diff --git a/lisp/complete.el b/lisp/complete.el
deleted file mode 100644
index 38315245f14..00000000000
--- a/lisp/complete.el
+++ /dev/null
@@ -1,1123 +0,0 @@
-;;; complete.el --- partial completion mechanism plus other goodies
-
-;; Copyright (C) 1990, 1991, 1992, 1993, 1999, 2000, 2001, 2002, 2003,
-;; 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Keywords: abbrev convenience
-;;
-;; Special thanks to Hallvard Furuseth for his many ideas and contributions.
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Extended completion for the Emacs minibuffer.
-;;
-;; The basic idea is that the command name or other completable text is
-;; divided into words and each word is completed separately, so that
-;; "M-x p-b" expands to "M-x print-buffer". If the entry is ambiguous
-;; each word is completed as much as possible and then the cursor is
-;; left at the first position where typing another letter will resolve
-;; the ambiguity.
-;;
-;; Word separators for this purpose are hyphen, space, and period.
-;; These would most likely occur in command names, Info menu items,
-;; and file names, respectively. But all word separators are treated
-;; alike at all times.
-;;
-;; This completion package replaces the old-style completer's key
-;; bindings for TAB, SPC, RET, and `?'. The old completer is still
-;; available on the Meta versions of those keys. If you set
-;; PC-meta-flag to nil, the old completion keys will be left alone
-;; and the partial completer will use the Meta versions of the keys.
-
-
-;; Usage: M-x partial-completion-mode. During completable minibuffer entry,
-;;
-;; TAB means to do a partial completion;
-;; SPC means to do a partial complete-word;
-;; RET means to do a partial complete-and-exit;
-;; ? means to do a partial completion-help.
-;;
-;; If you set PC-meta-flag to nil, then TAB, SPC, RET, and ? perform
-;; original Emacs completions, and M-TAB etc. do partial completion.
-;; To do this, put the command,
-;;
-;; (setq PC-meta-flag nil)
-;;
-;; in your .emacs file. To load partial completion automatically, put
-;;
-;; (partial-completion-mode t)
-;;
-;; in your .emacs file, too. Things will be faster if you byte-compile
-;; this file when you install it.
-;;
-;; As an extra feature, in cases where RET would not normally
-;; complete (such as `C-x b'), the M-RET key will always do a partial
-;; complete-and-exit. Thus `C-x b f.c RET' will select or create a
-;; buffer called "f.c", but `C-x b f.c M-RET' will select the existing
-;; buffer whose name matches that pattern (perhaps "filing.c").
-;; (PC-meta-flag does not affect this behavior; M-RET used to be
-;; undefined in this situation.)
-;;
-;; The regular M-TAB (lisp-complete-symbol) command also supports
-;; partial completion in this package.
-
-;; In addition, this package includes a feature for accessing include
-;; files. For example, `C-x C-f <sys/time.h> RET' reads the file
-;; /usr/include/sys/time.h. The variable PC-include-file-path is a
-;; list of directories in which to search for include files. Completion
-;; is supported in include file names.
-
-
-;;; Code:
-
-(defgroup partial-completion nil
- "Partial Completion of items."
- :prefix "pc-"
- :group 'minibuffer
- :group 'convenience)
-
-(defcustom PC-first-char 'find-file
- "Control how the first character of a string is to be interpreted.
-If nil, the first character of a string is not taken literally if it is a word
-delimiter, so that \".e\" matches \"*.e*\".
-If t, the first character of a string is always taken literally even if it is a
-word delimiter, so that \".e\" matches \".e*\".
-If non-nil and non-t, the first character is taken literally only for file name
-completion."
- :type '(choice (const :tag "delimiter" nil)
- (const :tag "literal" t)
- (other :tag "find-file" find-file))
- :group 'partial-completion)
-
-(defcustom PC-meta-flag t
- "If non-nil, TAB means PC completion and M-TAB means normal completion.
-Otherwise, TAB means normal completion and M-TAB means Partial Completion."
- :type 'boolean
- :group 'partial-completion)
-
-(defcustom PC-word-delimiters "-_. "
- "A string of characters treated as word delimiters for completion.
-Some arcane rules:
-If `]' is in this string, it must come first.
-If `^' is in this string, it must not come first.
-If `-' is in this string, it must come first or right after `]'.
-In other words, if S is this string, then `[S]' must be a valid Emacs regular
-expression (not containing character ranges like `a-z')."
- :type 'string
- :group 'partial-completion)
-
-(defcustom PC-include-file-path '("/usr/include" "/usr/local/include")
- "A list of directories in which to look for include files.
-If nil, means use the colon-separated path in the variable $INCPATH instead."
- :type '(repeat directory)
- :group 'partial-completion)
-
-(defcustom PC-disable-includes nil
- "If non-nil, include-file support in \\[find-file] is disabled."
- :type 'boolean
- :group 'partial-completion)
-
-(defvar PC-default-bindings t
- "If non-nil, default partial completion key bindings are suppressed.")
-
-(defvar PC-env-vars-alist nil
- "A list of the environment variable names and values.")
-
-
-(defun PC-bindings (bind)
- (let ((completion-map minibuffer-local-completion-map)
- (must-match-map minibuffer-local-must-match-map))
- (cond ((not bind)
- ;; These bindings are the default bindings. It would be better to
- ;; restore the previous bindings.
- (define-key read-expression-map "\e\t" 'lisp-complete-symbol)
-
- (define-key completion-map "\t" 'minibuffer-complete)
- (define-key completion-map " " 'minibuffer-complete-word)
- (define-key completion-map "?" 'minibuffer-completion-help)
-
- (define-key must-match-map "\r" 'minibuffer-complete-and-exit)
- (define-key must-match-map "\n" 'minibuffer-complete-and-exit)
-
- (define-key global-map [remap lisp-complete-symbol] nil))
- (PC-default-bindings
- (define-key read-expression-map "\e\t" 'PC-lisp-complete-symbol)
-
- (define-key completion-map "\t" 'PC-complete)
- (define-key completion-map " " 'PC-complete-word)
- (define-key completion-map "?" 'PC-completion-help)
-
- (define-key completion-map "\e\t" 'PC-complete)
- (define-key completion-map "\e " 'PC-complete-word)
- (define-key completion-map "\e\r" 'PC-force-complete-and-exit)
- (define-key completion-map "\e\n" 'PC-force-complete-and-exit)
- (define-key completion-map "\e?" 'PC-completion-help)
-
- (define-key must-match-map "\r" 'PC-complete-and-exit)
- (define-key must-match-map "\n" 'PC-complete-and-exit)
-
- (define-key must-match-map "\e\r" 'PC-complete-and-exit)
- (define-key must-match-map "\e\n" 'PC-complete-and-exit)
-
- (define-key global-map [remap lisp-complete-symbol] 'PC-lisp-complete-symbol)))))
-
-(defvar PC-do-completion-end nil
- "Internal variable used by `PC-do-completion'.")
-
-(make-variable-buffer-local 'PC-do-completion-end)
-
-(defvar PC-goto-end nil
- "Internal variable set in `PC-do-completion', used in
-`choose-completion-string-functions'.")
-
-(make-variable-buffer-local 'PC-goto-end)
-
-;;;###autoload
-(define-minor-mode partial-completion-mode
- "Toggle Partial Completion mode.
-With prefix ARG, turn Partial Completion mode on if ARG is positive.
-
-When Partial Completion mode is enabled, TAB (or M-TAB if `PC-meta-flag' is
-nil) is enhanced so that if some string is divided into words and each word is
-delimited by a character in `PC-word-delimiters', partial words are completed
-as much as possible and `*' characters are treated likewise in file names.
-
-For example, M-x p-c-m expands to M-x partial-completion-mode since no other
-command begins with that sequence of characters, and
-\\[find-file] f_b.c TAB might complete to foo_bar.c if that file existed and no
-other file in that directory begins with that sequence of characters.
-
-Unless `PC-disable-includes' is non-nil, the `<...>' sequence is interpreted
-specially in \\[find-file]. For example,
-\\[find-file] <sys/time.h> RET finds the file `/usr/include/sys/time.h'.
-See also the variable `PC-include-file-path'.
-
-Partial Completion mode extends the meaning of `completion-auto-help' (which
-see), so that if it is neither nil nor t, Emacs shows the `*Completions*'
-buffer only on the second attempt to complete. That is, if TAB finds nothing
-to complete, the first TAB just says \"Next char not unique\" and the
-second TAB brings up the `*Completions*' buffer."
- :global t :group 'partial-completion
- ;; Deal with key bindings...
- (PC-bindings partial-completion-mode)
- ;; Deal with include file feature...
- (cond ((not partial-completion-mode)
- (remove-hook 'find-file-not-found-functions 'PC-look-for-include-file))
- ((not PC-disable-includes)
- (add-hook 'find-file-not-found-functions 'PC-look-for-include-file)))
- ;; Adjust the completion selection in *Completion* buffers to the way
- ;; we work. The default minibuffer completion code only completes the
- ;; text before point and leaves the text after point alone (new in
- ;; Emacs-22). In contrast we use the whole text and we even sometimes
- ;; move point to a place before EOB, to indicate the first position where
- ;; there's a difference, so when the user uses choose-completion, we have
- ;; to trick choose-completion into replacing the whole minibuffer text
- ;; rather than only the text before point. --Stef
- (funcall
- (if partial-completion-mode 'add-hook 'remove-hook)
- 'choose-completion-string-functions
- (lambda (choice buffer &rest ignored)
- ;; When completing M-: (lisp- ) with point before the ), it is
- ;; not appropriate to go to point-max (unlike the filename case).
- (if (and (not PC-goto-end)
- (minibufferp buffer))
- (goto-char (point-max))
- ;; Need a similar hack for the non-minibuffer-case -- gm.
- (when PC-do-completion-end
- (goto-char PC-do-completion-end)
- (setq PC-do-completion-end nil)))
- (setq PC-goto-end nil)
- nil))
- ;; Build the env-completion and mapping table.
- (when (and partial-completion-mode (null PC-env-vars-alist))
- (setq PC-env-vars-alist
- (mapcar (lambda (string)
- (let ((d (string-match "=" string)))
- (cons (concat "$" (substring string 0 d))
- (and d (substring string (1+ d))))))
- process-environment))))
-
-
-(defun PC-complete ()
- "Like minibuffer-complete, but allows \"b--di\"-style abbreviations.
-For example, \"M-x b--di\" would match `byte-recompile-directory', or any
-name which consists of three or more words, the first beginning with \"b\"
-and the third beginning with \"di\".
-
-The pattern \"b--d\" is ambiguous for `byte-recompile-directory' and
-`beginning-of-defun', so this would produce a list of completions
-just like when normal Emacs completions are ambiguous.
-
-Word-delimiters for the purposes of Partial Completion are \"-\", \"_\",
-\".\", and SPC."
- (interactive)
- (if (PC-was-meta-key)
- (minibuffer-complete)
- ;; If the previous command was not this one,
- ;; never scroll, always retry completion.
- (or (eq last-command this-command)
- (setq minibuffer-scroll-window nil))
- (let ((window minibuffer-scroll-window))
- ;; If there's a fresh completion window with a live buffer,
- ;; and this command is repeated, scroll that window.
- (if (and window (window-buffer window)
- (buffer-name (window-buffer window)))
- (with-current-buffer (window-buffer window)
- (if (pos-visible-in-window-p (point-max) window)
- (set-window-start window (point-min) nil)
- (scroll-other-window)))
- (PC-do-completion nil)))))
-
-
-(defun PC-complete-word ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This can be bound to other keys, like `-' and `.', if you wish."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (if (eq last-command-event ? )
- (minibuffer-complete-word)
- (self-insert-command 1))
- (self-insert-command 1)
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-space ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This is suitable for binding to other keys which should act just like SPC."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-word)
- (insert " ")
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-and-exit)
- (PC-do-complete-and-exit)))
-
-(defun PC-force-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (let ((minibuffer-completion-confirm nil))
- (PC-do-complete-and-exit)))
-
-(defun PC-do-complete-and-exit ()
- (cond
- ((= (point-max) (minibuffer-prompt-end))
- ;; Duplicate the "bug" that Info-menu relies on...
- (exit-minibuffer))
- ((eq minibuffer-completion-confirm 'confirm)
- (if (or (eq last-command this-command)
- (test-completion (field-string)
- minibuffer-completion-table
- minibuffer-completion-predicate))
- (exit-minibuffer)
- (PC-temp-minibuffer-message " [Confirm]")))
- ((eq minibuffer-completion-confirm 'confirm-after-completion)
- ;; Similar to the above, but only if trying to exit immediately
- ;; after typing TAB (this catches most minibuffer typos).
- (if (and (memq last-command minibuffer-confirm-exit-commands)
- (not (test-completion (field-string)
- minibuffer-completion-table
- minibuffer-completion-predicate)))
- (PC-temp-minibuffer-message " [Confirm]")
- (exit-minibuffer)))
- (t
- (let ((flag (PC-do-completion 'exit)))
- (and flag
- (if (or (eq flag 'complete)
- (not minibuffer-completion-confirm))
- (exit-minibuffer)
- (PC-temp-minibuffer-message " [Confirm]")))))))
-
-
-(defun PC-completion-help ()
- "Like `minibuffer-completion-help', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-completion-help)
- (PC-do-completion 'help)))
-
-(defun PC-was-meta-key ()
- (or (/= (length (this-command-keys)) 1)
- (let ((key (aref (this-command-keys) 0)))
- (if (integerp key)
- (>= key 128)
- (not (null (memq 'meta (event-modifiers key))))))))
-
-
-(defvar PC-ignored-extensions 'empty-cache)
-(defvar PC-delims 'empty-cache)
-(defvar PC-ignored-regexp nil)
-(defvar PC-word-failed-flag nil)
-(defvar PC-delim-regex nil)
-(defvar PC-ndelims-regex nil)
-(defvar PC-delims-list nil)
-
-(defvar PC-completion-as-file-name-predicate
- (lambda () minibuffer-completing-file-name)
- "A function testing whether a minibuffer completion now will work filename-style.
-The function takes no arguments, and typically looks at the value
-of `minibuffer-completion-table' and the minibuffer contents.")
-
-;; Returns the sequence of non-delimiter characters that follow regexp in string.
-(defun PC-chunk-after (string regexp)
- (if (not (string-match regexp string))
- (let ((message "String %s didn't match regexp %s"))
- (message message string regexp)
- (error message string regexp)))
- (let ((result (substring string (match-end 0))))
- ;; result may contain multiple chunks
- (if (string-match PC-delim-regex result)
- (setq result (substring result 0 (match-beginning 0))))
- result))
-
-(defun test-completion-ignore-case (str table pred)
- "Like `test-completion', but ignores case when possible."
- ;; Binding completion-ignore-case to nil ensures, for compatibility with
- ;; standard completion, that the return value is exactly one of the
- ;; possibilities. Do this binding only if pred is nil, out of paranoia;
- ;; perhaps it is safe even if pred is non-nil.
- (if pred
- (test-completion str table pred)
- (let ((completion-ignore-case nil))
- (test-completion str table pred))))
-
-;; The following function is an attempt to work around two problems:
-
-;; (1) When complete.el was written, (try-completion "" '(("") (""))) used to
-;; return the value "". With a change from 2002-07-07 it returns t which caused
-;; `PC-lisp-complete-symbol' to fail with a "Wrong type argument: sequencep, t"
-;; error. `PC-try-completion' returns STRING in this case.
-
-;; (2) (try-completion "" '((""))) returned t before the above-mentioned change.
-;; Since `PC-chop-word' operates on the return value of `try-completion' this
-;; case might have provoked a similar error as in (1). `PC-try-completion'
-;; returns "" instead. I don't know whether this is a real problem though.
-
-;; Since `PC-try-completion' is not a guaranteed to fix these bugs reliably, you
-;; should try to look at the following discussions when you encounter problems:
-;; - emacs-pretest-bug ("Partial Completion" starting 2007-02-23),
-;; - emacs-devel ("[address-of-OP: Partial completion]" starting 2007-02-24),
-;; - emacs-devel ("[address-of-OP: EVAL and mouse selection in *Completions*]"
-;; starting 2007-03-05).
-(defun PC-try-completion (string alist &optional predicate)
- "Like `try-completion' but return STRING instead of t."
- (let ((result (try-completion string alist predicate)))
- (if (eq result t) string result)))
-
-;; TODO document MODE magic...
-(defun PC-do-completion (&optional mode beg end goto-end)
- "Internal function to do the work of partial completion.
-Text to be completed lies between BEG and END. Normally when
-replacing text in the minibuffer, this function replaces up to
-point-max (as is appropriate for completing a file name). If
-GOTO-END is non-nil, however, it instead replaces up to END."
- (or beg (setq beg (minibuffer-prompt-end)))
- (or end (setq end (point-max)))
- (let* ((table (if (eq minibuffer-completion-table 'read-file-name-internal)
- 'PC-read-file-name-internal
- minibuffer-completion-table))
- (pred minibuffer-completion-predicate)
- (filename (funcall PC-completion-as-file-name-predicate))
- (dirname nil) ; non-nil only if a filename is being completed
- ;; The following used to be "(dirlength 0)" which caused the erasure of
- ;; the entire buffer text before `point' when inserting a completion
- ;; into a buffer.
- dirlength
- (str (buffer-substring beg end))
- (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str)))
- (ambig nil)
- basestr origstr
- env-on
- regex
- p offset
- abbreviated
- (poss nil)
- helpposs
- (case-fold-search completion-ignore-case))
-
- ;; Check if buffer contents can already be considered complete
- (if (and (eq mode 'exit)
- (test-completion str table pred))
- 'complete
-
- ;; Do substitutions in directory names
- (and filename
- (setq basestr (or (file-name-directory str) ""))
- (setq dirlength (length basestr))
- ;; Do substitutions in directory names
- (setq p (substitute-in-file-name basestr))
- (not (string-equal basestr p))
- (setq str (concat p (file-name-nondirectory str)))
- (progn
- (delete-region beg end)
- (insert str)
- (setq end (+ beg (length str)))))
-
- ;; Prepare various delimiter strings
- (or (equal PC-word-delimiters PC-delims)
- (setq PC-delims PC-word-delimiters
- PC-delim-regex (concat "[" PC-delims "]")
- PC-ndelims-regex (concat "[^" PC-delims "]*")
- PC-delims-list (append PC-delims nil)))
-
- ;; Add wildcards if necessary
- (and filename
- (let ((dir (file-name-directory str))
- (file (file-name-nondirectory str))
- ;; The base dir for file-completion was passed in `predicate'.
- (default-directory (if (stringp pred) (expand-file-name pred)
- default-directory)))
- (while (and (stringp dir) (not (file-directory-p dir)))
- (setq dir (directory-file-name dir))
- (setq file (concat (replace-regexp-in-string
- PC-delim-regex "*\\&"
- (file-name-nondirectory dir))
- "*/" file))
- (setq dir (file-name-directory dir)))
- (setq origstr str str (concat dir file))))
-
- ;; Look for wildcard expansions in directory name
- (and filename
- (string-match "\\*.*/" str)
- (let ((pat str)
- ;; The base dir for file-completion was passed in `predicate'.
- (default-directory (if (stringp pred) (expand-file-name pred)
- default-directory))
- files)
- (setq p (1+ (string-match "/[^/]*\\'" pat)))
- (while (setq p (string-match PC-delim-regex pat p))
- (setq pat (concat (substring pat 0 p)
- "*"
- (substring pat p))
- p (+ p 2)))
- (setq files (file-expand-wildcards (concat pat "*")))
- (if files
- (let ((dir (file-name-directory (car files)))
- (p files))
- (while (and (setq p (cdr p))
- (equal dir (file-name-directory (car p)))))
- (if p
- (setq filename nil table nil
- pred (if (stringp pred) nil pred)
- ambig t)
- (delete-region beg end)
- (setq str (concat dir (file-name-nondirectory str)))
- (insert str)
- (setq end (+ beg (length str)))))
- (if origstr
- ;; If the wildcards were introduced by us, it's
- ;; possible that PC-read-file-name-internal can
- ;; still find matches for the original string
- ;; even if we couldn't, so remove the added
- ;; wildcards.
- (setq str origstr)
- (setq filename nil table nil
- pred (if (stringp pred) nil pred))))))
-
- ;; Strip directory name if appropriate
- (if filename
- (if incname
- (setq basestr (substring str incname)
- dirname (substring str 0 incname))
- (setq basestr (file-name-nondirectory str)
- dirname (file-name-directory str))
- ;; Make sure str is consistent with its directory and basename
- ;; parts. This is important on DOZe'NT systems when str only
- ;; includes a drive letter, like in "d:".
- (setq str (concat dirname basestr)))
- (setq basestr str))
-
- ;; Convert search pattern to a standard regular expression
- (setq regex (regexp-quote basestr)
- offset (if (and (> (length regex) 0)
- (not (eq (aref basestr 0) ?\*))
- (or (eq PC-first-char t)
- (and PC-first-char filename))) 1 0)
- p offset)
- (while (setq p (string-match PC-delim-regex regex p))
- (if (eq (aref regex p) ? )
- (setq regex (concat (substring regex 0 p)
- PC-ndelims-regex
- PC-delim-regex
- (substring regex (1+ p)))
- p (+ p (length PC-ndelims-regex) (length PC-delim-regex)))
- (let ((bump (if (memq (aref regex p)
- '(?$ ?^ ?\. ?* ?+ ?? ?[ ?] ?\\))
- -1 0)))
- (setq regex (concat (substring regex 0 (+ p bump))
- PC-ndelims-regex
- (substring regex (+ p bump)))
- p (+ p (length PC-ndelims-regex) 1)))))
- (setq p 0)
- (if filename
- (while (setq p (string-match "\\\\\\*" regex p))
- (setq regex (concat (substring regex 0 p)
- "[^/]*"
- (substring regex (+ p 2))))))
- ;;(setq the-regex regex)
- (setq regex (concat "\\`" regex))
-
- (and (> (length basestr) 0)
- (= (aref basestr 0) ?$)
- (setq env-on t
- table PC-env-vars-alist
- pred nil))
-
- ;; Find an initial list of possible completions
- (unless (setq p (string-match (concat PC-delim-regex
- (if filename "\\|\\*" ""))
- str
- (+ (length dirname) offset)))
-
- ;; Minibuffer contains no hyphens -- simple case!
- (setq poss (all-completions (if env-on basestr str)
- table
- pred))
- (unless (or poss (string-equal str ""))
- ;; Try completion as an abbreviation, e.g. "mvb" ->
- ;; "m-v-b" -> "multiple-value-bind", but only for
- ;; non-empty strings.
- (setq origstr str
- abbreviated t)
- (if filename
- (cond
- ;; "alpha" or "/alpha" -> expand whole path.
- ((string-match "^/?\\([A-Za-z0-9]+\\)$" str)
- (setq
- basestr ""
- p nil
- poss (file-expand-wildcards
- (concat "/"
- (mapconcat #'list (match-string 1 str) "*/")
- "*"))
- beg (1- beg)))
- ;; Alphanumeric trailer -> expand trailing file
- ((string-match "^\\(.+/\\)\\([A-Za-z0-9]+\\)$" str)
- (setq regex (concat "\\`"
- (mapconcat #'list
- (match-string 2 str)
- "[A-Za-z0-9]*[^A-Za-z0-9]"))
- p (1+ (length (match-string 1 str))))))
- (setq regex (concat "\\`" (mapconcat (lambda (c)
- (regexp-quote (string c)))
- str "[^-]*-"))
- p 1))))
- (when p
- ;; Use all-completions to do an initial cull. This is a big win,
- ;; since all-completions is written in C!
- (let ((compl (all-completions (if env-on
- (file-name-nondirectory (substring str 0 p))
- (substring str 0 p))
- table
- pred)))
- (setq p compl)
- (when (and compl abbreviated)
- (if filename
- (progn
- (setq p nil)
- (dolist (x compl)
- (when (string-match regex x)
- (push x p)))
- (setq basestr (try-completion "" p)))
- (setq basestr (mapconcat 'list str "-"))
- (delete-region beg end)
- (setq end (+ beg (length basestr)))
- (insert basestr))))
- (while p
- (and (string-match regex (car p))
- (progn
- (set-text-properties 0 (length (car p)) '() (car p))
- (setq poss (cons (car p) poss))))
- (setq p (cdr p))))
-
- ;; If table had duplicates, they can be here.
- (delete-dups poss)
-
- ;; Handle completion-ignored-extensions
- (and filename
- (not (eq mode 'help))
- (let ((p2 poss))
-
- ;; Build a regular expression representing the extensions list
- (or (equal completion-ignored-extensions PC-ignored-extensions)
- (setq PC-ignored-regexp
- (concat "\\("
- (mapconcat
- 'regexp-quote
- (setq PC-ignored-extensions
- completion-ignored-extensions)
- "\\|")
- "\\)\\'")))
-
- ;; Check if there are any without an ignored extension.
- ;; Also ignore `.' and `..'.
- (setq p nil)
- (while p2
- (or (string-match PC-ignored-regexp (car p2))
- (string-match "\\(\\`\\|/\\)[.][.]?/?\\'" (car p2))
- (setq p (cons (car p2) p)))
- (setq p2 (cdr p2)))
-
- ;; If there are "good" names, use them
- (and p (setq poss p))))
-
- ;; Now we have a list of possible completions
-
- (cond
-
- ;; No valid completions found
- ((null poss)
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
- (let ((PC-word-failed-flag t))
- (delete-backward-char 1)
- (PC-do-completion 'word))
- (when abbreviated
- (delete-region beg end)
- (insert origstr))
- (beep)
- (PC-temp-minibuffer-message (if ambig
- " [Ambiguous dir name]"
- (if (eq mode 'help)
- " [No completions]"
- " [No match]")))
- nil))
-
- ;; More than one valid completion found
- ((or (cdr (setq helpposs poss))
- (memq mode '(help word)))
-
- ;; Is the actual string one of the possible completions?
- (setq p (and (not (eq mode 'help)) poss))
- (while (and p
- (not (string-equal (car p) basestr)))
- (setq p (cdr p)))
- (and p (null mode)
- (PC-temp-minibuffer-message " [Complete, but not unique]"))
- (if (and p
- (not (and (null mode)
- (eq this-command last-command))))
- t
-
- ;; If ambiguous, try for a partial completion
- (let ((improved nil)
- prefix
- (pt nil)
- (skip "\\`"))
-
- ;; Check if next few letters are the same in all cases
- (if (and (not (eq mode 'help))
- (setq prefix (PC-try-completion
- (PC-chunk-after basestr skip) poss)))
- (let ((first t) i)
- (if (eq mode 'word)
- (setq prefix (PC-chop-word prefix basestr)))
- (goto-char (+ beg (length dirname)))
- (while (and (progn
- (setq i 0) ; index into prefix string
- (while (< i (length prefix))
- (if (and (< (point) end)
- (or (eq (downcase (aref prefix i))
- (downcase (following-char)))
- (and (looking-at " ")
- (memq (aref prefix i)
- PC-delims-list))))
- ;; replace " " by the actual delimiter
- ;; or input char by prefix char
- (progn
- (delete-char 1)
- (insert (substring prefix i (1+ i))))
- ;; insert a new character
- (progn
- (and filename (looking-at "\\*")
- (progn
- (delete-char 1)
- (setq end (1- end))))
- (setq improved t)
- (insert (substring prefix i (1+ i)))
- (setq end (1+ end))))
- (setq i (1+ i)))
- (or pt (setq pt (point)))
- (looking-at PC-delim-regex))
- (setq skip (concat skip
- (regexp-quote prefix)
- PC-ndelims-regex)
- prefix (PC-try-completion
- (PC-chunk-after
- ;; not basestr, because that does
- ;; not reflect insertions
- (buffer-substring
- (+ beg (length dirname)) end)
- skip)
- (mapcar
- (lambda (x)
- (when (string-match skip x)
- (substring x (match-end 0))))
- poss)))
- (or (> i 0) (> (length prefix) 0))
- (or (not (eq mode 'word))
- (and first (> (length prefix) 0)
- (setq first nil
- prefix (substring prefix 0 1))))))
- (goto-char (if (eq mode 'word) end
- (or pt beg)))))
-
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
-
- (if improved
-
- ;; We changed it... would it be complete without the space?
- (if (test-completion (buffer-substring
- (field-beginning) (1- end))
- table pred)
- (delete-region (1- end) end)))
-
- (if improved
-
- ;; We changed it... enough to be complete?
- (and (eq mode 'exit)
- (test-completion-ignore-case (field-string) table pred))
-
- ;; If totally ambiguous, display a list of completions
- (if (or (eq completion-auto-help t)
- (and completion-auto-help
- (eq last-command this-command))
- (eq mode 'help))
- (let ((prompt-end (minibuffer-prompt-end)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (sort helpposs 'string-lessp))
- (setq PC-do-completion-end end
- PC-goto-end goto-end)
- (with-current-buffer standard-output
- ;; Record which part of the buffer we are completing
- ;; so that choosing a completion from the list
- ;; knows how much old text to replace.
- ;; This was briefly nil in the non-dirname case.
- ;; However, if one calls PC-lisp-complete-symbol
- ;; on "(ne-f" with point on the hyphen, PC offers
- ;; all completions starting with "(ne", some of
- ;; which do not match the "-f" part (maybe it
- ;; should not, but it does). In such cases,
- ;; completion gets confused trying to figure out
- ;; how much to replace, so we tell it explicitly
- ;; (ie, the number of chars in the buffer before beg).
- ;;
- ;; Note that choose-completion-string-functions
- ;; plays around with point.
- (setq completion-base-size (if dirname
- dirlength
- (- beg prompt-end))))))
- (PC-temp-minibuffer-message " [Next char not unique]"))
- ;; Expansion of filenames is not reversible,
- ;; so just keep the prefix.
- (when (and abbreviated filename)
- (delete-region (point) end))
- nil)))))
-
- ;; Only one possible completion
- (t
- (if (and (equal basestr (car poss))
- (not (and env-on filename))
- (not abbreviated))
- (if (null mode)
- (PC-temp-minibuffer-message " [Sole completion]"))
- (delete-region beg end)
- (insert (format "%s"
- (if filename
- (substitute-in-file-name (concat dirname (car poss)))
- (car poss)))))
- t)))))
-
-(defun PC-chop-word (new old)
- (let ((i -1)
- (j -1))
- (while (and (setq i (string-match PC-delim-regex old (1+ i)))
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (if (and j
- (or (not PC-word-failed-flag)
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (substring new 0 (1+ j))
- new)))
-
-(defvar PC-not-minibuffer nil)
-
-(defun PC-temp-minibuffer-message (message)
- "A Lisp version of `temp_minibuffer_message' from minibuf.c."
- (cond (PC-not-minibuffer
- (message "%s" message)
- (sit-for 2)
- (message ""))
- ((fboundp 'temp-minibuffer-message)
- (temp-minibuffer-message message))
- (t
- (let ((point-max (point-max)))
- (save-excursion
- (goto-char point-max)
- (insert message))
- (let ((inhibit-quit t))
- (sit-for 2)
- (delete-region point-max (point-max))
- (when quit-flag
- (setq quit-flag nil
- unread-command-events '(7))))))))
-
-;; Does not need to be buffer-local (?) because only used when one
-;; PC-l-c-s immediately follows another.
-(defvar PC-lisp-complete-end nil
- "Internal variable used by `PC-lisp-complete-symbol'.")
-
-(defun PC-lisp-complete-symbol ()
- "Perform completion on Lisp symbol preceding point.
-That symbol is compared against the symbols that exist
-and any additional characters determined by what is there
-are inserted.
-If the symbol starts just after an open-parenthesis,
-only symbols with function definitions are considered.
-Otherwise, all symbols with function definitions, values
-or properties are considered."
- (interactive)
- (let* ((end
- (save-excursion
- (with-syntax-table lisp-mode-syntax-table
- (skip-syntax-forward "_w")
- (point))))
- (beg (save-excursion
- (with-syntax-table lisp-mode-syntax-table
- (backward-sexp 1)
- (while (= (char-syntax (following-char)) ?\')
- (forward-char 1))
- (point))))
- (minibuffer-completion-table obarray)
- (minibuffer-completion-predicate
- (if (eq (char-after (1- beg)) ?\()
- 'fboundp
- (function (lambda (sym)
- (or (boundp sym) (fboundp sym)
- (symbol-plist sym))))))
- (PC-not-minibuffer t))
- ;; http://lists.gnu.org/archive/html/emacs-devel/2007-03/msg01211.html
- ;;
- ;; This deals with cases like running PC-l-c-s on "M-: (n-f".
- ;; The first call to PC-l-c-s expands this to "(ne-f", and moves
- ;; point to the hyphen [1]. If one calls PC-l-c-s immediately after,
- ;; then without the last-command check, one is offered all
- ;; completions of "(ne", which is presumably not what one wants.
- ;;
- ;; This is arguably (at least, it seems to be the existing intended
- ;; behavior) what one _does_ want if point has been explicitly
- ;; positioned on the hyphen. Note that if PC-do-completion (qv) binds
- ;; completion-base-size to nil, then completion does not replace the
- ;; correct amount of text in such cases.
- ;;
- ;; Neither of these problems occur when using PC for filenames in the
- ;; minibuffer, because in that case PC-do-completion is called without
- ;; an explicit value for END, and so uses (point-max). This is fine for
- ;; a filename, because the end of the filename must be at the end of
- ;; the minibuffer. The same is not true for lisp symbols.
- ;;
- ;; [1] An alternate fix would be to not move point to the hyphen
- ;; in such cases, but that would make the behavior different from
- ;; that for filenames. It seems PC moves point to the site of the
- ;; first difference between the possible completions.
- ;;
- ;; Alternatively alternatively, maybe end should be computed in
- ;; the same way as beg. That would change the behavior though.
- (if (equal last-command 'PC-lisp-complete-symbol)
- (PC-do-completion nil beg PC-lisp-complete-end t)
- (if PC-lisp-complete-end
- (move-marker PC-lisp-complete-end end)
- (setq PC-lisp-complete-end (copy-marker end t)))
- (PC-do-completion nil beg end t))))
-
-(defun PC-complete-as-file-name ()
- "Perform completion on file names preceding point.
- Environment vars are converted to their values."
- (interactive)
- (let* ((end (point))
- (beg (if (re-search-backward "[^\\][ \t\n\"\`\'][^ \t\n\"\`\']"
- (point-min) t)
- (+ (point) 2)
- (point-min)))
- (minibuffer-completion-table 'PC-read-file-name-internal)
- (minibuffer-completion-predicate nil)
- (PC-not-minibuffer t))
- (goto-char end)
- (PC-do-completion nil beg end)))
-
-;; Facilities for loading C header files. This is independent from the
-;; main completion code. See also the variable `PC-include-file-path'
-;; at top of this file.
-
-(defun PC-look-for-include-file ()
- (if (string-match "[\"<]\\([^\"<>]*\\)[\">]?$" (buffer-file-name))
- (let ((name (substring (buffer-file-name)
- (match-beginning 1) (match-end 1)))
- (punc (aref (buffer-file-name) (match-beginning 0)))
- (path nil)
- new-buf)
- (kill-buffer (current-buffer))
- (if (equal name "")
- (with-current-buffer (car (buffer-list))
- (save-excursion
- (beginning-of-line)
- (if (looking-at
- "[ \t]*#[ \t]*include[ \t]+[<\"]\\(.+\\)[>\"][ \t]*[\n/]")
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc (char-after (1- (match-beginning 1))))
- ;; Suggested by Frank Siebenlist:
- (if (or (looking-at
- "[ \t]*([ \t]*load[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*load-library[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*require[ \t]+'\\([^\t )]+\\)[\t )]"))
- (progn
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc ?\<
- path load-path)
- (if (string-match "\\.elc$" name)
- (setq name (substring name 0 -1))
- (or (string-match "\\.el$" name)
- (setq name (concat name ".el")))))
- (error "Not on an #include line"))))))
- (or (string-match "\\.[[:alnum:]]+$" name)
- (setq name (concat name ".h")))
- (if (eq punc ?\<)
- (let ((path (or path (PC-include-file-path))))
- (while (and path
- (not (file-exists-p
- (concat (file-name-as-directory (car path))
- name))))
- (setq path (cdr path)))
- (if path
- (setq name (concat (file-name-as-directory (car path)) name))
- (error "No such include file: <%s>" name)))
- (let ((dir (with-current-buffer (car (buffer-list))
- default-directory)))
- (if (file-exists-p (concat dir name))
- (setq name (concat dir name))
- (error "No such include file: `%s'" name))))
- (setq new-buf (get-file-buffer name))
- (if new-buf
- ;; no need to verify last-modified time for this!
- (set-buffer new-buf)
- (set-buffer (create-file-buffer name))
- (erase-buffer)
- (insert-file-contents name t))
- ;; Returning non-nil with the new buffer current
- ;; is sufficient to tell find-file to use it.
- t)
- nil))
-
-(defun PC-include-file-path ()
- (or PC-include-file-path
- (let ((env (getenv "INCPATH"))
- (path nil)
- pos)
- (or env (error "No include file path specified"))
- (while (setq pos (string-match ":[^:]+$" env))
- (setq path (cons (substring env (1+ pos)) path)
- env (substring env 0 pos)))
- path)))
-
-;; This is adapted from lib-complete.el, by Mike Williams.
-(defun PC-include-file-all-completions (file search-path &optional full)
- "Return all completions for FILE in any directory on SEARCH-PATH.
-If optional third argument FULL is non-nil, returned pathnames should be
-absolute rather than relative to some directory on the SEARCH-PATH."
- (setq search-path
- (mapcar (lambda (dir)
- (if dir (file-name-as-directory dir) default-directory))
- search-path))
- (if (file-name-absolute-p file)
- ;; It's an absolute file name, so don't need search-path
- (progn
- (setq file (expand-file-name file))
- (file-name-all-completions
- (file-name-nondirectory file) (file-name-directory file)))
- (let ((subdir (file-name-directory file))
- (ndfile (file-name-nondirectory file))
- file-lists)
- ;; Append subdirectory part to each element of search-path
- (if subdir
- (setq search-path
- (mapcar (lambda (dir) (concat dir subdir))
- search-path)
- file ))
- ;; Make list of completions in each directory on search-path
- (while search-path
- (let* ((dir (car search-path))
- (subdir (if full dir subdir)))
- (if (file-directory-p dir)
- (progn
- (setq file-lists
- (cons
- (mapcar (lambda (file) (concat subdir file))
- (file-name-all-completions ndfile
- (car search-path)))
- file-lists))))
- (setq search-path (cdr search-path))))
- ;; Compress out duplicates while building complete list (slloooow!)
- (let ((sorted (sort (apply 'nconc file-lists)
- (lambda (x y) (not (string-lessp x y)))))
- compressed)
- (while sorted
- (if (equal (car sorted) (car compressed)) nil
- (setq compressed (cons (car sorted) compressed)))
- (setq sorted (cdr sorted)))
- compressed))))
-
-(defun PC-read-file-name-internal (string pred action)
- "Extend `read-file-name-internal' to handle include files.
-This is only used by "
- (if (string-match "<\\([^\"<>]*\\)>?\\'" string)
- (let* ((name (match-string 1 string))
- (str2 (substring string (match-beginning 0)))
- (completion-table
- (mapcar (lambda (x)
- (format (if (string-match "/\\'" x) "<%s" "<%s>") x))
- (PC-include-file-all-completions
- name (PC-include-file-path)))))
- (cond
- ((not completion-table) nil)
- ((eq action 'lambda) (test-completion str2 completion-table nil))
- ((eq action nil) (PC-try-completion str2 completion-table nil))
- ((eq action t) (all-completions str2 completion-table nil))))
- (read-file-name-internal string pred action)))
-
-
-(provide 'complete)
-
-;; arch-tag: fc7e2768-ff44-4e22-b579-4d825b968458
-;;; complete.el ends here