X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a4e104bf5ccd3e19a16cdb6bad79edff86fba3cb..773415d9340f12db3bd8654de5014deec57d49b7:/lisp/complete.el diff --git a/lisp/complete.el b/lisp/complete.el index b4e374532a..60bddd01f1 100644 --- a/lisp/complete.el +++ b/lisp/complete.el @@ -1,9 +1,10 @@ -;; complete.el -- partial completion mechanism plus other goodies. +;;; complete.el --- partial completion mechanism plus other goodies -;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. +;; Copyright (C) 1990, 1991, 1992, 1993, 1999, 2000, 2003, 2005 +;; Free Software Foundation, Inc. ;; Author: Dave Gillespie -;; Version: 2.02 +;; Keywords: abbrev convenience ;; Special thanks to Hallvard Furuseth for his many ideas and contributions. ;; This file is part of GNU Emacs. @@ -19,10 +20,11 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. -;; Commentary: +;;; Commentary: ;; Extended completion for the Emacs minibuffer. ;; @@ -45,7 +47,7 @@ ;; and the partial completer will use the Meta versions of the keys. -;; Usage: Load this file. Now, during completable minibuffer entry, +;; 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; @@ -60,7 +62,7 @@ ;; ;; in your .emacs file. To load partial completion automatically, put ;; -;; (load "complete") +;; (partial-completion-mode t) ;; ;; in your .emacs file, too. Things will be faster if you byte-compile ;; this file when you install it. @@ -76,17 +78,6 @@ ;; The regular M-TAB (lisp-complete-symbol) command also supports ;; partial completion in this package. -;; This package also contains a wildcard feature for C-x C-f (find-file). -;; For example, `C-x C-f *.c RET' loads all .c files at once, exactly -;; as if you had typed C-x C-f separately for each file. Completion -;; is supported in connection with wildcards. Currently only the `*' -;; wildcard character works. - -;; File name completion does not do partial completion of directories -;; on the path, e.g., "/u/b/f" will not complete to "/usr/bin/foo", -;; but you can put *'s in the path to accomplish this: "/u*/b*/f". -;; Stars are required for performance reasons. - ;; In addition, this package includes a feature for accessing include ;; files. For example, `C-x C-f RET' reads the file ;; /usr/include/sys/time.h. The variable PC-include-file-path is a @@ -94,73 +85,151 @@ ;; is supported in include file names. -;; Code: - -(defvar PC-meta-flag t - "*If nil, TAB does normal Emacs completion and M-TAB does Partial Completion. -If t, TAB does Partial Completion and M-TAB does normal completion.") - - -(defvar PC-word-delimiters "-_. " - "*A string of characters which are to be treated as word delimiters -by the Partial Completion system. - -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 legal Emacs regular expression -\(not containing character ranges like `a-z').") - - -(defvar PC-first-char 'x - "*If t, first character of a string to be completed is always taken literally. -If nil, word delimiters are handled even if they appear as first character. -This controls whether \".e\" matches \".e*\" (t) or \"*.e*\" (nil). -If neither nil nor t, first char is literal only for filename completion.") - - -(defvar PC-include-file-path '("/usr/include") - "*List of directories in which to look for include files. -If this is nil, uses the colon-separated path in $INCPATH instead.") - - -(defvar PC-disable-wildcards nil - "Set this to non-nil to disable wildcard support in \\[find-file].") - -(defvar PC-disable-includes nil - "Set this to non-nil to disable include-file support in \\[find-file].") - +;;; 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 - "Set this to nil to suppress the default partial completion key bindings.") - -(if PC-default-bindings (progn -(define-key minibuffer-local-completion-map "\t" 'PC-complete) -(define-key minibuffer-local-completion-map " " 'PC-complete-word) -(define-key minibuffer-local-completion-map "?" 'PC-completion-help) + "If non-nil, default partial completion key bindings are suppressed.") -(define-key minibuffer-local-completion-map "\e\t" 'PC-complete) -(define-key minibuffer-local-completion-map "\e " 'PC-complete-word) -(define-key minibuffer-local-completion-map "\e\r" 'PC-force-complete-and-exit) -(define-key minibuffer-local-completion-map "\e\n" 'PC-force-complete-and-exit) -(define-key minibuffer-local-completion-map "\e?" 'PC-completion-help) +(defvar PC-env-vars-alist nil + "A list of the environment variable names and values.") -(define-key minibuffer-local-must-match-map "\t" 'PC-complete) -(define-key minibuffer-local-must-match-map " " 'PC-complete-word) -(define-key minibuffer-local-must-match-map "\r" 'PC-complete-and-exit) -(define-key minibuffer-local-must-match-map "\n" 'PC-complete-and-exit) -(define-key minibuffer-local-must-match-map "?" 'PC-completion-help) - -(define-key minibuffer-local-must-match-map "\e\t" 'PC-complete) -(define-key minibuffer-local-must-match-map "\e " 'PC-complete-word) -(define-key minibuffer-local-must-match-map "\e\r" 'PC-complete-and-exit) -(define-key minibuffer-local-must-match-map "\e\n" 'PC-complete-and-exit) -(define-key minibuffer-local-must-match-map "\e?" 'PC-completion-help) - -(define-key global-map "\e\t" 'PC-lisp-complete-symbol) -)) + +(defvar PC-old-read-file-name-internal nil) +(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 completion-map "\t" 'minibuffer-complete) + (define-key completion-map " " 'minibuffer-complete-word) + (define-key completion-map "?" 'minibuffer-completion-help) + + (define-key must-match-map "\t" 'minibuffer-complete) + (define-key must-match-map " " 'minibuffer-complete-word) + (define-key must-match-map "\r" 'minibuffer-complete-and-exit) + (define-key must-match-map "\n" 'minibuffer-complete-and-exit) + (define-key must-match-map "?" 'minibuffer-completion-help) + + (define-key global-map "\e\t" 'complete-symbol)) + (PC-default-bindings + (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 "\t" 'PC-complete) + (define-key must-match-map " " 'PC-complete-word) + (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 "?" 'PC-completion-help) + + (define-key must-match-map "\e\t" 'PC-complete) + (define-key must-match-map "\e " 'PC-complete-word) + (define-key must-match-map "\e\r" 'PC-complete-and-exit) + (define-key must-match-map "\e\n" 'PC-complete-and-exit) + (define-key must-match-map "\e?" 'PC-completion-help) + + (define-key global-map "\e\t" 'PC-lisp-complete-symbol))))) + +;;;###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 begin with that sequence of characters. + +Unless `PC-disable-includes' is non-nil, the `<...>' sequence is interpreted +specially in \\[find-file]. For example, +\\[find-file] RET finds the file `/usr/include/sys/time.h'. +See also the variable `PC-include-file-path'." + :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-hooks 'PC-look-for-include-file)) + ((not PC-disable-includes) + (add-hook 'find-file-not-found-hooks 'PC-look-for-include-file))) + ;; ... with some underhand redefining. + (cond ((and (not partial-completion-mode) + (functionp PC-old-read-file-name-internal)) + (fset 'read-file-name-internal PC-old-read-file-name-internal)) + ((and (not PC-disable-includes) (not PC-old-read-file-name-internal)) + (setq PC-old-read-file-name-internal + (symbol-function 'read-file-name-internal)) + (fset 'read-file-name-internal + 'PC-read-include-file-name-internal))) + (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 @@ -176,7 +245,21 @@ Word-delimiters for the purposes of Partial Completion are \"-\", \"_\", (interactive) (if (PC-was-meta-key) (minibuffer-complete) - (PC-do-completion nil))) + ;; 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))) + (save-excursion + (set-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 () @@ -221,14 +304,14 @@ See `PC-complete' for details." (PC-do-complete-and-exit))) (defun PC-do-complete-and-exit () - (if (= (buffer-size) 0) ; Duplicate the "bug" that Info-menu relies on... + (if (= (point-max) (minibuffer-prompt-end)) ; Duplicate the "bug" that Info-menu relies on... (exit-minibuffer) (let ((flag (PC-do-completion 'exit))) (and flag (if (or (eq flag 'complete) (not minibuffer-completion-confirm)) (exit-minibuffer) - (PC-temp-minibuffer-message " (Confirm)")))))) + (PC-temp-minibuffer-message " [Confirm]")))))) (defun PC-completion-help () @@ -255,18 +338,28 @@ See `PC-complete' for details." (defvar PC-ndelims-regex nil) (defvar PC-delims-list nil) +(defvar PC-completion-as-file-name-predicate + (function + (lambda () + (memq minibuffer-completion-table + '(read-file-name-internal read-directory-name-internal)))) + "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.") + (defun PC-do-completion (&optional mode beg end) - (or beg (setq beg (point-min))) + (or beg (setq beg (minibuffer-prompt-end))) (or end (setq end (point-max))) (let* ((table minibuffer-completion-table) (pred minibuffer-completion-predicate) - (filename (memq table '(read-file-name-internal - read-directory-name-internal))) + (filename (funcall PC-completion-as-file-name-predicate)) (dirname nil) + (dirlength 0) (str (buffer-substring beg end)) (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str))) (ambig nil) basestr + env-on regex p offset (poss nil) @@ -275,16 +368,21 @@ See `PC-complete' for details." ;; Check if buffer contents can already be considered complete (if (and (eq mode 'exit) - (PC-is-complete-p str table pred)) + (test-completion str table pred)) 'complete ;; Do substitutions in directory names (and filename - (not (equal str (setq p (substitute-in-file-name str)))) - (progn + (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 p) - (setq str p end (+ beg (length str))))) + (insert str) + (setq end (+ beg (length str))))) ;; Prepare various delimiter strings (or (equal PC-word-delimiters PC-delims) @@ -293,10 +391,27 @@ See `PC-complete' for details." 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 is passed in `predicate'. + (default-directory (expand-file-name pred))) + (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 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 is passed in `predicate'. + (default-directory (expand-file-name pred)) files) (setq p (1+ (string-match "/[^/]*\\'" pat))) (while (setq p (string-match PC-delim-regex pat p)) @@ -325,7 +440,11 @@ See `PC-complete' for details." (setq basestr (substring str incname) dirname (substring str 0 incname)) (setq basestr (file-name-nondirectory str) - dirname (file-name-directory 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 @@ -358,6 +477,12 @@ See `PC-complete' for details." ;;(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 (if (not (setq p (string-match (concat PC-delim-regex (if filename "\\|\\*" "")) @@ -365,19 +490,24 @@ See `PC-complete' for details." (+ (length dirname) offset)))) ;; Minibuffer contains no hyphens -- simple case! - (setq poss (all-completions str + (setq poss (all-completions (if env-on + basestr str) table pred)) ;; Use all-completions to do an initial cull. This is a big win, ;; since all-completions is written in C! - (let ((compl (all-completions (substring str 0 p) - table - pred))) + (let ((compl (all-completions (if env-on + (file-name-nondirectory (substring str 0 p)) + (substring str 0 p)) + table + pred))) (setq p compl) (while p (and (string-match regex (car p)) - (setq poss (cons (car p) poss))) + (progn + (set-text-properties 0 (length (car p)) '() (car p)) + (setq poss (cons (car p) poss)))) (setq p (cdr p))))) ;; Now we have a list of possible completions @@ -392,10 +522,10 @@ See `PC-complete' for details." (PC-do-completion 'word)) (beep) (PC-temp-minibuffer-message (if ambig - " (Ambiguous dir name)" + " [Ambiguous dir name]" (if (eq mode 'help) - " (No completions)" - " (No match)"))) + " [No completions]" + " [No match]"))) nil)) ;; More than one valid completion found @@ -418,10 +548,12 @@ See `PC-complete' for details." "\\|") "\\)\\'"))) - ;; Check if there are any without an ignored extension + ;; 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))) @@ -431,14 +563,14 @@ See `PC-complete' for details." ;; Is the actual string one of the possible completions? (setq p (and (not (eq mode 'help)) poss)) (while (and p - (not (equal (car p) basestr))) + (not (string-equal (car p) basestr))) (setq p (cdr p))) - (if p - - (progn - (if (null mode) - (PC-temp-minibuffer-message " (Complete, but not unique)")) - t) + (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) @@ -509,7 +641,7 @@ See `PC-complete' for details." (if improved ;; We changed it... would it be complete without the space? - (if (PC-is-complete-p (buffer-substring 1 (1- end)) + (if (test-completion (buffer-substring 1 (1- end)) table pred) (delete-region (1- end) end))) @@ -517,41 +649,37 @@ See `PC-complete' for details." ;; We changed it... enough to be complete? (and (eq mode 'exit) - (PC-is-complete-p (buffer-string) table pred)) + (test-completion (field-string) table pred)) ;; If totally ambiguous, display a list of completions - (if (or completion-auto-help + (if (or (eq completion-auto-help t) + (and completion-auto-help + (eq last-command this-command)) (eq mode 'help)) - (with-output-to-temp-buffer " *Completions*" - (display-completion-list (sort helpposs 'string-lessp))) - (PC-temp-minibuffer-message " (Next char not unique)")) + (with-output-to-temp-buffer "*Completions*" + (display-completion-list (sort helpposs 'string-lessp)) + (save-excursion + (set-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. + (setq completion-base-size dirlength))) + (PC-temp-minibuffer-message " [Next char not unique]")) nil))))) ;; Only one possible completion (t - (if (equal basestr (car poss)) + (if (and (equal basestr (car poss)) + (not (and env-on filename))) (if (null mode) - (PC-temp-minibuffer-message " (Sole completion)")) + (PC-temp-minibuffer-message " [Sole completion]")) (delete-region beg end) - (insert (if filename - (substitute-in-file-name (concat dirname (car poss))) - (car poss)))) + (insert (format "%s" + (if filename + (substitute-in-file-name (concat dirname (car poss))) + (car poss))))) t))))) - -(defun PC-is-complete-p (str table pred) - (let ((res (if (listp table) - (assoc str table) - (if (vectorp table) - (or (equal str "nil") ; heh, heh, heh - (intern-soft str table)) - (funcall table str pred 'lambda))))) - (and res - (or (not pred) - (and (not (listp table)) (not (vectorp table))) - (funcall pred res)) - res))) - (defun PC-chop-word (new old) (let ((i -1) (j -1)) @@ -565,25 +693,25 @@ See `PC-complete' for details." (defvar PC-not-minibuffer nil) -(defun PC-temp-minibuffer-message (m) +(defun PC-temp-minibuffer-message (message) "A Lisp version of `temp_minibuffer_message' from minibuf.c." - (if PC-not-minibuffer - (progn - (message m) - (sit-for 2) - (message "")) - (if (fboundp 'temp-minibuffer-message) - (temp-minibuffer-message m) - (let ((savemax (point-max))) - (save-excursion - (goto-char (point-max)) - (insert m)) - (let ((inhibit-quit t)) - (sit-for 2) - (delete-region savemax (point-max)) - (if quit-flag - (setq quit-flag nil - unread-command-char 7))))))) + (cond (PC-not-minibuffer + (message 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)))))))) (defun PC-lisp-complete-symbol () @@ -617,53 +745,23 @@ or properties are considered." (PC-not-minibuffer t)) (PC-do-completion nil beg end))) - -;;; Wildcards in `C-x C-f' command. This is independent from the main -;;; completion code, except for `PC-expand-many-files' which is called -;;; when "*"'s are found in the path during filename completion. (The -;;; above completion code always understands "*"'s, except in file paths, -;;; without relying on the following code.) - -(defvar PC-many-files-list nil) - -(defun PC-try-load-many-files () - (if (string-match "\\*" buffer-file-name) - (let* ((pat buffer-file-name) - (files (PC-expand-many-files pat)) - (first (car files)) - (next files)) - (kill-buffer (current-buffer)) - (or files - (error "No matching files")) - (save-window-excursion - (while (setq next (cdr next)) - (let ((buf (find-file-noselect (car next)))) - (switch-to-buffer buf)))) - ;; This modifies the "buf" variable inside find-file-noselect. - (setq buf (get-file-buffer first)) - (if buf - nil ; should do verify-visited-file-modtime stuff. - (setq filename first) - (setq buf (create-file-buffer filename)) - (set-buffer buf) - (erase-buffer) - (insert-file-contents filename t)) - (if (cdr files) - (setq PC-many-files-list (mapconcat - (if (string-match "\\*.*/" pat) - 'identity - 'file-name-nondirectory) - (cdr files) ", ") - find-file-hooks (cons 'PC-after-load-many-files - find-file-hooks))) - ;; This modifies the "error" variable inside find-file-noselect. - (setq error nil) - t) - nil)) - -(defun PC-after-load-many-files () - (setq find-file-hooks (delq 'PC-after-load-many-files find-file-hooks)) - (message "Also loaded %s." PC-many-files-list)) +(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 'read-file-name-internal) + (minibuffer-completion-predicate "") + (PC-not-minibuffer t)) + (goto-char end) + (PC-do-completion nil beg end))) + +;;; Use the shell to do globbing. +;;; This could now use file-expand-wildcards instead. (defun PC-expand-many-files (name) (save-excursion @@ -681,16 +779,23 @@ or properties are considered." (delete-backward-char 1) (insert "\")") (goto-char (point-min)) - (let ((files (read (current-buffer)))) + (let ((files (read (current-buffer))) (p nil)) (kill-buffer (current-buffer)) - files)))) - -(or PC-disable-wildcards - (memq 'PC-try-load-many-files find-file-not-found-hooks) - (setq find-file-not-found-hooks (cons 'PC-try-load-many-files - find-file-not-found-hooks))) - - + (or (equal completion-ignored-extensions PC-ignored-extensions) + (setq PC-ignored-regexp + (concat "\\(" + (mapconcat + 'regexp-quote + (setq PC-ignored-extensions + completion-ignored-extensions) + "\\|") + "\\)\\'"))) + (setq p nil) + (while files + (or (string-match PC-ignored-regexp (car files)) + (setq p (cons (car files) p))) + (setq files (cdr files))) + p)))) ;;; Facilities for loading C header files. This is independent from the ;;; main completion code. See also the variable `PC-include-file-path' @@ -731,7 +836,7 @@ or properties are considered." (or (string-match "\\.el$" name) (setq name (concat name ".el"))))) (error "Not on an #include line")))))) - (or (string-match "\\.[a-zA-Z0-9]+$" name) + (or (string-match "\\.[[:alnum:]]+$" name) (setq name (concat name ".h"))) (if (eq punc ?\<) (let ((path (or path (PC-include-file-path)))) @@ -748,7 +853,7 @@ or properties are considered." default-directory))) (if (file-exists-p (concat dir name)) (setq name (concat dir name)) - (error "No such include file: \"%s\"" 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! @@ -757,9 +862,8 @@ or properties are considered." (set-buffer new-buf) (erase-buffer) (insert-file-contents name t)) - (setq filename name - error nil - buf new-buf) + ;; Returning non-nil with the new buffer current + ;; is sufficient to tell find-file to use it. t) nil)) @@ -777,17 +881,17 @@ or properties are considered." ;;; 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 +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)) + (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-all-completions (file-name-nondirectory file) (file-name-directory file))) (let ((subdir (file-name-directory file)) (ndfile (file-name-nondirectory file)) @@ -795,7 +899,7 @@ absolute rather than relative to some directory on the SEARCH-PATH." ;; Append subdirectory part to each element of search-path (if subdir (setq search-path - (mapcar '(lambda (dir) (concat dir subdir)) + (mapcar (lambda (dir) (concat dir subdir)) search-path) file )) ;; Make list of completions in each directory on search-path @@ -805,15 +909,15 @@ absolute rather than relative to some directory on the SEARCH-PATH." (if (file-directory-p dir) (progn (setq file-lists - (cons - (mapcar '(lambda (file) (concat subdir file)) - (file-name-all-completions ndfile + (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))))) + (lambda (x y) (not (string-lessp x y))))) compressed) (while sorted (if (equal (car sorted) (car compressed)) nil @@ -821,8 +925,6 @@ absolute rather than relative to some directory on the SEARCH-PATH." (setq sorted (cdr sorted))) compressed)))) -(defvar PC-old-read-file-name-internal nil) - (defun PC-read-include-file-name-internal (string dir action) (if (string-match "<\\([^\"<>]*\\)>?$" string) (let* ((name (substring string (match-beginning 1) (match-end 1))) @@ -835,23 +937,11 @@ absolute rather than relative to some directory on the SEARCH-PATH." ((not completion-table) nil) ((eq action nil) (try-completion str2 completion-table nil)) ((eq action t) (all-completions str2 completion-table nil)) - ((eq action 'lambda) - (eq (try-completion str2 completion-table nil) t)))) + ((eq action 'lambda) (test-completion str2 completion-table nil)))) (funcall PC-old-read-file-name-internal string dir action))) - -(or PC-disable-includes - (memq 'PC-look-for-include-file find-file-not-found-hooks) - (setq find-file-not-found-hooks (cons 'PC-look-for-include-file - find-file-not-found-hooks))) - -(or PC-disable-includes - PC-old-read-file-name-internal - (progn - (setq PC-old-read-file-name-internal - (symbol-function 'read-file-name-internal)) - (fset 'read-file-name-internal 'PC-read-include-file-name-internal))) - + (provide 'complete) -;;; End. +;; arch-tag: fc7e2768-ff44-4e22-b579-4d825b968458 +;;; complete.el ends here