diff options
| author | Stefan Monnier | 2008-04-11 22:28:02 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2008-04-11 22:28:02 +0000 |
| commit | 21622c6d1045fc8c1ce909ffe9db980b79f3dd3a (patch) | |
| tree | 16a3e964899bfcd71908a4f6f39c61cbd944087e | |
| parent | 629f618d69f177ff6b95483cc6232d6374cb4b0c (diff) | |
| download | emacs-21622c6d1045fc8c1ce909ffe9db980b79f3dd3a.tar.gz emacs-21622c6d1045fc8c1ce909ffe9db980b79f3dd3a.zip | |
* minibuffer.el (complete-with-action, lazy-completion-table):
Move from subr.el.
(apply-partially, completion-table-dynamic)
(completion-table-with-context, completion-table-with-terminator)
(completion-table-in-turn): New funs.
(completion--make-envvar-table, completion--embedded-envvar-table): New funs.
(read-file-name-internal): Use them.
(completion-setup-hook): Move from simple.el.
* subr.el (complete-with-action, lazy-completion-table):
* simple.el (completion-setup-hook): Move to minibuffer.el.
| -rw-r--r-- | lisp/ChangeLog | 14 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 131 | ||||
| -rw-r--r-- | lisp/simple.el | 8 | ||||
| -rw-r--r-- | lisp/subr.el | 86 |
4 files changed, 140 insertions, 99 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 49f8b81f27e..3f46d81971e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2008-04-11 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * minibuffer.el (complete-with-action, lazy-completion-table): | ||
| 4 | Move from subr.el. | ||
| 5 | (apply-partially, completion-table-dynamic) | ||
| 6 | (completion-table-with-context, completion-table-with-terminator) | ||
| 7 | (completion-table-in-turn): New funs. | ||
| 8 | (completion--make-envvar-table, completion--embedded-envvar-table): | ||
| 9 | New funs. | ||
| 10 | (read-file-name-internal): Use them. | ||
| 11 | (completion-setup-hook): Move from simple.el. | ||
| 12 | * subr.el (complete-with-action, lazy-completion-table): | ||
| 13 | * simple.el (completion-setup-hook): Move to minibuffer.el. | ||
| 14 | |||
| 1 | 2008-04-11 Glenn Morris <rgm@gnu.org> | 15 | 2008-04-11 Glenn Morris <rgm@gnu.org> |
| 2 | 16 | ||
| 3 | * Makefile.in (AUTOGENEL): Add calc/calc-loaddefs.el. | 17 | * Makefile.in (AUTOGENEL): Add calc/calc-loaddefs.el. |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 98d28824adf..9392885a61e 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -24,14 +24,102 @@ | |||
| 24 | ;; Names starting with "minibuffer--" are for functions and variables that | 24 | ;; Names starting with "minibuffer--" are for functions and variables that |
| 25 | ;; are meant to be for internal use only. | 25 | ;; are meant to be for internal use only. |
| 26 | 26 | ||
| 27 | ;; TODO: | 27 | ;; BUGS: |
| 28 | ;; - merge do-completion and complete-word | 28 | ;; - envvar completion for file names breaks completion-base-size. |
| 29 | ;; - move all I/O out of do-completion | ||
| 30 | 29 | ||
| 31 | ;;; Code: | 30 | ;;; Code: |
| 32 | 31 | ||
| 33 | (eval-when-compile (require 'cl)) | 32 | (eval-when-compile (require 'cl)) |
| 34 | 33 | ||
| 34 | ;;; Completion table manipulation | ||
| 35 | |||
| 36 | (defun apply-partially (fun &rest args) | ||
| 37 | (lexical-let ((fun fun) (args1 args)) | ||
| 38 | (lambda (&rest args2) (apply fun (append args1 args2))))) | ||
| 39 | |||
| 40 | (defun complete-with-action (action table string pred) | ||
| 41 | "Perform completion ACTION. | ||
| 42 | STRING is the string to complete. | ||
| 43 | TABLE is the completion table, which should not be a function. | ||
| 44 | PRED is a completion predicate. | ||
| 45 | ACTION can be one of nil, t or `lambda'." | ||
| 46 | ;; (assert (not (functionp table))) | ||
| 47 | (funcall | ||
| 48 | (cond | ||
| 49 | ((null action) 'try-completion) | ||
| 50 | ((eq action t) 'all-completions) | ||
| 51 | (t 'test-completion)) | ||
| 52 | string table pred)) | ||
| 53 | |||
| 54 | (defun completion-table-dynamic (fun) | ||
| 55 | "Use function FUN as a dynamic completion table. | ||
| 56 | FUN is called with one argument, the string for which completion is required, | ||
| 57 | and it should return an alist containing all the intended possible | ||
| 58 | completions. This alist may be a full list of possible completions so that FUN | ||
| 59 | can ignore the value of its argument. If completion is performed in the | ||
| 60 | minibuffer, FUN will be called in the buffer from which the minibuffer was | ||
| 61 | entered. | ||
| 62 | |||
| 63 | The result of the `dynamic-completion-table' form is a function | ||
| 64 | that can be used as the ALIST argument to `try-completion' and | ||
| 65 | `all-completion'. See Info node `(elisp)Programmed Completion'." | ||
| 66 | (lexical-let ((fun fun)) | ||
| 67 | (lambda (string pred action) | ||
| 68 | (with-current-buffer (let ((win (minibuffer-selected-window))) | ||
| 69 | (if (window-live-p win) (window-buffer win) | ||
| 70 | (current-buffer))) | ||
| 71 | (complete-with-action action (funcall fun string) string pred))))) | ||
| 72 | |||
| 73 | (defmacro lazy-completion-table (var fun) | ||
| 74 | "Initialize variable VAR as a lazy completion table. | ||
| 75 | If the completion table VAR is used for the first time (e.g., by passing VAR | ||
| 76 | as an argument to `try-completion'), the function FUN is called with no | ||
| 77 | arguments. FUN must return the completion table that will be stored in VAR. | ||
| 78 | If completion is requested in the minibuffer, FUN will be called in the buffer | ||
| 79 | from which the minibuffer was entered. The return value of | ||
| 80 | `lazy-completion-table' must be used to initialize the value of VAR. | ||
| 81 | |||
| 82 | You should give VAR a non-nil `risky-local-variable' property." | ||
| 83 | (declare (debug (symbol lambda-expr))) | ||
| 84 | (let ((str (make-symbol "string"))) | ||
| 85 | `(completion-table-dynamic | ||
| 86 | (lambda (,str) | ||
| 87 | (when (functionp ,var) | ||
| 88 | (setq ,var (,fun))) | ||
| 89 | ,var)))) | ||
| 90 | |||
| 91 | (defun completion-table-with-context (prefix table string pred action) | ||
| 92 | ;; TODO: add `suffix', and think about how we should support `pred'. | ||
| 93 | ;; Notice that `pred' is not a predicate when called from read-file-name. | ||
| 94 | ;; (if pred (setq pred (lexical-let ((pred pred)) | ||
| 95 | ;; ;; FIXME: this doesn't work if `table' is an obarray. | ||
| 96 | ;; (lambda (s) (funcall pred (concat prefix s)))))) | ||
| 97 | (let ((comp (complete-with-action action table string nil))) ;; pred | ||
| 98 | (if (stringp comp) | ||
| 99 | (concat prefix comp) | ||
| 100 | comp))) | ||
| 101 | |||
| 102 | (defun completion-table-with-terminator (terminator table string pred action) | ||
| 103 | (let ((comp (complete-with-action action table string pred))) | ||
| 104 | (if (eq action nil) | ||
| 105 | (if (eq comp t) | ||
| 106 | (concat string terminator) | ||
| 107 | (if (and (stringp comp) | ||
| 108 | (eq (complete-with-action action table comp pred) t)) | ||
| 109 | (concat comp terminator) | ||
| 110 | comp)) | ||
| 111 | comp))) | ||
| 112 | |||
| 113 | (defun completion-table-in-turn (a b) | ||
| 114 | "Create a completion table that first tries completion in A and then in B. | ||
| 115 | A and B should not be costly (or side-effecting) expressions." | ||
| 116 | (lexical-let ((a a) (b b)) | ||
| 117 | (lambda (string pred action) | ||
| 118 | (or (complete-with-action action a string pred) | ||
| 119 | (complete-with-action action b string pred))))) | ||
| 120 | |||
| 121 | ;;; Minibuffer completion | ||
| 122 | |||
| 35 | (defgroup minibuffer nil | 123 | (defgroup minibuffer nil |
| 36 | "Controlling the behavior of the minibuffer." | 124 | "Controlling the behavior of the minibuffer." |
| 37 | :link '(custom-manual "(emacs)Minibuffer") | 125 | :link '(custom-manual "(emacs)Minibuffer") |
| @@ -363,6 +451,14 @@ It also eliminates runs of equal strings." | |||
| 363 | 451 | ||
| 364 | (defvar completion-common-substring) | 452 | (defvar completion-common-substring) |
| 365 | 453 | ||
| 454 | (defvar completion-setup-hook nil | ||
| 455 | "Normal hook run at the end of setting up a completion list buffer. | ||
| 456 | When this hook is run, the current buffer is the one in which the | ||
| 457 | command to display the completion list buffer was run. | ||
| 458 | The completion list buffer is available as the value of `standard-output'. | ||
| 459 | The common prefix substring for completion may be available as the | ||
| 460 | value of `completion-common-substring'. See also `display-completion-list'.") | ||
| 461 | |||
| 366 | (defun display-completion-list (completions &optional common-substring) | 462 | (defun display-completion-list (completions &optional common-substring) |
| 367 | "Display the list of completions, COMPLETIONS, using `standard-output'. | 463 | "Display the list of completions, COMPLETIONS, using `standard-output'. |
| 368 | Each element may be just a symbol or string | 464 | Each element may be just a symbol or string |
| @@ -453,12 +549,33 @@ during running `completion-setup-hook'." | |||
| 453 | (defun minibuffer--double-dollars (str) | 549 | (defun minibuffer--double-dollars (str) |
| 454 | (replace-regexp-in-string "\\$" "$$" str)) | 550 | (replace-regexp-in-string "\\$" "$$" str)) |
| 455 | 551 | ||
| 456 | (defun read-file-name-internal (string dir action) | 552 | (defun completion--make-envvar-table () |
| 553 | (mapcar (lambda (enventry) | ||
| 554 | (substring enventry 0 (string-match "=" enventry))) | ||
| 555 | process-environment)) | ||
| 556 | |||
| 557 | (defun completion--embedded-envvar-table (string pred action) | ||
| 558 | (when (string-match (concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)" | ||
| 559 | "$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'") | ||
| 560 | string) | ||
| 561 | (let* ((beg (or (match-beginning 2) (match-beginning 1))) | ||
| 562 | (table (completion-make-envvar-table)) | ||
| 563 | (prefix (substring string 0 beg))) | ||
| 564 | (if (eq (aref string (1- beg)) ?{) | ||
| 565 | (setq table (apply-partially 'completion-table-with-terminator | ||
| 566 | "}" table))) | ||
| 567 | (completion-table-with-context prefix table | ||
| 568 | (substring string beg) | ||
| 569 | pred action)))) | ||
| 570 | |||
| 571 | (defun completion--file-name-table (string dir action) | ||
| 457 | "Internal subroutine for read-file-name. Do not call this." | 572 | "Internal subroutine for read-file-name. Do not call this." |
| 458 | (setq dir (expand-file-name dir)) | 573 | (setq dir (expand-file-name dir)) |
| 459 | (if (and (zerop (length string)) (eq 'lambda action)) | 574 | (if (and (zerop (length string)) (eq 'lambda action)) |
| 460 | nil ; FIXME: why? | 575 | nil ; FIXME: why? |
| 461 | (let* ((str (substitute-in-file-name string)) | 576 | (let* ((str (condition-case nil |
| 577 | (substitute-in-file-name string) | ||
| 578 | (error string))) | ||
| 462 | (name (file-name-nondirectory str)) | 579 | (name (file-name-nondirectory str)) |
| 463 | (specdir (file-name-directory str)) | 580 | (specdir (file-name-directory str)) |
| 464 | (realdir (if specdir (expand-file-name specdir dir) | 581 | (realdir (if specdir (expand-file-name specdir dir) |
| @@ -503,6 +620,10 @@ during running `completion-setup-hook'." | |||
| 503 | (let ((default-directory dir)) | 620 | (let ((default-directory dir)) |
| 504 | (funcall (or read-file-name-predicate 'file-exists-p) str))))))) | 621 | (funcall (or read-file-name-predicate 'file-exists-p) str))))))) |
| 505 | 622 | ||
| 623 | (defalias 'read-file-name-internal | ||
| 624 | (completion-table-in-turn 'completion-embedded-envvar-table | ||
| 625 | 'completion-file-name-table) | ||
| 626 | "Internal subroutine for `read-file-name'. Do not call this.") | ||
| 506 | 627 | ||
| 507 | (provide 'minibuffer) | 628 | (provide 'minibuffer) |
| 508 | ;;; minibuffer.el ends here | 629 | ;;; minibuffer.el ends here |
diff --git a/lisp/simple.el b/lisp/simple.el index 02d2d5c8779..90955e88e2f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -5451,14 +5451,6 @@ Called from `temp-buffer-show-hook'." | |||
| 5451 | 5451 | ||
| 5452 | (add-hook 'temp-buffer-show-hook 'completion-list-mode-finish) | 5452 | (add-hook 'temp-buffer-show-hook 'completion-list-mode-finish) |
| 5453 | 5453 | ||
| 5454 | (defvar completion-setup-hook nil | ||
| 5455 | "Normal hook run at the end of setting up a completion list buffer. | ||
| 5456 | When this hook is run, the current buffer is the one in which the | ||
| 5457 | command to display the completion list buffer was run. | ||
| 5458 | The completion list buffer is available as the value of `standard-output'. | ||
| 5459 | The common prefix substring for completion may be available as the | ||
| 5460 | value of `completion-common-substring'. See also `display-completion-list'.") | ||
| 5461 | |||
| 5462 | 5454 | ||
| 5463 | ;; Variables and faces used in `completion-setup-function'. | 5455 | ;; Variables and faces used in `completion-setup-function'. |
| 5464 | 5456 | ||
diff --git a/lisp/subr.el b/lisp/subr.el index 17fe146aff6..d81dfae4575 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -2688,92 +2688,6 @@ The value returned is the value of the last form in BODY." | |||
| 2688 | (with-current-buffer ,old-buffer | 2688 | (with-current-buffer ,old-buffer |
| 2689 | (set-case-table ,old-case-table)))))) | 2689 | (set-case-table ,old-case-table)))))) |
| 2690 | 2690 | ||
| 2691 | ;;;; Constructing completion tables. | ||
| 2692 | |||
| 2693 | (defun complete-with-action (action table string pred) | ||
| 2694 | "Perform completion ACTION. | ||
| 2695 | STRING is the string to complete. | ||
| 2696 | TABLE is the completion table, which should not be a function. | ||
| 2697 | PRED is a completion predicate. | ||
| 2698 | ACTION can be one of nil, t or `lambda'." | ||
| 2699 | ;; (assert (not (functionp table))) | ||
| 2700 | (funcall | ||
| 2701 | (cond | ||
| 2702 | ((null action) 'try-completion) | ||
| 2703 | ((eq action t) 'all-completions) | ||
| 2704 | (t 'test-completion)) | ||
| 2705 | string table pred)) | ||
| 2706 | |||
| 2707 | (defmacro dynamic-completion-table (fun) | ||
| 2708 | "Use function FUN as a dynamic completion table. | ||
| 2709 | FUN is called with one argument, the string for which completion is required, | ||
| 2710 | and it should return an alist containing all the intended possible | ||
| 2711 | completions. This alist may be a full list of possible completions so that FUN | ||
| 2712 | can ignore the value of its argument. If completion is performed in the | ||
| 2713 | minibuffer, FUN will be called in the buffer from which the minibuffer was | ||
| 2714 | entered. | ||
| 2715 | |||
| 2716 | The result of the `dynamic-completion-table' form is a function | ||
| 2717 | that can be used as the ALIST argument to `try-completion' and | ||
| 2718 | `all-completion'. See Info node `(elisp)Programmed Completion'." | ||
| 2719 | (declare (debug (lambda-expr))) | ||
| 2720 | (let ((win (make-symbol "window")) | ||
| 2721 | (string (make-symbol "string")) | ||
| 2722 | (predicate (make-symbol "predicate")) | ||
| 2723 | (mode (make-symbol "mode"))) | ||
| 2724 | `(lambda (,string ,predicate ,mode) | ||
| 2725 | (with-current-buffer (let ((,win (minibuffer-selected-window))) | ||
| 2726 | (if (window-live-p ,win) (window-buffer ,win) | ||
| 2727 | (current-buffer))) | ||
| 2728 | (complete-with-action ,mode (,fun ,string) ,string ,predicate))))) | ||
| 2729 | |||
| 2730 | (defmacro lazy-completion-table (var fun) | ||
| 2731 | ;; We used to have `&rest args' where `args' were evaluated late (at the | ||
| 2732 | ;; time of the call to `fun'), which was counter intuitive. But to get | ||
| 2733 | ;; them to be evaluated early, we have to either use lexical-let (which is | ||
| 2734 | ;; not available in subr.el) or use `(lambda (,str) ...) which prevents the use | ||
| 2735 | ;; of lexical-let in the callers. | ||
| 2736 | ;; So we just removed the argument. Callers can then simply use either of: | ||
| 2737 | ;; (lazy-completion-table var (lambda () (fun x y))) | ||
| 2738 | ;; or | ||
| 2739 | ;; (lazy-completion-table var `(lambda () (fun ',x ',y))) | ||
| 2740 | ;; or | ||
| 2741 | ;; (lexical-let ((x x)) ((y y)) | ||
| 2742 | ;; (lazy-completion-table var (lambda () (fun x y)))) | ||
| 2743 | ;; depending on the behavior they want. | ||
| 2744 | "Initialize variable VAR as a lazy completion table. | ||
| 2745 | If the completion table VAR is used for the first time (e.g., by passing VAR | ||
| 2746 | as an argument to `try-completion'), the function FUN is called with no | ||
| 2747 | arguments. FUN must return the completion table that will be stored in VAR. | ||
| 2748 | If completion is requested in the minibuffer, FUN will be called in the buffer | ||
| 2749 | from which the minibuffer was entered. The return value of | ||
| 2750 | `lazy-completion-table' must be used to initialize the value of VAR. | ||
| 2751 | |||
| 2752 | You should give VAR a non-nil `risky-local-variable' property." | ||
| 2753 | (declare (debug (symbol lambda-expr))) | ||
| 2754 | (let ((str (make-symbol "string"))) | ||
| 2755 | `(dynamic-completion-table | ||
| 2756 | (lambda (,str) | ||
| 2757 | (when (functionp ,var) | ||
| 2758 | (setq ,var (,fun))) | ||
| 2759 | ,var)))) | ||
| 2760 | |||
| 2761 | (defmacro complete-in-turn (a b) | ||
| 2762 | "Create a completion table that first tries completion in A and then in B. | ||
| 2763 | A and B should not be costly (or side-effecting) expressions." | ||
| 2764 | (declare (debug (def-form def-form))) | ||
| 2765 | `(lambda (string predicate mode) | ||
| 2766 | (cond | ||
| 2767 | ((eq mode t) | ||
| 2768 | (or (all-completions string ,a predicate) | ||
| 2769 | (all-completions string ,b predicate))) | ||
| 2770 | ((eq mode nil) | ||
| 2771 | (or (try-completion string ,a predicate) | ||
| 2772 | (try-completion string ,b predicate))) | ||
| 2773 | (t | ||
| 2774 | (or (test-completion string ,a predicate) | ||
| 2775 | (test-completion string ,b predicate)))))) | ||
| 2776 | |||
| 2777 | ;;; Matching and match data. | 2691 | ;;; Matching and match data. |
| 2778 | 2692 | ||
| 2779 | (defvar save-match-data-internal) | 2693 | (defvar save-match-data-internal) |