diff options
| author | Stefan Monnier | 2011-05-31 18:40:30 -0300 |
|---|---|---|
| committer | Stefan Monnier | 2011-05-31 18:40:30 -0300 |
| commit | 30a235016ebe8326593b16ed42daeeaa4dead526 (patch) | |
| tree | 83d273354080c337be857278eb4567e7bce99fd5 | |
| parent | 5a94384bca430c6cd8161d1825e14639c2a5a7e3 (diff) | |
| download | emacs-30a235016ebe8326593b16ed42daeeaa4dead526.tar.gz emacs-30a235016ebe8326593b16ed42daeeaa4dead526.zip | |
* lisp/minibuffer.el (complete-with-action): Return nil for the metadata and
boundaries of non-functional tables.
(completion-table-dynamic): Return nil for the metadata.
(completion-table-with-terminator): Add default case, using
complete-with-action.
(completion--metadata): New function.
(completion-all-sorted-completions, minibuffer-completion-help): Use it
to try and avoid pathological performance problems.
(completion--embedded-envvar-table): Return `category' metadata.
| -rw-r--r-- | lisp/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 99 |
2 files changed, 72 insertions, 39 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 384a30cb7cd..8f96a838cc5 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2011-05-31 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * minibuffer.el (complete-with-action): Return nil for the metadata and | ||
| 4 | boundaries of non-functional tables. | ||
| 5 | (completion-table-dynamic): Return nil for the metadata. | ||
| 6 | (completion-table-with-terminator): Add default case, using | ||
| 7 | complete-with-action. | ||
| 8 | (completion--metadata): New function. | ||
| 9 | (completion-all-sorted-completions, minibuffer-completion-help): Use it | ||
| 10 | to try and avoid pathological performance problems. | ||
| 11 | (completion--embedded-envvar-table): Return `category' metadata. | ||
| 12 | |||
| 1 | 2011-05-31 Lars Magne Ingebrigtsen <larsi@gnus.org> | 13 | 2011-05-31 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 14 | ||
| 3 | * subr.el (process-alive-p): New tiny convenience function. | 15 | * subr.el (process-alive-p): New tiny convenience function. |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 0f96f7905eb..972c65f62e3 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -26,11 +26,15 @@ | |||
| 26 | ;; internal use only. | 26 | ;; internal use only. |
| 27 | 27 | ||
| 28 | ;; Functional completion tables have an extended calling conventions: | 28 | ;; Functional completion tables have an extended calling conventions: |
| 29 | ;; - The `action' can be (additionally to nil, t, and lambda) of the form | 29 | ;; The `action' can be (additionally to nil, t, and lambda) of the form |
| 30 | ;; (boundaries . SUFFIX) in which case it should return | 30 | ;; - (boundaries . SUFFIX) in which case it should return |
| 31 | ;; (boundaries START . END). See `completion-boundaries'. | 31 | ;; (boundaries START . END). See `completion-boundaries'. |
| 32 | ;; Any other return value should be ignored (so we ignore values returned | 32 | ;; Any other return value should be ignored (so we ignore values returned |
| 33 | ;; from completion tables that don't know about this new `action' form). | 33 | ;; from completion tables that don't know about this new `action' form). |
| 34 | ;; - `metadata' in which case it should return (metadata . ALIST) where | ||
| 35 | ;; ALIST is the metadata of this table. See `completion-metadata'. | ||
| 36 | ;; Any other return value should be ignored (so we ignore values returned | ||
| 37 | ;; from completion tables that don't know about this new `action' form). | ||
| 34 | 38 | ||
| 35 | ;;; Bugs: | 39 | ;;; Bugs: |
| 36 | 40 | ||
| @@ -107,7 +111,8 @@ E.g. for simple completion tables, the result is always (0 . (length SUFFIX)) | |||
| 107 | and for file names the result is the positions delimited by | 111 | and for file names the result is the positions delimited by |
| 108 | the closest directory separators." | 112 | the closest directory separators." |
| 109 | (let ((boundaries (if (functionp table) | 113 | (let ((boundaries (if (functionp table) |
| 110 | (funcall table string pred (cons 'boundaries suffix))))) | 114 | (funcall table string pred |
| 115 | (cons 'boundaries suffix))))) | ||
| 111 | (if (not (eq (car-safe boundaries) 'boundaries)) | 116 | (if (not (eq (car-safe boundaries) 'boundaries)) |
| 112 | (setq boundaries nil)) | 117 | (setq boundaries nil)) |
| 113 | (cons (or (cadr boundaries) 0) | 118 | (cons (or (cadr boundaries) 0) |
| @@ -125,7 +130,8 @@ This metadata is an alist. Currently understood keys are: | |||
| 125 | Takes one argument (COMPLETIONS) and should return a new list | 130 | Takes one argument (COMPLETIONS) and should return a new list |
| 126 | of completions. Can operate destructively. | 131 | of completions. Can operate destructively. |
| 127 | - `cycle-sort-function': function to sort entries when cycling. | 132 | - `cycle-sort-function': function to sort entries when cycling. |
| 128 | Works like `display-sort-function'." | 133 | Works like `display-sort-function'. |
| 134 | The metadata of a completion table should be constant between two boundaries." | ||
| 129 | (let ((metadata (if (functionp table) | 135 | (let ((metadata (if (functionp table) |
| 130 | (funcall table string pred 'metadata)))) | 136 | (funcall table string pred 'metadata)))) |
| 131 | (if (eq (car-safe metadata) 'metadata) | 137 | (if (eq (car-safe metadata) 'metadata) |
| @@ -160,8 +166,8 @@ PRED is a completion predicate. | |||
| 160 | ACTION can be one of nil, t or `lambda'." | 166 | ACTION can be one of nil, t or `lambda'." |
| 161 | (cond | 167 | (cond |
| 162 | ((functionp table) (funcall table string pred action)) | 168 | ((functionp table) (funcall table string pred action)) |
| 163 | ((eq (car-safe action) 'boundaries) | 169 | ((eq (car-safe action) 'boundaries) nil) |
| 164 | (cons 'boundaries (completion-boundaries string table pred (cdr action)))) | 170 | ((eq action 'metadata) nil) |
| 165 | (t | 171 | (t |
| 166 | (funcall | 172 | (funcall |
| 167 | (cond | 173 | (cond |
| @@ -182,7 +188,7 @@ The result of the `completion-table-dynamic' form is a function | |||
| 182 | that can be used as the COLLECTION argument to `try-completion' and | 188 | that can be used as the COLLECTION argument to `try-completion' and |
| 183 | `all-completions'. See Info node `(elisp)Programmed Completion'." | 189 | `all-completions'. See Info node `(elisp)Programmed Completion'." |
| 184 | (lambda (string pred action) | 190 | (lambda (string pred action) |
| 185 | (if (eq (car-safe action) 'boundaries) | 191 | (if (or (eq (car-safe action) 'boundaries) (eq action 'metadata)) |
| 186 | ;; `fun' is not supposed to return another function but a plain old | 192 | ;; `fun' is not supposed to return another function but a plain old |
| 187 | ;; completion table, whose boundaries are always trivial. | 193 | ;; completion table, whose boundaries are always trivial. |
| 188 | nil | 194 | nil |
| @@ -287,18 +293,18 @@ instead of a string, a function that takes the completion and returns the | |||
| 287 | (funcall terminator comp) | 293 | (funcall terminator comp) |
| 288 | (concat comp terminator)) | 294 | (concat comp terminator)) |
| 289 | comp)))) | 295 | comp)))) |
| 290 | ((eq action t) | 296 | ;; completion-table-with-terminator is always used for |
| 297 | ;; "sub-completions" so it's only called if the terminator is missing, | ||
| 298 | ;; in which case `test-completion' should return nil. | ||
| 299 | ((eq action 'lambda) nil) | ||
| 300 | (t | ||
| 291 | ;; FIXME: We generally want the `try' and `all' behaviors to be | 301 | ;; FIXME: We generally want the `try' and `all' behaviors to be |
| 292 | ;; consistent so pcm can merge the `all' output to get the `try' output, | 302 | ;; consistent so pcm can merge the `all' output to get the `try' output, |
| 293 | ;; but that sometimes clashes with the need for `all' output to look | 303 | ;; but that sometimes clashes with the need for `all' output to look |
| 294 | ;; good in *Completions*. | 304 | ;; good in *Completions*. |
| 295 | ;; (mapcar (lambda (s) (concat s terminator)) | 305 | ;; (mapcar (lambda (s) (concat s terminator)) |
| 296 | ;; (all-completions string table pred)))) | 306 | ;; (all-completions string table pred)))) |
| 297 | (all-completions string table pred)) | 307 | (complete-with-action action table string pred)))) |
| 298 | ;; completion-table-with-terminator is always used for | ||
| 299 | ;; "sub-completions" so it's only called if the terminator is missing, | ||
| 300 | ;; in which case `test-completion' should return nil. | ||
| 301 | ((eq action 'lambda) nil))) | ||
| 302 | 308 | ||
| 303 | (defun completion-table-with-predicate (table pred1 strict string pred2 action) | 309 | (defun completion-table-with-predicate (table pred1 strict string pred2 action) |
| 304 | "Make a completion table equivalent to TABLE but filtered through PRED1. | 310 | "Make a completion table equivalent to TABLE but filtered through PRED1. |
| @@ -769,22 +775,33 @@ scroll the window of possible completions." | |||
| 769 | (setq completion-cycling nil) | 775 | (setq completion-cycling nil) |
| 770 | (setq completion-all-sorted-completions nil)) | 776 | (setq completion-all-sorted-completions nil)) |
| 771 | 777 | ||
| 778 | (defun completion--metadata (string base md-at-point table pred) | ||
| 779 | ;; Like completion-metadata, but for the specific case of getting the | ||
| 780 | ;; metadata at `base', which tends to trigger pathological behavior for old | ||
| 781 | ;; completion tables which don't understand `metadata'. | ||
| 782 | (let ((bounds (completion-boundaries string table pred ""))) | ||
| 783 | (if (eq (car bounds) base) md-at-point | ||
| 784 | (completion-metadata (substring string 0 base) table pred)))) | ||
| 785 | |||
| 772 | (defun completion-all-sorted-completions () | 786 | (defun completion-all-sorted-completions () |
| 773 | (or completion-all-sorted-completions | 787 | (or completion-all-sorted-completions |
| 774 | (let* ((start (field-beginning)) | 788 | (let* ((start (field-beginning)) |
| 775 | (end (field-end)) | 789 | (end (field-end)) |
| 776 | (string (buffer-substring start end)) | 790 | (string (buffer-substring start end)) |
| 791 | (md (completion--field-metadata start)) | ||
| 777 | (all (completion-all-completions | 792 | (all (completion-all-completions |
| 778 | string | 793 | string |
| 779 | minibuffer-completion-table | 794 | minibuffer-completion-table |
| 780 | minibuffer-completion-predicate | 795 | minibuffer-completion-predicate |
| 781 | (- (point) start) | 796 | (- (point) start) |
| 782 | (completion--field-metadata start))) | 797 | md)) |
| 783 | (last (last all)) | 798 | (last (last all)) |
| 784 | (base-size (or (cdr last) 0)) | 799 | (base-size (or (cdr last) 0)) |
| 785 | (all-md (completion-metadata (substring string 0 base-size) | 800 | (all-md (completion--metadata (buffer-substring-no-properties |
| 786 | minibuffer-completion-table | 801 | start (point)) |
| 787 | minibuffer-completion-predicate)) | 802 | base-size md |
| 803 | minibuffer-completion-table | ||
| 804 | minibuffer-completion-predicate)) | ||
| 788 | (sort-fun (completion-metadata-get all-md 'cycle-sort-function))) | 805 | (sort-fun (completion-metadata-get all-md 'cycle-sort-function))) |
| 789 | (when last | 806 | (when last |
| 790 | (setcdr last nil) | 807 | (setcdr last nil) |
| @@ -1272,12 +1289,13 @@ variables.") | |||
| 1272 | (let* ((start (field-beginning)) | 1289 | (let* ((start (field-beginning)) |
| 1273 | (end (field-end)) | 1290 | (end (field-end)) |
| 1274 | (string (field-string)) | 1291 | (string (field-string)) |
| 1292 | (md (completion--field-metadata start)) | ||
| 1275 | (completions (completion-all-completions | 1293 | (completions (completion-all-completions |
| 1276 | string | 1294 | string |
| 1277 | minibuffer-completion-table | 1295 | minibuffer-completion-table |
| 1278 | minibuffer-completion-predicate | 1296 | minibuffer-completion-predicate |
| 1279 | (- (point) (field-beginning)) | 1297 | (- (point) (field-beginning)) |
| 1280 | (completion--field-metadata start)))) | 1298 | md))) |
| 1281 | (message nil) | 1299 | (message nil) |
| 1282 | (if (or (null completions) | 1300 | (if (or (null completions) |
| 1283 | (and (not (consp (cdr completions))) | 1301 | (and (not (consp (cdr completions))) |
| @@ -1293,12 +1311,11 @@ variables.") | |||
| 1293 | (let* ((last (last completions)) | 1311 | (let* ((last (last completions)) |
| 1294 | (base-size (cdr last)) | 1312 | (base-size (cdr last)) |
| 1295 | (prefix (unless (zerop base-size) (substring string 0 base-size))) | 1313 | (prefix (unless (zerop base-size) (substring string 0 base-size))) |
| 1296 | ;; FIXME: This function is for the output of all-completions, | 1314 | (all-md (completion--metadata (buffer-substring-no-properties |
| 1297 | ;; not completion-all-completions. Often it's the same, but | 1315 | start (point)) |
| 1298 | ;; not always. | 1316 | base-size md |
| 1299 | (all-md (completion-metadata (substring string 0 base-size) | 1317 | minibuffer-completion-table |
| 1300 | minibuffer-completion-table | 1318 | minibuffer-completion-predicate)) |
| 1301 | minibuffer-completion-predicate)) | ||
| 1302 | (afun (or (completion-metadata-get all-md 'annotation-function) | 1319 | (afun (or (completion-metadata-get all-md 'annotation-function) |
| 1303 | (plist-get completion-extra-properties | 1320 | (plist-get completion-extra-properties |
| 1304 | :annotation-function) | 1321 | :annotation-function) |
| @@ -1673,8 +1690,8 @@ same as `substitute-in-file-name'." | |||
| 1673 | ;; other table that provides the "main" completion. Let the | 1690 | ;; other table that provides the "main" completion. Let the |
| 1674 | ;; other table handle the test-completion case. | 1691 | ;; other table handle the test-completion case. |
| 1675 | nil) | 1692 | nil) |
| 1676 | ((eq (car-safe action) 'boundaries) | 1693 | ((or (eq (car-safe action) 'boundaries) (eq action 'metadata)) |
| 1677 | ;; Only return boundaries if there's something to complete, | 1694 | ;; Only return boundaries/metadata if there's something to complete, |
| 1678 | ;; since otherwise when we're used in | 1695 | ;; since otherwise when we're used in |
| 1679 | ;; completion-table-in-turn, we could return boundaries and | 1696 | ;; completion-table-in-turn, we could return boundaries and |
| 1680 | ;; let some subsequent table return a list of completions. | 1697 | ;; let some subsequent table return a list of completions. |
| @@ -1684,11 +1701,13 @@ same as `substitute-in-file-name'." | |||
| 1684 | (when (try-completion (substring string beg) table nil) | 1701 | (when (try-completion (substring string beg) table nil) |
| 1685 | ;; Compute the boundaries of the subfield to which this | 1702 | ;; Compute the boundaries of the subfield to which this |
| 1686 | ;; completion applies. | 1703 | ;; completion applies. |
| 1687 | (let ((suffix (cdr action))) | 1704 | (if (eq action 'metadata) |
| 1688 | (list* 'boundaries | 1705 | '(metadata (category . environment-variable)) |
| 1689 | (or (match-beginning 2) (match-beginning 1)) | 1706 | (let ((suffix (cdr action))) |
| 1690 | (when (string-match "[^[:alnum:]_]" suffix) | 1707 | (list* 'boundaries |
| 1691 | (match-beginning 0)))))) | 1708 | (or (match-beginning 2) (match-beginning 1)) |
| 1709 | (when (string-match "[^[:alnum:]_]" suffix) | ||
| 1710 | (match-beginning 0))))))) | ||
| 1692 | (t | 1711 | (t |
| 1693 | (if (eq (aref string (1- beg)) ?{) | 1712 | (if (eq (aref string (1- beg)) ?{) |
| 1694 | (setq table (apply-partially 'completion-table-with-terminator | 1713 | (setq table (apply-partially 'completion-table-with-terminator |
| @@ -2299,7 +2318,8 @@ PATTERN is as returned by `completion-pcm--string->pattern'." | |||
| 2299 | (case-fold-search completion-ignore-case) | 2318 | (case-fold-search completion-ignore-case) |
| 2300 | (completion-regexp-list (cons regex completion-regexp-list)) | 2319 | (completion-regexp-list (cons regex completion-regexp-list)) |
| 2301 | (compl (all-completions | 2320 | (compl (all-completions |
| 2302 | (concat prefix (if (stringp (car pattern)) (car pattern) "")) | 2321 | (concat prefix |
| 2322 | (if (stringp (car pattern)) (car pattern) "")) | ||
| 2303 | table pred))) | 2323 | table pred))) |
| 2304 | (if (not (functionp table)) | 2324 | (if (not (functionp table)) |
| 2305 | ;; The internal functions already obeyed completion-regexp-list. | 2325 | ;; The internal functions already obeyed completion-regexp-list. |
| @@ -2397,13 +2417,14 @@ filter out additional entries (because TABLE migth not obey PRED)." | |||
| 2397 | (- (length newbeforepoint) | 2417 | (- (length newbeforepoint) |
| 2398 | (car newbounds))))) | 2418 | (car newbounds))))) |
| 2399 | (dolist (submatch suball) | 2419 | (dolist (submatch suball) |
| 2400 | (setq all (nconc (mapcar | 2420 | (setq all (nconc |
| 2401 | (lambda (s) (concat submatch between s)) | 2421 | (mapcar |
| 2402 | (funcall filter | 2422 | (lambda (s) (concat submatch between s)) |
| 2403 | (completion-pcm--all-completions | 2423 | (funcall filter |
| 2404 | (concat subprefix submatch between) | 2424 | (completion-pcm--all-completions |
| 2405 | pattern table pred))) | 2425 | (concat subprefix submatch between) |
| 2406 | all))) | 2426 | pattern table pred))) |
| 2427 | all))) | ||
| 2407 | ;; FIXME: This can come in handy for try-completion, | 2428 | ;; FIXME: This can come in handy for try-completion, |
| 2408 | ;; but isn't right for all-completions, since it lists | 2429 | ;; but isn't right for all-completions, since it lists |
| 2409 | ;; invalid completions. | 2430 | ;; invalid completions. |