aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS3
-rw-r--r--lisp/ChangeLog14
-rw-r--r--lisp/minibuffer.el152
3 files changed, 157 insertions, 12 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 969b1cdcf5f..76078ec14fe 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
71and 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 @@
12011-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
12011-03-30 Jason Merrill <jason@redhat.com> (tiny change) 152011-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
240number 1 should match TERMINATOR. This is used when there is a need to 244number 1 should match TERMINATOR. This is used when there is a need to
241distinguish occurrences of the TERMINATOR strings which are really terminators 245distinguish occurrences of the TERMINATOR strings which are really terminators
242from others (e.g. escaped)." 246from 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
1237are expected to perform completion on START..END using COLLECTION 1247are expected to perform completion on START..END using COLLECTION
1238and PREDICATE, either by calling NEXT-FUN or by doing it themselves.") 1248and 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.
1242Return nil if there is no valid completion, else t. 1254Return 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.
1260Each function on this hook is called in turns without any argument and should 1336Each function on this hook is called in turns without any argument and should
1261return either nil to mean that it is not applicable at point, 1337return either nil to mean that it is not applicable at point,
1262or t to mean that it already performed completion (discouraged),
1263or a function of no argument to perform completion (discouraged), 1338or a function of no argument to perform completion (discouraged),
1264or a list of the form (START END COLLECTION &rest PROPS) where 1339or 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.
1274The completion method is determined by `completion-at-point-functions'." 1371The 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.
1390The 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))