diff options
| author | Juri Linkov | 2007-07-23 20:29:55 +0000 |
|---|---|---|
| committer | Juri Linkov | 2007-07-23 20:29:55 +0000 |
| commit | 297b8ccd7a0a30b566ea95d6c3ac20a8e68e9818 (patch) | |
| tree | 19810f77a4ca16669d47aad253c02c148a453ca2 | |
| parent | ac475d3a720d3f0650061411d40403d6f9bba04d (diff) | |
| download | emacs-297b8ccd7a0a30b566ea95d6c3ac20a8e68e9818.tar.gz emacs-297b8ccd7a0a30b566ea95d6c3ac20a8e68e9818.zip | |
(goto-history-element): New function created from
next-history-element.
(next-history-element): Most code moved to goto-history-element.
Call goto-history-element with (- minibuffer-history-position n).
(previous-history-element): Call goto-history-element with (+
minibuffer-history-position n).
(minibuffer-setup-hook): Add minibuffer-history-isearch-setup.
(minibuffer-history-isearch-message-overlay): New buffer-local variable.
(minibuffer-history-isearch-setup, minibuffer-history-isearch-end)
(minibuffer-history-isearch-search, minibuffer-history-isearch-message)
(minibuffer-history-isearch-wrap, minibuffer-history-isearch-push-state)
(minibuffer-history-isearch-pop-state): New functions.
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/simple.el | 215 |
3 files changed, 204 insertions, 39 deletions
| @@ -57,6 +57,16 @@ recenter the visited source file. Its value can be a number (for example, | |||
| 57 | 57 | ||
| 58 | ** New command kill-matching-buffers kills buffers whose name matches a regexp. | 58 | ** New command kill-matching-buffers kills buffers whose name matches a regexp. |
| 59 | 59 | ||
| 60 | ** Minibuffer changes: | ||
| 61 | |||
| 62 | *** isearch started in the minibuffer searches in the minibuffer history. | ||
| 63 | Reverse isearch commands (C-r, C-M-r) search in previous minibuffer | ||
| 64 | history elements, and forward isearch commands (C-s, C-M-s) search in | ||
| 65 | next history elements. When the reverse search reaches the first history | ||
| 66 | element, it wraps to the last history element, and the forward search | ||
| 67 | wraps to the first history element. When the search is terminated, the | ||
| 68 | history element containing the search string becomes the current. | ||
| 69 | |||
| 60 | 70 | ||
| 61 | * New Modes and Packages in Emacs 23.1 | 71 | * New Modes and Packages in Emacs 23.1 |
| 62 | 72 | ||
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 88481804473..b8872038d0a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2007-07-23 Juri Linkov <juri@jurta.org> | ||
| 2 | |||
| 3 | * isearch.el (isearch-message-function): New variable. | ||
| 4 | (isearch-update, isearch-search): Use it. | ||
| 5 | |||
| 6 | * simple.el (goto-history-element): New function created from | ||
| 7 | next-history-element. | ||
| 8 | (next-history-element): Most code moved to goto-history-element. | ||
| 9 | Call goto-history-element with (- minibuffer-history-position n). | ||
| 10 | (previous-history-element): Call goto-history-element with (+ | ||
| 11 | minibuffer-history-position n). | ||
| 12 | (minibuffer-setup-hook): Add minibuffer-history-isearch-setup. | ||
| 13 | (minibuffer-history-isearch-message-overlay): New buffer-local variable. | ||
| 14 | (minibuffer-history-isearch-setup, minibuffer-history-isearch-end) | ||
| 15 | (minibuffer-history-isearch-search, minibuffer-history-isearch-message) | ||
| 16 | (minibuffer-history-isearch-wrap, minibuffer-history-isearch-push-state) | ||
| 17 | (minibuffer-history-isearch-pop-state): New functions. | ||
| 18 | |||
| 1 | 2007-07-23 Thien-Thi Nguyen <ttn@gnuvola.org> | 19 | 2007-07-23 Thien-Thi Nguyen <ttn@gnuvola.org> |
| 2 | 20 | ||
| 3 | * vc-hooks.el (vc-stay-local-p): Fix bug: Avoid remove-if-not. | 21 | * vc-hooks.el (vc-stay-local-p): Fix bug: Avoid remove-if-not. |
diff --git a/lisp/simple.el b/lisp/simple.el index c052ce3574b..10374e16cd2 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -1300,55 +1300,61 @@ makes the search case-sensitive." | |||
| 1300 | 1300 | ||
| 1301 | (defvar minibuffer-temporary-goal-position nil) | 1301 | (defvar minibuffer-temporary-goal-position nil) |
| 1302 | 1302 | ||
| 1303 | (defun goto-history-element (nabs) | ||
| 1304 | "Puts element of the minibuffer history in the minibuffer. | ||
| 1305 | The argument NABS specifies the absolute history position." | ||
| 1306 | (interactive "p") | ||
| 1307 | (let ((minimum (if minibuffer-default -1 0)) | ||
| 1308 | elt minibuffer-returned-to-present) | ||
| 1309 | (if (and (zerop minibuffer-history-position) | ||
| 1310 | (null minibuffer-text-before-history)) | ||
| 1311 | (setq minibuffer-text-before-history | ||
| 1312 | (minibuffer-contents-no-properties))) | ||
| 1313 | (if (< nabs minimum) | ||
| 1314 | (if minibuffer-default | ||
| 1315 | (error "End of history; no next item") | ||
| 1316 | (error "End of history; no default available"))) | ||
| 1317 | (if (> nabs (length (symbol-value minibuffer-history-variable))) | ||
| 1318 | (error "Beginning of history; no preceding item")) | ||
| 1319 | (unless (memq last-command '(next-history-element | ||
| 1320 | previous-history-element)) | ||
| 1321 | (let ((prompt-end (minibuffer-prompt-end))) | ||
| 1322 | (set (make-local-variable 'minibuffer-temporary-goal-position) | ||
| 1323 | (cond ((<= (point) prompt-end) prompt-end) | ||
| 1324 | ((eobp) nil) | ||
| 1325 | (t (point)))))) | ||
| 1326 | (goto-char (point-max)) | ||
| 1327 | (delete-minibuffer-contents) | ||
| 1328 | (setq minibuffer-history-position nabs) | ||
| 1329 | (cond ((= nabs -1) | ||
| 1330 | (setq elt minibuffer-default)) | ||
| 1331 | ((= nabs 0) | ||
| 1332 | (setq elt (or minibuffer-text-before-history "")) | ||
| 1333 | (setq minibuffer-returned-to-present t) | ||
| 1334 | (setq minibuffer-text-before-history nil)) | ||
| 1335 | (t (setq elt (nth (1- minibuffer-history-position) | ||
| 1336 | (symbol-value minibuffer-history-variable))))) | ||
| 1337 | (insert | ||
| 1338 | (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth)) | ||
| 1339 | (not minibuffer-returned-to-present)) | ||
| 1340 | (let ((print-level nil)) | ||
| 1341 | (prin1-to-string elt)) | ||
| 1342 | elt)) | ||
| 1343 | (goto-char (or minibuffer-temporary-goal-position (point-max))))) | ||
| 1344 | |||
| 1303 | (defun next-history-element (n) | 1345 | (defun next-history-element (n) |
| 1304 | "Puts next element of the minibuffer history in the minibuffer. | 1346 | "Puts next element of the minibuffer history in the minibuffer. |
| 1305 | With argument N, it uses the Nth following element." | 1347 | With argument N, it uses the Nth following element." |
| 1306 | (interactive "p") | 1348 | (interactive "p") |
| 1307 | (or (zerop n) | 1349 | (or (zerop n) |
| 1308 | (let ((narg (- minibuffer-history-position n)) | 1350 | (goto-history-element (- minibuffer-history-position n)))) |
| 1309 | (minimum (if minibuffer-default -1 0)) | ||
| 1310 | elt minibuffer-returned-to-present) | ||
| 1311 | (if (and (zerop minibuffer-history-position) | ||
| 1312 | (null minibuffer-text-before-history)) | ||
| 1313 | (setq minibuffer-text-before-history | ||
| 1314 | (minibuffer-contents-no-properties))) | ||
| 1315 | (if (< narg minimum) | ||
| 1316 | (if minibuffer-default | ||
| 1317 | (error "End of history; no next item") | ||
| 1318 | (error "End of history; no default available"))) | ||
| 1319 | (if (> narg (length (symbol-value minibuffer-history-variable))) | ||
| 1320 | (error "Beginning of history; no preceding item")) | ||
| 1321 | (unless (memq last-command '(next-history-element | ||
| 1322 | previous-history-element)) | ||
| 1323 | (let ((prompt-end (minibuffer-prompt-end))) | ||
| 1324 | (set (make-local-variable 'minibuffer-temporary-goal-position) | ||
| 1325 | (cond ((<= (point) prompt-end) prompt-end) | ||
| 1326 | ((eobp) nil) | ||
| 1327 | (t (point)))))) | ||
| 1328 | (goto-char (point-max)) | ||
| 1329 | (delete-minibuffer-contents) | ||
| 1330 | (setq minibuffer-history-position narg) | ||
| 1331 | (cond ((= narg -1) | ||
| 1332 | (setq elt minibuffer-default)) | ||
| 1333 | ((= narg 0) | ||
| 1334 | (setq elt (or minibuffer-text-before-history "")) | ||
| 1335 | (setq minibuffer-returned-to-present t) | ||
| 1336 | (setq minibuffer-text-before-history nil)) | ||
| 1337 | (t (setq elt (nth (1- minibuffer-history-position) | ||
| 1338 | (symbol-value minibuffer-history-variable))))) | ||
| 1339 | (insert | ||
| 1340 | (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth)) | ||
| 1341 | (not minibuffer-returned-to-present)) | ||
| 1342 | (let ((print-level nil)) | ||
| 1343 | (prin1-to-string elt)) | ||
| 1344 | elt)) | ||
| 1345 | (goto-char (or minibuffer-temporary-goal-position (point-max)))))) | ||
| 1346 | 1351 | ||
| 1347 | (defun previous-history-element (n) | 1352 | (defun previous-history-element (n) |
| 1348 | "Puts previous element of the minibuffer history in the minibuffer. | 1353 | "Puts previous element of the minibuffer history in the minibuffer. |
| 1349 | With argument N, it uses the Nth previous element." | 1354 | With argument N, it uses the Nth previous element." |
| 1350 | (interactive "p") | 1355 | (interactive "p") |
| 1351 | (next-history-element (- n))) | 1356 | (or (zerop n) |
| 1357 | (goto-history-element (+ minibuffer-history-position n)))) | ||
| 1352 | 1358 | ||
| 1353 | (defun next-complete-history-element (n) | 1359 | (defun next-complete-history-element (n) |
| 1354 | "Get next history element which completes the minibuffer before the point. | 1360 | "Get next history element which completes the minibuffer before the point. |
| @@ -1381,6 +1387,137 @@ Return 0 if current buffer is not a minibuffer." | |||
| 1381 | ;; the buffer; this should be 0 for normal buffers. | 1387 | ;; the buffer; this should be 0 for normal buffers. |
| 1382 | (1- (minibuffer-prompt-end))) | 1388 | (1- (minibuffer-prompt-end))) |
| 1383 | 1389 | ||
| 1390 | ;; isearch minibuffer history | ||
| 1391 | (add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup) | ||
| 1392 | |||
| 1393 | (defvar minibuffer-history-isearch-message-overlay) | ||
| 1394 | (make-variable-buffer-local 'minibuffer-history-isearch-message-overlay) | ||
| 1395 | |||
| 1396 | (defun minibuffer-history-isearch-setup () | ||
| 1397 | "Set up a minibuffer for using isearch to search the minibuffer history. | ||
| 1398 | Intended to be added to `minibuffer-setup-hook'." | ||
| 1399 | (set (make-local-variable 'isearch-search-fun-function) | ||
| 1400 | 'minibuffer-history-isearch-search) | ||
| 1401 | (set (make-local-variable 'isearch-message-function) | ||
| 1402 | 'minibuffer-history-isearch-message) | ||
| 1403 | (set (make-local-variable 'isearch-wrap-function) | ||
| 1404 | 'minibuffer-history-isearch-wrap) | ||
| 1405 | (set (make-local-variable 'isearch-push-state-function) | ||
| 1406 | 'minibuffer-history-isearch-push-state) | ||
| 1407 | (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t)) | ||
| 1408 | |||
| 1409 | (defun minibuffer-history-isearch-end () | ||
| 1410 | "Clean up the minibuffer after terminating isearch in the minibuffer." | ||
| 1411 | (if minibuffer-history-isearch-message-overlay | ||
| 1412 | (delete-overlay minibuffer-history-isearch-message-overlay))) | ||
| 1413 | |||
| 1414 | (defun minibuffer-history-isearch-search () | ||
| 1415 | "Return the proper search function, for isearch in minibuffer history." | ||
| 1416 | (cond | ||
| 1417 | (isearch-word | ||
| 1418 | (if isearch-forward 'word-search-forward 'word-search-backward)) | ||
| 1419 | (t | ||
| 1420 | (lambda (string bound noerror) | ||
| 1421 | (let ((search-fun | ||
| 1422 | ;; Use standard functions to search within minibuffer text | ||
| 1423 | (cond | ||
| 1424 | (isearch-regexp | ||
| 1425 | (if isearch-forward 're-search-forward 're-search-backward)) | ||
| 1426 | (t | ||
| 1427 | (if isearch-forward 'search-forward 'search-backward)))) | ||
| 1428 | found) | ||
| 1429 | ;; Avoid lazy-highlighting matches in the minibuffer prompt when | ||
| 1430 | ;; searching forward. Lazy-highlight calls this lambda with the | ||
| 1431 | ;; bound arg, so skip the minibuffer prompt. | ||
| 1432 | (if (and bound isearch-forward (< (point) (minibuffer-prompt-end))) | ||
| 1433 | (goto-char (minibuffer-prompt-end))) | ||
| 1434 | (or | ||
| 1435 | ;; 1. First try searching in the initial minibuffer text | ||
| 1436 | (funcall search-fun string | ||
| 1437 | (if isearch-forward bound (minibuffer-prompt-end)) | ||
| 1438 | noerror) | ||
| 1439 | ;; 2. If the above search fails, start putting next/prev history | ||
| 1440 | ;; elements in the minibuffer successively, and search the string | ||
| 1441 | ;; in them. Do this only when bound is nil (i.e. not while | ||
| 1442 | ;; lazy-highlighting search strings in the current minibuffer text). | ||
| 1443 | (unless bound | ||
| 1444 | (condition-case nil | ||
| 1445 | (progn | ||
| 1446 | (while (not found) | ||
| 1447 | (cond (isearch-forward | ||
| 1448 | (next-history-element 1) | ||
| 1449 | (goto-char (minibuffer-prompt-end))) | ||
| 1450 | (t | ||
| 1451 | (previous-history-element 1) | ||
| 1452 | (goto-char (point-max)))) | ||
| 1453 | (setq isearch-barrier (point) isearch-opoint (point)) | ||
| 1454 | ;; After putting the next/prev history element, search | ||
| 1455 | ;; the string in them again, until next-history-element | ||
| 1456 | ;; or previous-history-element raises an error at the | ||
| 1457 | ;; beginning/end of history. | ||
| 1458 | (setq found (funcall search-fun string | ||
| 1459 | (unless isearch-forward | ||
| 1460 | ;; For backward search, don't search | ||
| 1461 | ;; in the minibuffer prompt | ||
| 1462 | (minibuffer-prompt-end)) | ||
| 1463 | noerror))) | ||
| 1464 | ;; Return point of the new search result | ||
| 1465 | (point)) | ||
| 1466 | ;; Return nil when next(prev)-history-element fails | ||
| 1467 | (error nil))))))))) | ||
| 1468 | |||
| 1469 | (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis) | ||
| 1470 | "Display the minibuffer history search prompt. | ||
| 1471 | If there are no search errors, this function displays an overlay with | ||
| 1472 | the isearch prompt which replaces the original minibuffer prompt. | ||
| 1473 | Otherwise, it displays the standard isearch message returned from | ||
| 1474 | `isearch-message'." | ||
| 1475 | (if (not (and (minibufferp) isearch-success (not isearch-error))) | ||
| 1476 | ;; Use standard function `isearch-message' when not in the minibuffer, | ||
| 1477 | ;; or search fails, or has an error (like incomplete regexp). | ||
| 1478 | ;; This function overwrites minibuffer text with isearch message, | ||
| 1479 | ;; so it's possible to see what is wrong in the search string. | ||
| 1480 | (isearch-message c-q-hack ellipsis) | ||
| 1481 | ;; Otherwise, put the overlay with the standard isearch prompt over | ||
| 1482 | ;; the initial minibuffer prompt. | ||
| 1483 | (if (overlayp minibuffer-history-isearch-message-overlay) | ||
| 1484 | (move-overlay minibuffer-history-isearch-message-overlay | ||
| 1485 | (point-min) (minibuffer-prompt-end)) | ||
| 1486 | (setq minibuffer-history-isearch-message-overlay | ||
| 1487 | (make-overlay (point-min) (minibuffer-prompt-end))) | ||
| 1488 | (overlay-put minibuffer-history-isearch-message-overlay 'evaporate t)) | ||
| 1489 | (overlay-put minibuffer-history-isearch-message-overlay | ||
| 1490 | 'display (isearch-message-prefix c-q-hack ellipsis)) | ||
| 1491 | ;; And clear any previous isearch message. | ||
| 1492 | (message ""))) | ||
| 1493 | |||
| 1494 | (defun minibuffer-history-isearch-wrap () | ||
| 1495 | "Wrap the minibuffer history search when search is failed. | ||
| 1496 | Move point to the first history element for a forward search, | ||
| 1497 | or to the last history element for a backward search." | ||
| 1498 | (unless isearch-word | ||
| 1499 | ;; When `minibuffer-history-isearch-search' fails on reaching the | ||
| 1500 | ;; beginning/end of the history, wrap the search to the first/last | ||
| 1501 | ;; minibuffer history element. | ||
| 1502 | (if isearch-forward | ||
| 1503 | (goto-history-element (length (symbol-value minibuffer-history-variable))) | ||
| 1504 | (goto-history-element 0)) | ||
| 1505 | (setq isearch-success t)) | ||
| 1506 | (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max)))) | ||
| 1507 | |||
| 1508 | (defun minibuffer-history-isearch-push-state () | ||
| 1509 | "Save a function restoring the state of minibuffer history search. | ||
| 1510 | Save `minibuffer-history-position' to the additional state parameter | ||
| 1511 | in the search status stack." | ||
| 1512 | `(lambda (cmd) | ||
| 1513 | (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position))) | ||
| 1514 | |||
| 1515 | (defun minibuffer-history-isearch-pop-state (cmd hist-pos) | ||
| 1516 | "Restore the minibuffer history search state. | ||
| 1517 | Go to the history element by the absolute history position `hist-pos'." | ||
| 1518 | (goto-history-element hist-pos)) | ||
| 1519 | |||
| 1520 | |||
| 1384 | ;Put this on C-x u, so we can force that rather than C-_ into startup msg | 1521 | ;Put this on C-x u, so we can force that rather than C-_ into startup msg |
| 1385 | (defalias 'advertised-undo 'undo) | 1522 | (defalias 'advertised-undo 'undo) |
| 1386 | 1523 | ||