diff options
| author | Eli Zaretskii | 2003-11-01 17:00:02 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2003-11-01 17:00:02 +0000 |
| commit | 1e491f1bb8aee4406b7cbb2869a24f7508e650bf (patch) | |
| tree | 86c6944ecc821c4cf8f8664e8c0de48bbd3cbaae | |
| parent | 867bae0b00ac9aa22648a9d82d49bc40e2ecc83b (diff) | |
| download | emacs-1e491f1bb8aee4406b7cbb2869a24f7508e650bf.tar.gz emacs-1e491f1bb8aee4406b7cbb2869a24f7508e650bf.zip | |
(isearch-unread-key-sequence): New function, extracted from
isearch-other-meta-char.
(top level): (put 'foo 'isearch-scroll) on all Emacs's
"scrollable" standard functions.
(isearch-allow-scroll): New customizable variable.
(isearch-string-out-of-window, isearch-back-into-window)
(isearch-reread-key-sequence-naturally)
(isearch-lookup-scroll-key): New functions.
(isearch-other-meta-char): Doc string and functionality enhanced.
Now accepts a prefix argument.
(isearch-lazy-highlight-window-end): New variable.
(isearch-lazy-highlight-new-loop): Pay attention to the window's
end (thru isearch-lazy-highlight-window-end), not only its start.
| -rw-r--r-- | lisp/isearch.el | 222 |
1 files changed, 195 insertions, 27 deletions
diff --git a/lisp/isearch.el b/lisp/isearch.el index 01285aedf05..d84510eb7a2 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el | |||
| @@ -242,7 +242,8 @@ Default value, nil, means edit the string instead." | |||
| 242 | (while l | 242 | (while l |
| 243 | (set-char-table-default table (car l) 'isearch-printing-char) | 243 | (set-char-table-default table (car l) 'isearch-printing-char) |
| 244 | (setq l (cdr l)))) | 244 | (setq l (cdr l)))) |
| 245 | ;; Make function keys, etc, exit the search. | 245 | ;; Make function keys, etc, which aren't bound to a scrolling-function |
| 246 | ;; exit the search. | ||
| 246 | (define-key map [t] 'isearch-other-control-char) | 247 | (define-key map [t] 'isearch-other-control-char) |
| 247 | ;; Control chars, by default, end isearch mode transparently. | 248 | ;; Control chars, by default, end isearch mode transparently. |
| 248 | ;; We need these explicit definitions because, in a dense keymap, | 249 | ;; We need these explicit definitions because, in a dense keymap, |
| @@ -1224,18 +1225,176 @@ might return the position of the end of the line." | |||
| 1224 | (goto-char isearch-barrier))) | 1225 | (goto-char isearch-barrier))) |
| 1225 | (isearch-process-search-char last-command-char)) | 1226 | (isearch-process-search-char last-command-char)) |
| 1226 | 1227 | ||
| 1228 | (defun isearch-unread-key-sequence (keylist) | ||
| 1229 | "Unread the given key-sequence KEYLIST. | ||
| 1230 | Scroll-bar or mode-line events are processed appropriately." | ||
| 1231 | (cancel-kbd-macro-events) | ||
| 1232 | (apply 'isearch-unread keylist) | ||
| 1233 | ;; If the event was a scroll-bar or mode-line click, the event will have | ||
| 1234 | ;; been prefixed by a symbol such as vertical-scroll-bar. We must remove | ||
| 1235 | ;; it here, because this symbol will be attached to the event again next | ||
| 1236 | ;; time it gets read by read-key-sequence. | ||
| 1237 | ;; | ||
| 1238 | ;; (Old comment from isearch-other-meta-char: "Note that we don't have to | ||
| 1239 | ;; modify the event anymore in 21 because read_key_sequence no longer | ||
| 1240 | ;; modifies events to produce fake prefix keys.") | ||
| 1241 | (if (and (> (length keylist) 1) | ||
| 1242 | (symbolp (car keylist)) | ||
| 1243 | (listp (cadr keylist)) | ||
| 1244 | (not (numberp (posn-point | ||
| 1245 | (event-start (cadr keylist) ))))) | ||
| 1246 | (pop unread-command-events))) | ||
| 1247 | |||
| 1248 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 1249 | ;; scrolling within Isearch mode. Alan Mackenzie (acm@muc.de), 2003/2/24 | ||
| 1250 | ;; | ||
| 1251 | ;; The idea here is that certain vertical scrolling commands (like C-l | ||
| 1252 | ;; `recenter') should be usable WITHIN Isearch mode. For a command to be | ||
| 1253 | ;; suitable, it must NOT alter the buffer, swap to another buffer or frame, | ||
| 1254 | ;; tamper with isearch's state, or move point. It is unacceptable for the | ||
| 1255 | ;; search string to be scrolled out of the current window. If a command | ||
| 1256 | ;; attempts this, we scroll the text back again. | ||
| 1257 | ;; | ||
| 1258 | ;; We implement this feature with a property called `isearch-scroll'. | ||
| 1259 | ;; If a command's symbol has the value t for this property it is a | ||
| 1260 | ;; scrolling command. The feature needs to be enabled by setting the | ||
| 1261 | ;; customizable variable `isearch-allow-scroll' to a non-nil value. | ||
| 1262 | ;; | ||
| 1263 | ;; The universal argument commands (e.g. C-u) in simple.el are marked | ||
| 1264 | ;; as scrolling commands, and isearch.el has been amended to allow | ||
| 1265 | ;; prefix arguments to be passed through to scrolling commands. Thus | ||
| 1266 | ;; M-0 C-l will scroll point to the top of the window. | ||
| 1267 | ;; | ||
| 1268 | ;; Horizontal scrolling commands are currently not catered for. | ||
| 1269 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 1270 | |||
| 1271 | ;; Set the isearch-scroll property on some standard functions: | ||
| 1272 | ;; Scroll-bar functions: | ||
| 1273 | (if (fboundp 'scroll-bar-toolkit-scroll) | ||
| 1274 | (put 'scroll-bar-toolkit-scroll 'isearch-scroll t)) | ||
| 1275 | (if (fboundp 'mac-handle-scroll-bar-event) | ||
| 1276 | (put 'mac-handle-scroll-bar-event 'isearch-scroll t)) | ||
| 1277 | (if (fboundp 'w32-handle-scroll-bar-event) | ||
| 1278 | (put 'w32-handle-scroll-bar-event 'isearch-scroll t)) | ||
| 1279 | |||
| 1280 | ;; Commands which scroll the window: | ||
| 1281 | (put 'recenter 'isearch-scroll t) | ||
| 1282 | (put 'reposition-window 'isearch-scroll t) | ||
| 1283 | (put 'scroll-up 'isearch-scroll t) | ||
| 1284 | (put 'scroll-down 'isearch-scroll t) | ||
| 1285 | |||
| 1286 | ;; Commands which act on the other window | ||
| 1287 | (put 'list-buffers 'isearch-scroll t) | ||
| 1288 | (put 'scroll-other-window 'isearch-scroll t) | ||
| 1289 | (put 'scroll-other-window-down 'isearch-scroll t) | ||
| 1290 | (put 'beginning-of-buffer-other-window 'isearch-scroll t) | ||
| 1291 | (put 'end-of-buffer-other-window 'isearch-scroll t) | ||
| 1292 | |||
| 1293 | ;; Commands which change the window layout | ||
| 1294 | (put 'delete-other-windows 'isearch-scroll t) | ||
| 1295 | (put 'balance-windows 'isearch-scroll t) | ||
| 1296 | (put 'split-window-vertically 'isearch-scroll t) | ||
| 1297 | (put 'enlarge-window 'isearch-scroll t) | ||
| 1298 | |||
| 1299 | ;; Universal argument commands | ||
| 1300 | (put 'universal-argument 'isearch-scroll t) | ||
| 1301 | (put 'negative-argument 'isearch-scroll t) | ||
| 1302 | (put 'digit-argument 'isearch-scroll t) | ||
| 1303 | |||
| 1304 | (defcustom isearch-allow-scroll nil | ||
| 1305 | "If non-nil, scrolling commands are allowed during incremental search." | ||
| 1306 | :type 'boolean | ||
| 1307 | :group 'isearch) | ||
| 1308 | |||
| 1309 | (defun isearch-string-out-of-window (isearch-point) | ||
| 1310 | "Test whether the search string is currently outside of the window. | ||
| 1311 | Return nil if it's completely visible, or if point is visible, | ||
| 1312 | together with as much of the search string as will fit; the symbol | ||
| 1313 | `above' if we need to scroll the text downwards; the symbol `below', | ||
| 1314 | if upwards." | ||
| 1315 | (let ((w-start (window-start)) | ||
| 1316 | (w-end (window-end nil t)) | ||
| 1317 | (w-L1 (save-excursion (move-to-window-line 1) (point))) | ||
| 1318 | (w-L-1 (save-excursion (move-to-window-line -1) (point))) | ||
| 1319 | start end) ; start and end of search string in buffer | ||
| 1320 | (if isearch-forward | ||
| 1321 | (setq end isearch-point start (or isearch-other-end isearch-point)) | ||
| 1322 | (setq start isearch-point end (or isearch-other-end isearch-point))) | ||
| 1323 | (cond ((or (and (>= start w-start) (<= end w-end)) | ||
| 1324 | (if isearch-forward | ||
| 1325 | (and (>= isearch-point w-L-1) (< isearch-point w-end)) ; point on Line -1 | ||
| 1326 | (and (>= isearch-point w-start) (< isearch-point w-L1)))) ; point on Line 0 | ||
| 1327 | nil) | ||
| 1328 | ((and (< start w-start) | ||
| 1329 | (< isearch-point w-L-1)) | ||
| 1330 | 'above) | ||
| 1331 | (t 'below)))) | ||
| 1332 | |||
| 1333 | (defun isearch-back-into-window (above isearch-point) | ||
| 1334 | "Scroll the window to bring the search string back into view. | ||
| 1335 | Restore point to ISEARCH-POINT in the process. ABOVE is t when the | ||
| 1336 | search string is above the top of the window, nil when it is beneath | ||
| 1337 | the bottom." | ||
| 1338 | (let (start end) | ||
| 1339 | (if isearch-forward | ||
| 1340 | (setq end isearch-point start (or isearch-other-end isearch-point)) | ||
| 1341 | (setq start isearch-point end (or isearch-other-end isearch-point))) | ||
| 1342 | (if above | ||
| 1343 | (progn | ||
| 1344 | (goto-char start) | ||
| 1345 | (recenter 0) | ||
| 1346 | (when (>= isearch-point (window-end nil t)) | ||
| 1347 | (goto-char isearch-point) | ||
| 1348 | (recenter -1))) | ||
| 1349 | (goto-char end) | ||
| 1350 | (recenter -1) | ||
| 1351 | (when (< isearch-point (window-start)) | ||
| 1352 | (goto-char isearch-point) | ||
| 1353 | (recenter 0)))) | ||
| 1354 | (goto-char isearch-point)) | ||
| 1355 | |||
| 1356 | (defun isearch-reread-key-sequence-naturally (keylist) | ||
| 1357 | "Reread key sequence KEYLIST with Isearch mode's keymap deactivated. | ||
| 1358 | Return the key sequence as a string/vector." | ||
| 1359 | (isearch-unread-key-sequence keylist) | ||
| 1360 | (let (overriding-terminal-local-map) | ||
| 1361 | (read-key-sequence nil))) ; This will go through function-key-map, if nec. | ||
| 1362 | |||
| 1363 | (defun isearch-lookup-scroll-key (key-seq) | ||
| 1364 | "If KEY-SEQ is bound to a scrolling command, return it as a symbol. | ||
| 1365 | Otherwise return nil." | ||
| 1366 | (let* ((overriding-terminal-local-map nil) | ||
| 1367 | (binding (key-binding key-seq))) | ||
| 1368 | (and binding (symbolp binding) (commandp binding) | ||
| 1369 | (eq (get binding 'isearch-scroll) t) | ||
| 1370 | binding))) | ||
| 1227 | 1371 | ||
| 1228 | (defalias 'isearch-other-control-char 'isearch-other-meta-char) | 1372 | (defalias 'isearch-other-control-char 'isearch-other-meta-char) |
| 1229 | 1373 | ||
| 1230 | (defun isearch-other-meta-char () | 1374 | (defun isearch-other-meta-char (&optional arg) |
| 1231 | "Exit the search normally and reread this key sequence. | 1375 | "Process a miscellaneous key sequence in Isearch mode. |
| 1232 | But only if `search-exit-option' is non-nil, the default. | 1376 | |
| 1233 | If it is the symbol `edit', the search string is edited in the minibuffer | 1377 | Try to convert the current key-sequence to something usable in Isearch |
| 1234 | and the meta character is unread so that it applies to editing the string." | 1378 | mode, either by converting it with `function-key-map', downcasing a |
| 1235 | (interactive) | 1379 | key with C-<upper case>, or finding a \"scrolling command\" bound to |
| 1236 | (let* ((key (this-command-keys)) | 1380 | it. \(In the last case, we may have to read more events.) If so, |
| 1381 | either unread the converted sequence or execute the command. | ||
| 1382 | |||
| 1383 | Otherwise, if `search-exit-option' is non-nil (the default) unread the | ||
| 1384 | key-sequence and exit the search normally. If it is the symbol | ||
| 1385 | `edit', the search string is edited in the minibuffer and the meta | ||
| 1386 | character is unread so that it applies to editing the string. | ||
| 1387 | |||
| 1388 | ARG is the prefix argument. It will be transmitted through to the | ||
| 1389 | scrolling command or to the command whose key-sequence exits | ||
| 1390 | Isearch mode." | ||
| 1391 | (interactive "P") | ||
| 1392 | (let* ((key (if current-prefix-arg ; not nec the same as ARG | ||
| 1393 | (substring (this-command-keys) universal-argument-num-events) | ||
| 1394 | (this-command-keys))) | ||
| 1237 | (main-event (aref key 0)) | 1395 | (main-event (aref key 0)) |
| 1238 | (keylist (listify-key-sequence key))) | 1396 | (keylist (listify-key-sequence key)) |
| 1397 | scroll-command isearch-point) | ||
| 1239 | (cond ((and (= (length key) 1) | 1398 | (cond ((and (= (length key) 1) |
| 1240 | (let ((lookup (lookup-key function-key-map key))) | 1399 | (let ((lookup (lookup-key function-key-map key))) |
| 1241 | (not (or (null lookup) (integerp lookup) | 1400 | (not (or (null lookup) (integerp lookup) |
| @@ -1287,23 +1446,27 @@ and the meta character is unread so that it applies to editing the string." | |||
| 1287 | ((eq search-exit-option 'edit) | 1446 | ((eq search-exit-option 'edit) |
| 1288 | (apply 'isearch-unread keylist) | 1447 | (apply 'isearch-unread keylist) |
| 1289 | (isearch-edit-string)) | 1448 | (isearch-edit-string)) |
| 1449 | ;; Handle a scrolling function. | ||
| 1450 | ((and isearch-allow-scroll | ||
| 1451 | (progn (setq key (isearch-reread-key-sequence-naturally keylist)) | ||
| 1452 | (setq keylist (listify-key-sequence key)) | ||
| 1453 | (setq main-event (aref key 0)) | ||
| 1454 | (setq scroll-command (isearch-lookup-scroll-key key)))) | ||
| 1455 | ;; From this point onwards, KEY, KEYLIST and MAIN-EVENT hold a | ||
| 1456 | ;; complete key sequence, possibly as modified by function-key-map, | ||
| 1457 | ;; not merely the one or two event fragment which invoked | ||
| 1458 | ;; isearch-other-meta-char in the first place. | ||
| 1459 | (setq isearch-point (point)) | ||
| 1460 | (setq prefix-arg arg) | ||
| 1461 | (command-execute scroll-command) | ||
| 1462 | (let ((ab-bel (isearch-string-out-of-window isearch-point))) | ||
| 1463 | (if ab-bel | ||
| 1464 | (isearch-back-into-window (eq ab-bel 'above) isearch-point))) | ||
| 1465 | (isearch-update)) | ||
| 1290 | (search-exit-option | 1466 | (search-exit-option |
| 1291 | (let (window) | 1467 | (let (window) |
| 1292 | (cancel-kbd-macro-events) | 1468 | (isearch-unread-key-sequence keylist) |
| 1293 | (apply 'isearch-unread keylist) | 1469 | (setq main-event (car unread-command-events)) |
| 1294 | |||
| 1295 | ;; Properly handle scroll-bar and mode-line clicks for | ||
| 1296 | ;; which a dummy prefix event was generated as (aref key | ||
| 1297 | ;; 0). Note that we don't have to modify the event | ||
| 1298 | ;; anymore in 21 because read_key_sequence no longer modifies | ||
| 1299 | ;; events to produce fake prefix keys. | ||
| 1300 | (when (and (> (length key) 1) | ||
| 1301 | (symbolp (aref key 0)) | ||
| 1302 | (listp (aref key 1)) | ||
| 1303 | (not (numberp (posn-point | ||
| 1304 | (event-start (aref key 1)))))) | ||
| 1305 | (pop unread-command-events) | ||
| 1306 | (setq main-event (car unread-command-events))) | ||
| 1307 | 1470 | ||
| 1308 | ;; If we got a mouse click event, that event contains the | 1471 | ;; If we got a mouse click event, that event contains the |
| 1309 | ;; window clicked on. maybe it was read with the buffer | 1472 | ;; window clicked on. maybe it was read with the buffer |
| @@ -1333,8 +1496,9 @@ and the meta character is unread so that it applies to editing the string." | |||
| 1333 | (isearch-done) | 1496 | (isearch-done) |
| 1334 | (isearch-clean-overlays)) | 1497 | (isearch-clean-overlays)) |
| 1335 | (isearch-done) | 1498 | (isearch-done) |
| 1336 | (isearch-clean-overlays)))) | 1499 | (isearch-clean-overlays) |
| 1337 | (t;; otherwise nil | 1500 | (setq prefix-arg arg)))) |
| 1501 | (t;; otherwise nil | ||
| 1338 | (isearch-process-search-string key key))))) | 1502 | (isearch-process-search-string key key))))) |
| 1339 | 1503 | ||
| 1340 | (defun isearch-quote-char () | 1504 | (defun isearch-quote-char () |
| @@ -1997,6 +2161,7 @@ A value of nil means highlight all matches." | |||
| 1997 | (defvar isearch-lazy-highlight-last-string nil) | 2161 | (defvar isearch-lazy-highlight-last-string nil) |
| 1998 | (defvar isearch-lazy-highlight-window nil) | 2162 | (defvar isearch-lazy-highlight-window nil) |
| 1999 | (defvar isearch-lazy-highlight-window-start nil) | 2163 | (defvar isearch-lazy-highlight-window-start nil) |
| 2164 | (defvar isearch-lazy-highlight-window-end nil) | ||
| 2000 | (defvar isearch-lazy-highlight-case-fold-search nil) | 2165 | (defvar isearch-lazy-highlight-case-fold-search nil) |
| 2001 | (defvar isearch-lazy-highlight-regexp nil) | 2166 | (defvar isearch-lazy-highlight-regexp nil) |
| 2002 | 2167 | ||
| @@ -2031,12 +2196,15 @@ search string to change or the window to scroll)." | |||
| 2031 | (not (eq isearch-lazy-highlight-regexp | 2196 | (not (eq isearch-lazy-highlight-regexp |
| 2032 | isearch-regexp)) | 2197 | isearch-regexp)) |
| 2033 | (not (= (window-start) | 2198 | (not (= (window-start) |
| 2034 | isearch-lazy-highlight-window-start)))) | 2199 | isearch-lazy-highlight-window-start)) |
| 2200 | (not (= (window-end) ; Window may have been split/joined. | ||
| 2201 | isearch-lazy-highlight-window-end)))) | ||
| 2035 | ;; something important did indeed change | 2202 | ;; something important did indeed change |
| 2036 | (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays | 2203 | (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays |
| 2037 | (when (not isearch-invalid-regexp) | 2204 | (when (not isearch-invalid-regexp) |
| 2038 | (setq isearch-lazy-highlight-window (selected-window) | 2205 | (setq isearch-lazy-highlight-window (selected-window) |
| 2039 | isearch-lazy-highlight-window-start (window-start) | 2206 | isearch-lazy-highlight-window-start (window-start) |
| 2207 | isearch-lazy-highlight-window-end (window-end) | ||
| 2040 | isearch-lazy-highlight-start (point) | 2208 | isearch-lazy-highlight-start (point) |
| 2041 | isearch-lazy-highlight-end (point) | 2209 | isearch-lazy-highlight-end (point) |
| 2042 | isearch-lazy-highlight-last-string isearch-string | 2210 | isearch-lazy-highlight-last-string isearch-string |