diff options
| -rw-r--r-- | etc/NEWS | 3 | ||||
| -rw-r--r-- | lisp/ChangeLog | 14 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 152 |
3 files changed, 157 insertions, 12 deletions
| @@ -67,6 +67,9 @@ from load-path. -Q now implies this. | |||
| 67 | 67 | ||
| 68 | * Changes in Emacs 24.1 | 68 | * Changes in Emacs 24.1 |
| 69 | 69 | ||
| 70 | ** Completion in a non-minibuffer now tries to detect the end of completion | ||
| 71 | and pops down the *Completions* buffer accordingly. | ||
| 72 | |||
| 70 | ** emacsclient changes | 73 | ** emacsclient changes |
| 71 | 74 | ||
| 72 | *** New emacsclient argument --parent-id ID can be used to open a | 75 | *** New emacsclient argument --parent-id ID can be used to open a |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 3c9e81f0b8a..03d1d6f5b19 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2011-03-30 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * minibuffer.el (completion-table-dynamic): Optimize `boundaries'. | ||
| 4 | (completion-in-region-mode): New minor mode. | ||
| 5 | (completion-in-region): Use it. | ||
| 6 | (completion-in-region--data, completion-in-region-mode-map): New vars. | ||
| 7 | (completion-in-region--postch): New function. | ||
| 8 | (completion--capf-misbehave-funs, completion--capf-safe-funs): | ||
| 9 | New vars. | ||
| 10 | (completion--capf-wrapper): New function. | ||
| 11 | (completion-at-point): Use it to track well-behavedness of | ||
| 12 | hook functions. | ||
| 13 | (completion-help-at-point): New command. | ||
| 14 | |||
| 1 | 2011-03-30 Jason Merrill <jason@redhat.com> (tiny change) | 15 | 2011-03-30 Jason Merrill <jason@redhat.com> (tiny change) |
| 2 | 16 | ||
| 3 | * vc/add-log.el (add-change-log-entry): Don't use whitespace | 17 | * vc/add-log.el (add-change-log-entry): Don't use whitespace |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index f1bc9f2d6d5..4aa34698809 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -173,10 +173,14 @@ that can be used as the COLLECTION argument to `try-completion' and | |||
| 173 | `all-completions'. See Info node `(elisp)Programmed Completion'." | 173 | `all-completions'. See Info node `(elisp)Programmed Completion'." |
| 174 | (lexical-let ((fun fun)) | 174 | (lexical-let ((fun fun)) |
| 175 | (lambda (string pred action) | 175 | (lambda (string pred action) |
| 176 | (with-current-buffer (let ((win (minibuffer-selected-window))) | 176 | (if (eq (car-safe action) 'boundaries) |
| 177 | (if (window-live-p win) (window-buffer win) | 177 | ;; `fun' is not supposed to return another function but a plain old |
| 178 | (current-buffer))) | 178 | ;; completion table, whose boundaries are always trivial. |
| 179 | (complete-with-action action (funcall fun string) string pred))))) | 179 | nil |
| 180 | (with-current-buffer (let ((win (minibuffer-selected-window))) | ||
| 181 | (if (window-live-p win) (window-buffer win) | ||
| 182 | (current-buffer))) | ||
| 183 | (complete-with-action action (funcall fun string) string pred)))))) | ||
| 180 | 184 | ||
| 181 | (defmacro lazy-completion-table (var fun) | 185 | (defmacro lazy-completion-table (var fun) |
| 182 | "Initialize variable VAR as a lazy completion table. | 186 | "Initialize variable VAR as a lazy completion table. |
| @@ -240,6 +244,10 @@ in which case TERMINATOR-REGEXP is a regular expression whose submatch | |||
| 240 | number 1 should match TERMINATOR. This is used when there is a need to | 244 | number 1 should match TERMINATOR. This is used when there is a need to |
| 241 | distinguish occurrences of the TERMINATOR strings which are really terminators | 245 | distinguish occurrences of the TERMINATOR strings which are really terminators |
| 242 | from others (e.g. escaped)." | 246 | from others (e.g. escaped)." |
| 247 | ;; FIXME: This implementation is not right since it only adds the terminator | ||
| 248 | ;; in try-completion, so any completion-style that builds the completion via | ||
| 249 | ;; all-completions won't get the terminator, and selecting an entry in | ||
| 250 | ;; *Completions* won't get the terminator added either. | ||
| 243 | (cond | 251 | (cond |
| 244 | ((eq (car-safe action) 'boundaries) | 252 | ((eq (car-safe action) 'boundaries) |
| 245 | (let* ((suffix (cdr action)) | 253 | (let* ((suffix (cdr action)) |
| @@ -716,6 +724,8 @@ scroll the window of possible completions." | |||
| 716 | (< (or s1 (length c1)) | 724 | (< (or s1 (length c1)) |
| 717 | (or s2 (length c2)))))))) | 725 | (or s2 (length c2)))))))) |
| 718 | ;; Prefer recently used completions. | 726 | ;; Prefer recently used completions. |
| 727 | ;; FIXME: Additional sorting ideas: | ||
| 728 | ;; - for M-x, prefer commands that have no key binding. | ||
| 719 | (let ((hist (symbol-value minibuffer-history-variable))) | 729 | (let ((hist (symbol-value minibuffer-history-variable))) |
| 720 | (setq all (sort all (lambda (c1 c2) | 730 | (setq all (sort all (lambda (c1 c2) |
| 721 | (> (length (member c1 hist)) | 731 | (> (length (member c1 hist)) |
| @@ -1008,8 +1018,8 @@ It also eliminates runs of equal strings." | |||
| 1008 | ;; a space displayed. | 1018 | ;; a space displayed. |
| 1009 | (set-text-properties (- (point) 1) (point) | 1019 | (set-text-properties (- (point) 1) (point) |
| 1010 | ;; We can't just set tab-width, because | 1020 | ;; We can't just set tab-width, because |
| 1011 | ;; completion-setup-function will kill all | 1021 | ;; completion-setup-function will kill |
| 1012 | ;; local variables :-( | 1022 | ;; all local variables :-( |
| 1013 | `(display (space :align-to ,column))) | 1023 | `(display (space :align-to ,column))) |
| 1014 | nil)))) | 1024 | nil)))) |
| 1015 | (if (not (consp str)) | 1025 | (if (not (consp str)) |
| @@ -1237,6 +1247,8 @@ the ones passed to `completion-in-region'. The functions on this hook | |||
| 1237 | are expected to perform completion on START..END using COLLECTION | 1247 | are expected to perform completion on START..END using COLLECTION |
| 1238 | and PREDICATE, either by calling NEXT-FUN or by doing it themselves.") | 1248 | and PREDICATE, either by calling NEXT-FUN or by doing it themselves.") |
| 1239 | 1249 | ||
| 1250 | (defvar completion-in-region--data nil) | ||
| 1251 | |||
| 1240 | (defun completion-in-region (start end collection &optional predicate) | 1252 | (defun completion-in-region (start end collection &optional predicate) |
| 1241 | "Complete the text between START and END using COLLECTION. | 1253 | "Complete the text between START and END using COLLECTION. |
| 1242 | Return nil if there is no valid completion, else t. | 1254 | Return nil if there is no valid completion, else t. |
| @@ -1251,15 +1263,78 @@ Point needs to be somewhere between START and END." | |||
| 1251 | (minibuffer-completion-predicate predicate) | 1263 | (minibuffer-completion-predicate predicate) |
| 1252 | (ol (make-overlay start end nil nil t))) | 1264 | (ol (make-overlay start end nil nil t))) |
| 1253 | (overlay-put ol 'field 'completion) | 1265 | (overlay-put ol 'field 'completion) |
| 1266 | (completion-in-region-mode 1) | ||
| 1267 | (setq completion-in-region--data | ||
| 1268 | (list (current-buffer) start end collection)) | ||
| 1254 | (unwind-protect | 1269 | (unwind-protect |
| 1255 | (call-interactively 'minibuffer-complete) | 1270 | (call-interactively 'minibuffer-complete) |
| 1256 | (delete-overlay ol))))) | 1271 | (delete-overlay ol))))) |
| 1257 | 1272 | ||
| 1273 | (defvar completion-in-region-mode-map | ||
| 1274 | (let ((map (make-sparse-keymap))) | ||
| 1275 | (define-key map "?" 'completion-help-at-point) | ||
| 1276 | (define-key map "\t" 'completion-at-point) | ||
| 1277 | map) | ||
| 1278 | "Keymap activated during `completion-in-region'.") | ||
| 1279 | |||
| 1280 | ;; It is difficult to know when to exit completion-in-region-mode (i.e. hide | ||
| 1281 | ;; the *Completions*). | ||
| 1282 | ;; - lisp-mode: never. | ||
| 1283 | ;; - comint: only do it if you hit SPC at the right time. | ||
| 1284 | ;; - pcomplete: pop it down on SPC or after some time-delay. | ||
| 1285 | ;; - semantic: use a post-command-hook check similar to this one. | ||
| 1286 | (defun completion-in-region--postch () | ||
| 1287 | (message "completion-in-region--postch: cmd=%s" this-command) | ||
| 1288 | (or unread-command-events ;Don't pop down the completions in the middle of | ||
| 1289 | ;mouse-drag-region/mouse-set-point. | ||
| 1290 | (and completion-in-region--data | ||
| 1291 | (and (eq (car completion-in-region--data) | ||
| 1292 | (current-buffer)) | ||
| 1293 | (>= (point) (nth 1 completion-in-region--data)) | ||
| 1294 | (<= (point) | ||
| 1295 | (save-excursion | ||
| 1296 | (goto-char (nth 2 completion-in-region--data)) | ||
| 1297 | (line-end-position))) | ||
| 1298 | (let ((comp-data (run-hook-wrapped | ||
| 1299 | 'completion-at-point-functions | ||
| 1300 | ;; Only use the known-safe functions. | ||
| 1301 | #'completion--capf-wrapper 'safe))) | ||
| 1302 | (eq (car comp-data) | ||
| 1303 | ;; We're still in the same completion field. | ||
| 1304 | (nth 1 completion-in-region--data))))) | ||
| 1305 | (completion-in-region-mode -1))) | ||
| 1306 | |||
| 1307 | ;; (defalias 'completion-in-region--prech 'completion-in-region--postch) | ||
| 1308 | |||
| 1309 | (define-minor-mode completion-in-region-mode | ||
| 1310 | "Transient minor mode used during `completion-in-region'." | ||
| 1311 | :global t | ||
| 1312 | (setq completion-in-region--data nil) | ||
| 1313 | ;; (remove-hook 'pre-command-hook #'completion-in-region--prech) | ||
| 1314 | (remove-hook 'post-command-hook #'completion-in-region--postch) | ||
| 1315 | (setq minor-mode-overriding-map-alist | ||
| 1316 | (delq (assq 'completion-in-region-mode minor-mode-overriding-map-alist) | ||
| 1317 | minor-mode-overriding-map-alist)) | ||
| 1318 | (if (null completion-in-region-mode) | ||
| 1319 | (progn | ||
| 1320 | (unless (equal "*Completions*" (buffer-name (window-buffer))) | ||
| 1321 | (minibuffer-hide-completions)) | ||
| 1322 | (message "Leaving completion-in-region-mode")) | ||
| 1323 | ;; (add-hook 'pre-command-hook #'completion-in-region--prech) | ||
| 1324 | (add-hook 'post-command-hook #'completion-in-region--postch) | ||
| 1325 | (push `(completion-in-region-mode . ,completion-in-region-mode-map) | ||
| 1326 | minor-mode-overriding-map-alist))) | ||
| 1327 | |||
| 1328 | ;; Define-minor-mode added our keymap to minor-mode-map-alist, but we want it | ||
| 1329 | ;; on minor-mode-overriding-map-alist instead. | ||
| 1330 | (setq minor-mode-map-alist | ||
| 1331 | (delq (assq 'completion-in-region-mode minor-mode-map-alist) | ||
| 1332 | minor-mode-map-alist)) | ||
| 1333 | |||
| 1258 | (defvar completion-at-point-functions '(tags-completion-at-point-function) | 1334 | (defvar completion-at-point-functions '(tags-completion-at-point-function) |
| 1259 | "Special hook to find the completion table for the thing at point. | 1335 | "Special hook to find the completion table for the thing at point. |
| 1260 | Each function on this hook is called in turns without any argument and should | 1336 | Each function on this hook is called in turns without any argument and should |
| 1261 | return either nil to mean that it is not applicable at point, | 1337 | return either nil to mean that it is not applicable at point, |
| 1262 | or t to mean that it already performed completion (discouraged), | ||
| 1263 | or a function of no argument to perform completion (discouraged), | 1338 | or a function of no argument to perform completion (discouraged), |
| 1264 | or a list of the form (START END COLLECTION &rest PROPS) where | 1339 | or a list of the form (START END COLLECTION &rest PROPS) where |
| 1265 | START and END delimit the entity to complete and should include point, | 1340 | START and END delimit the entity to complete and should include point, |
| @@ -1269,12 +1344,34 @@ Currently supported properties are: | |||
| 1269 | `:predicate' a predicate that completion candidates need to satisfy. | 1344 | `:predicate' a predicate that completion candidates need to satisfy. |
| 1270 | `:annotation-function' the value to use for `completion-annotate-function'.") | 1345 | `:annotation-function' the value to use for `completion-annotate-function'.") |
| 1271 | 1346 | ||
| 1347 | (defvar completion--capf-misbehave-funs nil | ||
| 1348 | "List of functions found on `completion-at-point-functions' that misbehave.") | ||
| 1349 | (defvar completion--capf-safe-funs nil | ||
| 1350 | "List of well-behaved functions found on `completion-at-point-functions'.") | ||
| 1351 | |||
| 1352 | (defun completion--capf-wrapper (fun which) | ||
| 1353 | (if (case which | ||
| 1354 | (all t) | ||
| 1355 | (safe (member fun completion--capf-safe-funs)) | ||
| 1356 | (optimist (not (member fun completion--capf-misbehave-funs)))) | ||
| 1357 | (let ((res (funcall fun))) | ||
| 1358 | (cond | ||
| 1359 | ((consp res) | ||
| 1360 | (unless (member fun completion--capf-safe-funs) | ||
| 1361 | (push fun completion--capf-safe-funs))) | ||
| 1362 | ((not (or (listp res) (functionp res))) | ||
| 1363 | (unless (member fun completion--capf-misbehave-funs) | ||
| 1364 | (message | ||
| 1365 | "Completion function %S uses a deprecated calling convention" fun) | ||
| 1366 | (push fun completion--capf-misbehave-funs)))) | ||
| 1367 | res))) | ||
| 1368 | |||
| 1272 | (defun completion-at-point () | 1369 | (defun completion-at-point () |
| 1273 | "Perform completion on the text around point. | 1370 | "Perform completion on the text around point. |
| 1274 | The completion method is determined by `completion-at-point-functions'." | 1371 | The completion method is determined by `completion-at-point-functions'." |
| 1275 | (interactive) | 1372 | (interactive) |
| 1276 | (let ((res (run-hook-with-args-until-success | 1373 | (let ((res (run-hook-wrapped 'completion-at-point-functions |
| 1277 | 'completion-at-point-functions))) | 1374 | #'completion--capf-wrapper 'all))) |
| 1278 | (cond | 1375 | (cond |
| 1279 | ((functionp res) (funcall res)) | 1376 | ((functionp res) (funcall res)) |
| 1280 | ((consp res) | 1377 | ((consp res) |
| @@ -1288,6 +1385,37 @@ The completion method is determined by `completion-at-point-functions'." | |||
| 1288 | (plist-get plist :predicate)))) | 1385 | (plist-get plist :predicate)))) |
| 1289 | (res)))) ;Maybe completion already happened and the function returned t. | 1386 | (res)))) ;Maybe completion already happened and the function returned t. |
| 1290 | 1387 | ||
| 1388 | (defun completion-help-at-point () | ||
| 1389 | "Display the completions on the text around point. | ||
| 1390 | The completion method is determined by `completion-at-point-functions'." | ||
| 1391 | (interactive) | ||
| 1392 | (let ((res (run-hook-wrapped 'completion-at-point-functions | ||
| 1393 | ;; Ignore misbehaving functions. | ||
| 1394 | #'completion--capf-wrapper 'optimist))) | ||
| 1395 | (cond | ||
| 1396 | ((functionp res) | ||
| 1397 | (message "Don't know how to show completions for %S" res)) | ||
| 1398 | ((consp res) | ||
| 1399 | (let* ((plist (nthcdr 3 res)) | ||
| 1400 | (minibuffer-completion-table (nth 2 res)) | ||
| 1401 | (minibuffer-completion-predicate (plist-get plist :predicate)) | ||
| 1402 | (completion-annotate-function | ||
| 1403 | (or (plist-get plist :annotation-function) | ||
| 1404 | completion-annotate-function)) | ||
| 1405 | (ol (make-overlay (nth 0 res) (nth 1 res) nil nil t))) | ||
| 1406 | ;; FIXME: We should somehow (ab)use completion-in-region-function or | ||
| 1407 | ;; introduce a corresponding hook (plus another for word-completion, | ||
| 1408 | ;; and another for force-completion, maybe?). | ||
| 1409 | (overlay-put ol 'field 'completion) | ||
| 1410 | (unwind-protect | ||
| 1411 | (call-interactively 'minibuffer-completion-help) | ||
| 1412 | (delete-overlay ol)))) | ||
| 1413 | (res | ||
| 1414 | ;; The hook function already performed completion :-( | ||
| 1415 | ;; Not much we can do at this point. | ||
| 1416 | nil) | ||
| 1417 | (t (message "Nothing to complete at point"))))) | ||
| 1418 | |||
| 1291 | ;;; Key bindings. | 1419 | ;;; Key bindings. |
| 1292 | 1420 | ||
| 1293 | (define-obsolete-variable-alias 'minibuffer-local-must-match-filename-map | 1421 | (define-obsolete-variable-alias 'minibuffer-local-must-match-filename-map |
| @@ -1910,9 +2038,9 @@ or a symbol chosen among `any', `star', `point', `prefix'." | |||
| 1910 | (append (completion-pcm--string->pattern prefix) | 2038 | (append (completion-pcm--string->pattern prefix) |
| 1911 | '(point) | 2039 | '(point) |
| 1912 | (completion-pcm--string->pattern suffix))) | 2040 | (completion-pcm--string->pattern suffix))) |
| 1913 | (let ((pattern nil) | 2041 | (let* ((pattern nil) |
| 1914 | (p 0) | 2042 | (p 0) |
| 1915 | (p0 0)) | 2043 | (p0 p)) |
| 1916 | 2044 | ||
| 1917 | (while (and (setq p (string-match completion-pcm--delim-wild-regex | 2045 | (while (and (setq p (string-match completion-pcm--delim-wild-regex |
| 1918 | string p)) | 2046 | string p)) |