aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2008-04-11 22:28:02 +0000
committerStefan Monnier2008-04-11 22:28:02 +0000
commit21622c6d1045fc8c1ce909ffe9db980b79f3dd3a (patch)
tree16a3e964899bfcd71908a4f6f39c61cbd944087e
parent629f618d69f177ff6b95483cc6232d6374cb4b0c (diff)
downloademacs-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/ChangeLog14
-rw-r--r--lisp/minibuffer.el131
-rw-r--r--lisp/simple.el8
-rw-r--r--lisp/subr.el86
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 @@
12008-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
12008-04-11 Glenn Morris <rgm@gnu.org> 152008-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.
42STRING is the string to complete.
43TABLE is the completion table, which should not be a function.
44PRED is a completion predicate.
45ACTION 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.
56FUN is called with one argument, the string for which completion is required,
57and it should return an alist containing all the intended possible
58completions. This alist may be a full list of possible completions so that FUN
59can ignore the value of its argument. If completion is performed in the
60minibuffer, FUN will be called in the buffer from which the minibuffer was
61entered.
62
63The result of the `dynamic-completion-table' form is a function
64that 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.
75If the completion table VAR is used for the first time (e.g., by passing VAR
76as an argument to `try-completion'), the function FUN is called with no
77arguments. FUN must return the completion table that will be stored in VAR.
78If completion is requested in the minibuffer, FUN will be called in the buffer
79from which the minibuffer was entered. The return value of
80`lazy-completion-table' must be used to initialize the value of VAR.
81
82You 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.
115A 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.
456When this hook is run, the current buffer is the one in which the
457command to display the completion list buffer was run.
458The completion list buffer is available as the value of `standard-output'.
459The common prefix substring for completion may be available as the
460value 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'.
368Each element may be just a symbol or string 464Each 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.
5456When this hook is run, the current buffer is the one in which the
5457command to display the completion list buffer was run.
5458The completion list buffer is available as the value of `standard-output'.
5459The common prefix substring for completion may be available as the
5460value 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.
2695STRING is the string to complete.
2696TABLE is the completion table, which should not be a function.
2697PRED is a completion predicate.
2698ACTION 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.
2709FUN is called with one argument, the string for which completion is required,
2710and it should return an alist containing all the intended possible
2711completions. This alist may be a full list of possible completions so that FUN
2712can ignore the value of its argument. If completion is performed in the
2713minibuffer, FUN will be called in the buffer from which the minibuffer was
2714entered.
2715
2716The result of the `dynamic-completion-table' form is a function
2717that 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.
2745If the completion table VAR is used for the first time (e.g., by passing VAR
2746as an argument to `try-completion'), the function FUN is called with no
2747arguments. FUN must return the completion table that will be stored in VAR.
2748If completion is requested in the minibuffer, FUN will be called in the buffer
2749from which the minibuffer was entered. The return value of
2750`lazy-completion-table' must be used to initialize the value of VAR.
2751
2752You 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.
2763A 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)