diff options
| author | Martin Rudalics | 2011-06-11 11:50:37 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2011-06-11 11:50:37 +0200 |
| commit | 9397e56f7424b87f0b52be1235b25a56002661f1 (patch) | |
| tree | 076db90751a94af4790e661a5a9a2d5cbdc2975f /lisp | |
| parent | b50691aaafa255709b1117000ce6fb98d9772695 (diff) | |
| download | emacs-9397e56f7424b87f0b52be1235b25a56002661f1.tar.gz emacs-9397e56f7424b87f0b52be1235b25a56002661f1.zip | |
Move/add window-buffer-related functions to window.el.
* buffer.c: New Lisp objects Qbuffer_list_update_hook and
Qclone_number. Remove external declaration of Qdelete_window.
(Fbuffer_list): Rewrite doc-string. Minor restructuring of
code.
(Fget_buffer_create, Fmake_indirect_buffer, Frename_buffer): Run
Qbuffer_list_update_hook if allowed.
(Fother_buffer): Rewrite doc-string. Major rewrite for new
buffer list implementation.
(other_buffer_safely): New function.
(Fkill_buffer): Replace call to replace_buffer_in_all_windows by
calls to replace_buffer_in_windows and
replace_buffer_in_windows_safely. Run Qbuffer_list_update_hook
if allowed.
(record_buffer): Inhibit quitting and rewrite using quittable
functions. Run Qbuffer_list_update_hook if allowed.
(Frecord_buffer, Funrecord_buffer): New functions.
(switch_to_buffer_1, Fswitch_to_buffer): Remove. Move
switch-to-buffer to window.el.
(bury-buffer): Move to window.el.
(Vbuffer_list_update_hook): New variable.
* lisp.h (other_buffer_safely): Add prototype in buffer.c
section.
* window.h (resize_frame_windows): Move up in code.
(Fwindow_frame): Remove EXFUN.
(replace_buffer_in_all_windows): Remove prototype.
(replace_buffer_in_windows_safely): Add prototype.
* window.c: Declare Qdelete_window static again. Move down
declaration of select_count.
(Fnext_window, Fprevious_window): Rewrite doc-strings.
(Fother_window): Move to window.el.
(window_loop): Remove DELETE_BUFFER_WINDOWS and UNSHOW_BUFFER
cases. Add REPLACE_BUFFER_IN_WINDOWS_SAFELY case.
(Fdelete_windows_on, Freplace_buffer_in_windows): Move to
window.el.
(replace_buffer_in_windows): Implement by calling
Qreplace_buffer_in_windows.
(replace_buffer_in_all_windows): Remove with some functionality
moved into replace_buffer_in_windows_safely.
(replace_buffer_in_windows_safely): New function.
(select_window_norecord, select_frame_norecord): Move in front
of run_window_configuration_change_hook. Remove now obsolete
declarations.
(Fset_window_buffer): Rewrite doc-string. Call
Qrecord_window_buffer.
(keys_of_window): Move binding for other-window to window.el.
* loadup.el (top-level): Load window before files for the sake
of replace-buffer-in-windows.
* files.el (read-buffer-to-switch)
(switch-to-buffer-other-window)
(switch-to-buffer-other-frame, display-buffer-other-frame): Move
to window.el.
* simple.el (get-next-valid-buffer, last-buffer, next-buffer)
(previous-buffer): Move to window.el.
* bindings.el (unbury-buffer): Move to window.el.
* window.el (delete-other-windows-vertically): Move after
definition of delete-other-windows.
(other-window, delete-windows-on, replace-buffer-in-windows):
Move here from window.c.
(record-window-buffer, unrecord-window-buffer)
(set-window-buffer-start-and-point, switch-to-prev-buffer)
(switch-to-next-buffer): New functions.
(get-next-valid-buffer, last-buffer, next-buffer): Move here
from simple.el. Call switch-to-next-buffer.
(previous-buffer): Move here from simple.el. Call
switch-to-prev-buffer.
(bury-buffer): Move here from buffer.c. Switch to previous
buffer when window cannot be deleted.
(unbury-buffer): Move here from bindings.el.
(ctl-x-map): Move binding for other-window from window.c to
here.
(read-buffer-to-switch, switch-to-buffer-other-window)
(switch-to-buffer-other-frame): Move here from files.el.
(normalize-buffer-to-switch-to): New functions.
(switch-to-buffer): Move here from buffer.c. Use
read-buffer-to-switch and normalize-buffer-to-switch-to.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 37 | ||||
| -rw-r--r-- | lisp/bindings.el | 5 | ||||
| -rw-r--r-- | lisp/files.el | 94 | ||||
| -rw-r--r-- | lisp/loadup.el | 2 | ||||
| -rw-r--r-- | lisp/simple.el | 54 | ||||
| -rw-r--r-- | lisp/window.el | 768 |
6 files changed, 777 insertions, 183 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1ac216dfbe2..611531330cc 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,42 @@ | |||
| 1 | 2011-06-10 Martin Rudalics <rudalics@gmx.at> | 1 | 2011-06-10 Martin Rudalics <rudalics@gmx.at> |
| 2 | 2 | ||
| 3 | * loadup.el (top-level): Load window before files for the sake | ||
| 4 | of replace-buffer-in-windows. | ||
| 5 | |||
| 6 | * files.el (read-buffer-to-switch) | ||
| 7 | (switch-to-buffer-other-window) | ||
| 8 | (switch-to-buffer-other-frame, display-buffer-other-frame): Move | ||
| 9 | to window.el. | ||
| 10 | |||
| 11 | * simple.el (get-next-valid-buffer, last-buffer, next-buffer) | ||
| 12 | (previous-buffer): Move to window.el. | ||
| 13 | |||
| 14 | * bindings.el (unbury-buffer): Move to window.el. | ||
| 15 | |||
| 16 | * window.el (delete-other-windows-vertically): Move after | ||
| 17 | definition of delete-other-windows. | ||
| 18 | (other-window, delete-windows-on, replace-buffer-in-windows): | ||
| 19 | Move here from window.c. | ||
| 20 | (record-window-buffer, unrecord-window-buffer) | ||
| 21 | (set-window-buffer-start-and-point, switch-to-prev-buffer) | ||
| 22 | (switch-to-next-buffer): New functions. | ||
| 23 | (get-next-valid-buffer, last-buffer, next-buffer): Move here | ||
| 24 | from simple.el. Call switch-to-next-buffer. | ||
| 25 | (previous-buffer): Move here from simple.el. Call | ||
| 26 | switch-to-prev-buffer. | ||
| 27 | (bury-buffer): Move here from buffer.c. Switch to previous | ||
| 28 | buffer when window cannot be deleted. | ||
| 29 | (unbury-buffer): Move here from bindings.el. | ||
| 30 | (ctl-x-map): Move binding for other-window from window.c to | ||
| 31 | here. | ||
| 32 | (read-buffer-to-switch, switch-to-buffer-other-window) | ||
| 33 | (switch-to-buffer-other-frame): Move here from files.el. | ||
| 34 | (normalize-buffer-to-switch-to): New functions. | ||
| 35 | (switch-to-buffer): Move here from buffer.c. Use | ||
| 36 | read-buffer-to-switch and normalize-buffer-to-switch-to. | ||
| 37 | |||
| 38 | 2011-06-10 Martin Rudalics <rudalics@gmx.at> | ||
| 39 | |||
| 3 | * window.el (window-min-height, window-min-width): Move here | 40 | * window.el (window-min-height, window-min-width): Move here |
| 4 | from window.c. Add defcustoms and rewrite doc-strings. | 41 | from window.c. Add defcustoms and rewrite doc-strings. |
| 5 | (resize-mini-window, resize-window): New functions. | 42 | (resize-mini-window, resize-window): New functions. |
diff --git a/lisp/bindings.el b/lisp/bindings.el index ffc797966b8..a7b729a1ba3 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el | |||
| @@ -454,11 +454,6 @@ Major modes that edit things other than ordinary files may change this | |||
| 454 | (put 'mode-line-buffer-identification 'risky-local-variable t) | 454 | (put 'mode-line-buffer-identification 'risky-local-variable t) |
| 455 | (make-variable-buffer-local 'mode-line-buffer-identification) | 455 | (make-variable-buffer-local 'mode-line-buffer-identification) |
| 456 | 456 | ||
| 457 | (defun unbury-buffer () "\ | ||
| 458 | Switch to the last buffer in the buffer list." | ||
| 459 | (interactive) | ||
| 460 | (switch-to-buffer (last-buffer))) | ||
| 461 | |||
| 462 | (defun mode-line-unbury-buffer (event) "\ | 457 | (defun mode-line-unbury-buffer (event) "\ |
| 463 | Call `unbury-buffer' in this window." | 458 | Call `unbury-buffer' in this window." |
| 464 | (interactive "e") | 459 | (interactive "e") |
diff --git a/lisp/files.el b/lisp/files.el index 317153dc9bf..aafc6f92906 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -1288,100 +1288,6 @@ return value, which may be passed as the REQUIRE-MATCH arg to | |||
| 1288 | 'confirm) | 1288 | 'confirm) |
| 1289 | (t nil))) | 1289 | (t nil))) |
| 1290 | 1290 | ||
| 1291 | (defun read-buffer-to-switch (prompt) | ||
| 1292 | "Read the name of a buffer to switch to and return as a string. | ||
| 1293 | It is intended for `switch-to-buffer' family of commands since they | ||
| 1294 | need to omit the name of current buffer from the list of completions | ||
| 1295 | and default values." | ||
| 1296 | (let ((rbts-completion-table (internal-complete-buffer-except))) | ||
| 1297 | (minibuffer-with-setup-hook | ||
| 1298 | (lambda () | ||
| 1299 | (setq minibuffer-completion-table rbts-completion-table) | ||
| 1300 | ;; Since rbts-completion-table is built dynamically, we | ||
| 1301 | ;; can't just add it to the default value of | ||
| 1302 | ;; icomplete-with-completion-tables, so we add it | ||
| 1303 | ;; here manually. | ||
| 1304 | (if (and (boundp 'icomplete-with-completion-tables) | ||
| 1305 | (listp icomplete-with-completion-tables)) | ||
| 1306 | (set (make-local-variable 'icomplete-with-completion-tables) | ||
| 1307 | (cons rbts-completion-table | ||
| 1308 | icomplete-with-completion-tables)))) | ||
| 1309 | (read-buffer prompt (other-buffer (current-buffer)) | ||
| 1310 | (confirm-nonexistent-file-or-buffer))))) | ||
| 1311 | |||
| 1312 | (defun switch-to-buffer-other-window (buffer-or-name &optional norecord) | ||
| 1313 | "Select the buffer specified by BUFFER-OR-NAME in another window. | ||
| 1314 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | ||
| 1315 | nil. Return the buffer switched to. | ||
| 1316 | |||
| 1317 | If called interactively, prompt for the buffer name using the | ||
| 1318 | minibuffer. The variable `confirm-nonexistent-file-or-buffer' | ||
| 1319 | determines whether to request confirmation before creating a new | ||
| 1320 | buffer. | ||
| 1321 | |||
| 1322 | If BUFFER-OR-NAME is a string and does not identify an existing | ||
| 1323 | buffer, create a new buffer with that name. If BUFFER-OR-NAME is | ||
| 1324 | nil, switch to the buffer returned by `other-buffer'. | ||
| 1325 | |||
| 1326 | Optional second argument NORECORD non-nil means do not put this | ||
| 1327 | buffer at the front of the list of recently selected ones. | ||
| 1328 | |||
| 1329 | This uses the function `display-buffer' as a subroutine; see its | ||
| 1330 | documentation for additional customization information." | ||
| 1331 | (interactive | ||
| 1332 | (list (read-buffer-to-switch "Switch to buffer in other window: "))) | ||
| 1333 | (let ((pop-up-windows t) | ||
| 1334 | same-window-buffer-names same-window-regexps) | ||
| 1335 | (pop-to-buffer buffer-or-name t norecord))) | ||
| 1336 | |||
| 1337 | (defun switch-to-buffer-other-frame (buffer-or-name &optional norecord) | ||
| 1338 | "Switch to buffer BUFFER-OR-NAME in another frame. | ||
| 1339 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | ||
| 1340 | nil. Return the buffer switched to. | ||
| 1341 | |||
| 1342 | If called interactively, prompt for the buffer name using the | ||
| 1343 | minibuffer. The variable `confirm-nonexistent-file-or-buffer' | ||
| 1344 | determines whether to request confirmation before creating a new | ||
| 1345 | buffer. | ||
| 1346 | |||
| 1347 | If BUFFER-OR-NAME is a string and does not identify an existing | ||
| 1348 | buffer, create a new buffer with that name. If BUFFER-OR-NAME is | ||
| 1349 | nil, switch to the buffer returned by `other-buffer'. | ||
| 1350 | |||
| 1351 | Optional second arg NORECORD non-nil means do not put this | ||
| 1352 | buffer at the front of the list of recently selected ones. | ||
| 1353 | |||
| 1354 | This uses the function `display-buffer' as a subroutine; see its | ||
| 1355 | documentation for additional customization information." | ||
| 1356 | (interactive | ||
| 1357 | (list (read-buffer-to-switch "Switch to buffer in other frame: "))) | ||
| 1358 | (let ((pop-up-frames t) | ||
| 1359 | same-window-buffer-names same-window-regexps) | ||
| 1360 | (pop-to-buffer buffer-or-name t norecord))) | ||
| 1361 | |||
| 1362 | (defun display-buffer-other-frame (buffer) | ||
| 1363 | "Display buffer BUFFER in another frame. | ||
| 1364 | This uses the function `display-buffer' as a subroutine; see | ||
| 1365 | its documentation for additional customization information." | ||
| 1366 | (interactive "BDisplay buffer in other frame: ") | ||
| 1367 | (let ((pop-up-frames t) | ||
| 1368 | same-window-buffer-names same-window-regexps | ||
| 1369 | ;;(old-window (selected-window)) | ||
| 1370 | new-window) | ||
| 1371 | (setq new-window (display-buffer buffer t)) | ||
| 1372 | ;; This may have been here in order to prevent the new frame from hiding | ||
| 1373 | ;; the old frame. But it does more harm than good. | ||
| 1374 | ;; Maybe we should call `raise-window' on the old-frame instead? --Stef | ||
| 1375 | ;;(lower-frame (window-frame new-window)) | ||
| 1376 | |||
| 1377 | ;; This may have been here in order to make sure the old-frame gets the | ||
| 1378 | ;; focus. But not only can it cause an annoying flicker, with some | ||
| 1379 | ;; window-managers it just makes the window invisible, with no easy | ||
| 1380 | ;; way to recover it. --Stef | ||
| 1381 | ;;(make-frame-invisible (window-frame old-window)) | ||
| 1382 | ;;(make-frame-visible (window-frame old-window)) | ||
| 1383 | )) | ||
| 1384 | |||
| 1385 | (defmacro minibuffer-with-setup-hook (fun &rest body) | 1291 | (defmacro minibuffer-with-setup-hook (fun &rest body) |
| 1386 | "Temporarily add FUN to `minibuffer-setup-hook' while executing BODY. | 1292 | "Temporarily add FUN to `minibuffer-setup-hook' while executing BODY. |
| 1387 | BODY should use the minibuffer at most once. | 1293 | BODY should use the minibuffer at most once. |
diff --git a/lisp/loadup.el b/lisp/loadup.el index 7e80ff97cff..4c677523689 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el | |||
| @@ -95,6 +95,7 @@ | |||
| 95 | (load "env") | 95 | (load "env") |
| 96 | (load "format") | 96 | (load "format") |
| 97 | (load "bindings") | 97 | (load "bindings") |
| 98 | (load "window") ; Needed here for `replace-buffer-in-windows'. | ||
| 98 | (setq load-source-file-function 'load-with-code-conversion) | 99 | (setq load-source-file-function 'load-with-code-conversion) |
| 99 | (load "files") | 100 | (load "files") |
| 100 | 101 | ||
| @@ -156,7 +157,6 @@ | |||
| 156 | (load "language/cham") | 157 | (load "language/cham") |
| 157 | 158 | ||
| 158 | (load "indent") | 159 | (load "indent") |
| 159 | (load "window") | ||
| 160 | (load "frame") | 160 | (load "frame") |
| 161 | (load "term/tty-colors") | 161 | (load "term/tty-colors") |
| 162 | (load "font-core") | 162 | (load "font-core") |
diff --git a/lisp/simple.el b/lisp/simple.el index 76269c9ef9a..b36cf2ec3ec 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -52,60 +52,6 @@ wait this many seconds after Emacs becomes idle before doing an update." | |||
| 52 | (defgroup paren-matching nil | 52 | (defgroup paren-matching nil |
| 53 | "Highlight (un)matching of parens and expressions." | 53 | "Highlight (un)matching of parens and expressions." |
| 54 | :group 'matching) | 54 | :group 'matching) |
| 55 | |||
| 56 | (defun get-next-valid-buffer (list &optional buffer visible-ok frame) | ||
| 57 | "Search LIST for a valid buffer to display in FRAME. | ||
| 58 | Return nil when all buffers in LIST are undesirable for display, | ||
| 59 | otherwise return the first suitable buffer in LIST. | ||
| 60 | |||
| 61 | Buffers not visible in windows are preferred to visible buffers, | ||
| 62 | unless VISIBLE-OK is non-nil. | ||
| 63 | If the optional argument FRAME is nil, it defaults to the selected frame. | ||
| 64 | If BUFFER is non-nil, ignore occurrences of that buffer in LIST." | ||
| 65 | ;; This logic is more or less copied from other-buffer. | ||
| 66 | (setq frame (or frame (selected-frame))) | ||
| 67 | (let ((pred (frame-parameter frame 'buffer-predicate)) | ||
| 68 | found buf) | ||
| 69 | (while (and (not found) list) | ||
| 70 | (setq buf (car list)) | ||
| 71 | (if (and (not (eq buffer buf)) | ||
| 72 | (buffer-live-p buf) | ||
| 73 | (or (null pred) (funcall pred buf)) | ||
| 74 | (not (eq (aref (buffer-name buf) 0) ?\s)) | ||
| 75 | (or visible-ok (null (get-buffer-window buf 'visible)))) | ||
| 76 | (setq found buf) | ||
| 77 | (setq list (cdr list)))) | ||
| 78 | (car list))) | ||
| 79 | |||
| 80 | (defun last-buffer (&optional buffer visible-ok frame) | ||
| 81 | "Return the last buffer in FRAME's buffer list. | ||
| 82 | If BUFFER is the last buffer, return the preceding buffer instead. | ||
| 83 | Buffers not visible in windows are preferred to visible buffers, | ||
| 84 | unless optional argument VISIBLE-OK is non-nil. | ||
| 85 | Optional third argument FRAME nil or omitted means use the | ||
| 86 | selected frame's buffer list. | ||
| 87 | If no such buffer exists, return the buffer `*scratch*', creating | ||
| 88 | it if necessary." | ||
| 89 | (setq frame (or frame (selected-frame))) | ||
| 90 | (or (get-next-valid-buffer (nreverse (buffer-list frame)) | ||
| 91 | buffer visible-ok frame) | ||
| 92 | (get-buffer "*scratch*") | ||
| 93 | (let ((scratch (get-buffer-create "*scratch*"))) | ||
| 94 | (set-buffer-major-mode scratch) | ||
| 95 | scratch))) | ||
| 96 | |||
| 97 | (defun next-buffer () | ||
| 98 | "Switch to the next buffer in cyclic order." | ||
| 99 | (interactive) | ||
| 100 | (let ((buffer (current-buffer))) | ||
| 101 | (switch-to-buffer (other-buffer buffer t)) | ||
| 102 | (bury-buffer buffer))) | ||
| 103 | |||
| 104 | (defun previous-buffer () | ||
| 105 | "Switch to the previous buffer in cyclic order." | ||
| 106 | (interactive) | ||
| 107 | (switch-to-buffer (last-buffer (current-buffer) t))) | ||
| 108 | |||
| 109 | 55 | ||
| 110 | ;;; next-error support framework | 56 | ;;; next-error support framework |
| 111 | 57 | ||
diff --git a/lisp/window.el b/lisp/window.el index a88e56be83c..2811baf706d 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -2078,6 +2078,74 @@ WINDOW can be any window and defaults to the selected window." | |||
| 2078 | "Return non-nil if WINDOW is the root window of its frame." | 2078 | "Return non-nil if WINDOW is the root window of its frame." |
| 2079 | (eq window (frame-root-window window))) | 2079 | (eq window (frame-root-window window))) |
| 2080 | 2080 | ||
| 2081 | (defun other-window (count &optional all-frames) | ||
| 2082 | "Select another window in cyclic ordering of windows. | ||
| 2083 | COUNT specifies the number of windows to skip, starting with the | ||
| 2084 | selected window, before making the selection. If COUNT is | ||
| 2085 | positive, skip COUNT windows forwards. If COUNT is negative, | ||
| 2086 | skip -COUNT windows backwards. COUNT zero means do not skip any | ||
| 2087 | window, so select the selected window. In an interactive call, | ||
| 2088 | COUNT is the numeric prefix argument. Return nil. | ||
| 2089 | |||
| 2090 | If the `other-window' parameter of WINDOW is a function and | ||
| 2091 | `ignore-window-parameters' is nil, call that function with the | ||
| 2092 | arguments COUNT and ALL-FRAMES. | ||
| 2093 | |||
| 2094 | This function does not select a window whose `no-other-window' | ||
| 2095 | window parameter is non-nil. | ||
| 2096 | |||
| 2097 | This function uses `next-window' for finding the window to | ||
| 2098 | select. The argument ALL-FRAMES has the same meaning as in | ||
| 2099 | `next-window', but the MINIBUF argument of `next-window' is | ||
| 2100 | always effectively nil." | ||
| 2101 | (interactive "p") | ||
| 2102 | (let* ((window (selected-window)) | ||
| 2103 | (function (and (not ignore-window-parameters) | ||
| 2104 | (window-parameter window 'other-window))) | ||
| 2105 | old-window old-count) | ||
| 2106 | (if (functionp function) | ||
| 2107 | (funcall function count all-frames) | ||
| 2108 | ;; `next-window' and `previous-window' may return a window we are | ||
| 2109 | ;; not allowed to select. Hence we need an exit strategy in case | ||
| 2110 | ;; all windows are non-selectable. | ||
| 2111 | (catch 'exit | ||
| 2112 | (while (> count 0) | ||
| 2113 | (setq window (next-window window nil all-frames)) | ||
| 2114 | (cond | ||
| 2115 | ((eq window old-window) | ||
| 2116 | (when (= count old-count) | ||
| 2117 | ;; Keep out of infinite loops. When COUNT has not changed | ||
| 2118 | ;; since we last looked at `window' we're probably in one. | ||
| 2119 | (throw 'exit nil))) | ||
| 2120 | ((window-parameter window 'no-other-window) | ||
| 2121 | (unless old-window | ||
| 2122 | ;; The first non-selectable window `next-window' got us: | ||
| 2123 | ;; Remember it and the current value of COUNT. | ||
| 2124 | (setq old-window window) | ||
| 2125 | (setq old-count count))) | ||
| 2126 | (t | ||
| 2127 | (setq count (1- count))))) | ||
| 2128 | (while (< count 0) | ||
| 2129 | (setq window (previous-window window nil all-frames)) | ||
| 2130 | (cond | ||
| 2131 | ((eq window old-window) | ||
| 2132 | (when (= count old-count) | ||
| 2133 | ;; Keep out of infinite loops. When COUNT has not changed | ||
| 2134 | ;; since we last looked at `window' we're probably in one. | ||
| 2135 | (throw 'exit nil))) | ||
| 2136 | ((window-parameter window 'no-other-window) | ||
| 2137 | (unless old-window | ||
| 2138 | ;; The first non-selectable window `previous-window' got | ||
| 2139 | ;; us: Remember it and the current value of COUNT. | ||
| 2140 | (setq old-window window) | ||
| 2141 | (setq old-count count))) | ||
| 2142 | (t | ||
| 2143 | (setq count (1+ count))))) | ||
| 2144 | |||
| 2145 | (select-window window) | ||
| 2146 | ;; Always return nil. | ||
| 2147 | nil)))) | ||
| 2148 | |||
| 2081 | ;; This should probably return non-nil when the selected window is part | 2149 | ;; This should probably return non-nil when the selected window is part |
| 2082 | ;; of an atomic window whose root is the frame's root window. | 2150 | ;; of an atomic window whose root is the frame's root window. |
| 2083 | (defun one-window-p (&optional nomini all-frames) | 2151 | (defun one-window-p (&optional nomini all-frames) |
| @@ -2285,6 +2353,518 @@ window signal an error." | |||
| 2285 | (window-check frame)) | 2353 | (window-check frame)) |
| 2286 | ;; Always return nil. | 2354 | ;; Always return nil. |
| 2287 | nil))) | 2355 | nil))) |
| 2356 | |||
| 2357 | (defun delete-other-windows-vertically (&optional window) | ||
| 2358 | "Delete the windows in the same column with WINDOW, but not WINDOW itself. | ||
| 2359 | This may be a useful alternative binding for \\[delete-other-windows] | ||
| 2360 | if you often split windows horizontally." | ||
| 2361 | (interactive) | ||
| 2362 | (let* ((window (or window (selected-window))) | ||
| 2363 | (edges (window-edges window)) | ||
| 2364 | (w window) delenda) | ||
| 2365 | (while (not (eq (setq w (next-window w 1)) window)) | ||
| 2366 | (let ((e (window-edges w))) | ||
| 2367 | (when (and (= (car e) (car edges)) | ||
| 2368 | (= (caddr e) (caddr edges))) | ||
| 2369 | (push w delenda)))) | ||
| 2370 | (mapc 'delete-window delenda))) | ||
| 2371 | |||
| 2372 | ;;; Windows and buffers. | ||
| 2373 | |||
| 2374 | ;; `prev-buffers' and `next-buffers' are two reserved window slots used | ||
| 2375 | ;; for (1) determining which buffer to show in the window when its | ||
| 2376 | ;; buffer shall be buried or killed and (2) which buffer to show for | ||
| 2377 | ;; `switch-to-prev-buffer' and `switch-to-next-buffer'. | ||
| 2378 | |||
| 2379 | ;; `prev-buffers' consists of <buffer, window-start, window-point> | ||
| 2380 | ;; triples. The entries on this list are ordered by the time their | ||
| 2381 | ;; buffer has been removed from the window, the most recently removed | ||
| 2382 | ;; buffer's entry being first. The window-start and window-point | ||
| 2383 | ;; components are `window-start' and `window-point' at the time the | ||
| 2384 | ;; buffer was removed from the window which implies that the entry must | ||
| 2385 | ;; be added when `set-window-buffer' removes the buffer from the window. | ||
| 2386 | |||
| 2387 | ;; `next-buffers' is the list of buffers that have been replaced | ||
| 2388 | ;; recently by `switch-to-prev-buffer'. These buffers are the least | ||
| 2389 | ;; preferred candidates of `switch-to-prev-buffer' and the preferred | ||
| 2390 | ;; candidates of `switch-to-next-buffer' to switch to. This list is | ||
| 2391 | ;; reset to nil by any action changing the window's buffer with the | ||
| 2392 | ;; exception of `switch-to-prev-buffer' and `switch-to-next-buffer'. | ||
| 2393 | ;; `switch-to-prev-buffer' pushes the buffer it just replaced on it, | ||
| 2394 | ;; `switch-to-next-buffer' pops the last pushed buffer from it. | ||
| 2395 | |||
| 2396 | ;; Both `prev-buffers' and `next-buffers' may reference killed buffers | ||
| 2397 | ;; if such a buffer was killed while the window was hidden within a | ||
| 2398 | ;; window configuration. Such killed buffers get removed whenever | ||
| 2399 | ;; `switch-to-prev-buffer' or `switch-to-next-buffer' encounter them. | ||
| 2400 | |||
| 2401 | ;; The following function is called by `set-window-buffer' _before_ it | ||
| 2402 | ;; replaces the buffer of the argument window with the new buffer. | ||
| 2403 | (defun record-window-buffer (&optional window) | ||
| 2404 | "Record WINDOW's buffer. | ||
| 2405 | WINDOW must be a live window and defaults to the selected one." | ||
| 2406 | (let* ((window (normalize-live-window window)) | ||
| 2407 | (buffer (window-buffer window)) | ||
| 2408 | (entry (assq buffer (window-prev-buffers window)))) | ||
| 2409 | ;; Reset WINDOW's next buffers. If needed, they are resurrected by | ||
| 2410 | ;; `switch-to-prev-buffer' and `switch-to-next-buffer'. | ||
| 2411 | (set-window-next-buffers window nil) | ||
| 2412 | |||
| 2413 | (when entry | ||
| 2414 | ;; Remove all entries for BUFFER from WINDOW's previous buffers. | ||
| 2415 | (set-window-prev-buffers | ||
| 2416 | window (assq-delete-all buffer (window-prev-buffers window)))) | ||
| 2417 | |||
| 2418 | ;; Don't record insignificant buffers. | ||
| 2419 | (unless (eq (aref (buffer-name buffer) 0) ?\s) | ||
| 2420 | ;; Add an entry for buffer to WINDOW's previous buffers. | ||
| 2421 | (with-current-buffer buffer | ||
| 2422 | (let ((start (window-start window)) | ||
| 2423 | (point (window-point window))) | ||
| 2424 | (setq entry | ||
| 2425 | (cons buffer | ||
| 2426 | (if entry | ||
| 2427 | ;; We have an entry, update marker positions. | ||
| 2428 | (list (set-marker (nth 1 entry) start) | ||
| 2429 | (set-marker (nth 2 entry) point)) | ||
| 2430 | ;; Make new markers. | ||
| 2431 | (list (copy-marker start) | ||
| 2432 | (copy-marker point))))) | ||
| 2433 | |||
| 2434 | (set-window-prev-buffers | ||
| 2435 | window (cons entry (window-prev-buffers window)))))))) | ||
| 2436 | |||
| 2437 | (defun unrecord-window-buffer (&optional window buffer) | ||
| 2438 | "Unrecord BUFFER in WINDOW. | ||
| 2439 | WINDOW must be a live window and defaults to the selected one. | ||
| 2440 | BUFFER must be a live buffer and defaults to the buffer of | ||
| 2441 | WINDOW." | ||
| 2442 | (let* ((window (normalize-live-window window)) | ||
| 2443 | (buffer (or buffer (window-buffer window)))) | ||
| 2444 | (set-window-prev-buffers | ||
| 2445 | window (assq-delete-all buffer (window-prev-buffers window))) | ||
| 2446 | (set-window-next-buffers | ||
| 2447 | window (delq buffer (window-next-buffers window))))) | ||
| 2448 | |||
| 2449 | (defun set-window-buffer-start-and-point (window buffer &optional start point) | ||
| 2450 | "Set WINDOW's buffer to BUFFER. | ||
| 2451 | Optional argument START non-nil means set WINDOW's start position | ||
| 2452 | to START. Optional argument POINT non-nil means set WINDOW's | ||
| 2453 | point to POINT. If WINDOW is selected this also sets BUFFER's | ||
| 2454 | `point' to POINT. If WINDOW is selected and the buffer it showed | ||
| 2455 | before was current this also makes BUFFER the current buffer." | ||
| 2456 | (let ((selected (eq window (selected-window))) | ||
| 2457 | (current (eq (window-buffer window) (current-buffer)))) | ||
| 2458 | (set-window-buffer window buffer) | ||
| 2459 | (when (and selected current) | ||
| 2460 | (set-buffer buffer)) | ||
| 2461 | (when start | ||
| 2462 | (set-window-start window start)) | ||
| 2463 | (when point | ||
| 2464 | (if selected | ||
| 2465 | (with-current-buffer buffer | ||
| 2466 | (goto-char point)) | ||
| 2467 | (set-window-point window point))))) | ||
| 2468 | |||
| 2469 | (defun switch-to-prev-buffer (&optional window bury-or-kill) | ||
| 2470 | "In WINDOW switch to previous buffer. | ||
| 2471 | WINDOW must be a live window and defaults to the selected one. | ||
| 2472 | |||
| 2473 | Optional argument BURY-OR-KILL non-nil means the buffer currently | ||
| 2474 | shown in WINDOW is about to be buried or killed and consequently | ||
| 2475 | shall not be switched to in future invocations of this command." | ||
| 2476 | (interactive) | ||
| 2477 | (let* ((window (normalize-live-window window)) | ||
| 2478 | (old-buffer (window-buffer window)) | ||
| 2479 | ;; Save this since it's destroyed by `set-window-buffer'. | ||
| 2480 | (next-buffers (window-next-buffers window)) | ||
| 2481 | entry new-buffer killed-buffers deletable visible) | ||
| 2482 | (cond | ||
| 2483 | ;; When BURY-OR-KILL is non-nil, there's no previous buffer for | ||
| 2484 | ;; this window, and we can delete the window (or the frame) do | ||
| 2485 | ;; that. | ||
| 2486 | ((and bury-or-kill | ||
| 2487 | (or (not (window-prev-buffers window)) | ||
| 2488 | (and (eq (caar (window-prev-buffers window)) old-buffer) | ||
| 2489 | (not (cdr (car (window-prev-buffers window)))))) | ||
| 2490 | (setq deletable (window-deletable-p window))) | ||
| 2491 | (if (eq deletable 'frame) | ||
| 2492 | (delete-frame (window-frame window)) | ||
| 2493 | (delete-window window))) | ||
| 2494 | ((window-dedicated-p window) | ||
| 2495 | (error "Window %s is dedicated to buffer %s" window old-buffer))) | ||
| 2496 | |||
| 2497 | (unless deletable | ||
| 2498 | (catch 'found | ||
| 2499 | ;; Scan WINDOW's previous buffers first, skipping entries of next | ||
| 2500 | ;; buffers. | ||
| 2501 | (dolist (entry (window-prev-buffers window)) | ||
| 2502 | (when (and (setq new-buffer (car entry)) | ||
| 2503 | (or (buffer-live-p new-buffer) | ||
| 2504 | (not (setq killed-buffers | ||
| 2505 | (cons new-buffer killed-buffers)))) | ||
| 2506 | (not (eq new-buffer old-buffer)) | ||
| 2507 | (or bury-or-kill | ||
| 2508 | (not (memq new-buffer next-buffers)))) | ||
| 2509 | (set-window-buffer-start-and-point | ||
| 2510 | window new-buffer (nth 1 entry) (nth 2 entry)) | ||
| 2511 | (throw 'found t))) | ||
| 2512 | ;; Scan reverted buffer list of WINDOW's frame next, skipping | ||
| 2513 | ;; entries of next buffers. Note that when we bury or kill a | ||
| 2514 | ;; buffer we don't reverse the global buffer list to avoid showing | ||
| 2515 | ;; a buried buffer instead. Otherwise, we must reverse the global | ||
| 2516 | ;; buffer list in order to make sure that switching to the | ||
| 2517 | ;; previous/next buffer traverse it in opposite directions. | ||
| 2518 | (dolist (buffer (if bury-or-kill | ||
| 2519 | (buffer-list (window-frame window)) | ||
| 2520 | (nreverse (buffer-list (window-frame window))))) | ||
| 2521 | (when (and (buffer-live-p buffer) | ||
| 2522 | (not (eq buffer old-buffer)) | ||
| 2523 | (not (eq (aref (buffer-name buffer) 0) ?\s)) | ||
| 2524 | (or bury-or-kill (not (memq buffer next-buffers)))) | ||
| 2525 | (if (get-buffer-window buffer) | ||
| 2526 | ;; Try to avoid showing a buffer visible in some other window. | ||
| 2527 | (setq visible buffer) | ||
| 2528 | (setq new-buffer buffer) | ||
| 2529 | (set-window-buffer-start-and-point window new-buffer) | ||
| 2530 | (throw 'found t)))) | ||
| 2531 | (unless bury-or-kill | ||
| 2532 | ;; Scan reverted next buffers last (must not use nreverse | ||
| 2533 | ;; here!). | ||
| 2534 | (dolist (buffer (reverse next-buffers)) | ||
| 2535 | ;; Actually, buffer _must_ be live here since otherwise it | ||
| 2536 | ;; would have been caught in the scan of previous buffers. | ||
| 2537 | (when (and (or (buffer-live-p buffer) | ||
| 2538 | (not (setq killed-buffers | ||
| 2539 | (cons buffer killed-buffers)))) | ||
| 2540 | (not (eq buffer old-buffer)) | ||
| 2541 | (setq entry (assq buffer (window-prev-buffers window)))) | ||
| 2542 | (setq new-buffer buffer) | ||
| 2543 | (set-window-buffer-start-and-point | ||
| 2544 | window new-buffer (nth 1 entry) (nth 2 entry)) | ||
| 2545 | (throw 'found t)))) | ||
| 2546 | |||
| 2547 | ;; Show a buffer visible in another window. | ||
| 2548 | (when visible | ||
| 2549 | (setq new-buffer visible) | ||
| 2550 | (set-window-buffer-start-and-point window new-buffer))) | ||
| 2551 | |||
| 2552 | (if bury-or-kill | ||
| 2553 | ;; Remove `old-buffer' from WINDOW's previous and (restored list | ||
| 2554 | ;; of) next buffers. | ||
| 2555 | (progn | ||
| 2556 | (set-window-prev-buffers | ||
| 2557 | window (assq-delete-all old-buffer (window-prev-buffers window))) | ||
| 2558 | (set-window-next-buffers window (delq old-buffer next-buffers))) | ||
| 2559 | ;; Move `old-buffer' to head of WINDOW's restored list of next | ||
| 2560 | ;; buffers. | ||
| 2561 | (set-window-next-buffers | ||
| 2562 | window (cons old-buffer (delq old-buffer next-buffers))))) | ||
| 2563 | |||
| 2564 | ;; Remove killed buffers from WINDOW's previous and next buffers. | ||
| 2565 | (when killed-buffers | ||
| 2566 | (dolist (buffer killed-buffers) | ||
| 2567 | (set-window-prev-buffers | ||
| 2568 | window (assq-delete-all buffer (window-prev-buffers window))) | ||
| 2569 | (set-window-next-buffers | ||
| 2570 | window (delq buffer (window-next-buffers window))))) | ||
| 2571 | |||
| 2572 | ;; Return new-buffer. | ||
| 2573 | new-buffer)) | ||
| 2574 | |||
| 2575 | (defun switch-to-next-buffer (&optional window) | ||
| 2576 | "In WINDOW switch to next buffer. | ||
| 2577 | WINDOW must be a live window and defaults to the selected one." | ||
| 2578 | (interactive) | ||
| 2579 | (let* ((window (normalize-live-window window)) | ||
| 2580 | (old-buffer (window-buffer window)) | ||
| 2581 | (next-buffers (window-next-buffers window)) | ||
| 2582 | new-buffer entry killed-buffers visible) | ||
| 2583 | (when (window-dedicated-p window) | ||
| 2584 | (error "Window %s is dedicated to buffer %s" window old-buffer)) | ||
| 2585 | |||
| 2586 | (catch 'found | ||
| 2587 | ;; Scan WINDOW's next buffers first. | ||
| 2588 | (dolist (buffer next-buffers) | ||
| 2589 | (when (and (or (buffer-live-p buffer) | ||
| 2590 | (not (setq killed-buffers | ||
| 2591 | (cons buffer killed-buffers)))) | ||
| 2592 | (not (eq buffer old-buffer)) | ||
| 2593 | (setq entry (assq buffer (window-prev-buffers window)))) | ||
| 2594 | (setq new-buffer buffer) | ||
| 2595 | (set-window-buffer-start-and-point | ||
| 2596 | window new-buffer (nth 1 entry) (nth 2 entry)) | ||
| 2597 | (throw 'found t))) | ||
| 2598 | ;; Scan the buffer list of WINDOW's frame next, skipping previous | ||
| 2599 | ;; buffers entries. | ||
| 2600 | (dolist (buffer (buffer-list (window-frame window))) | ||
| 2601 | (when (and (buffer-live-p buffer) (not (eq buffer old-buffer)) | ||
| 2602 | (not (eq (aref (buffer-name buffer) 0) ?\s)) | ||
| 2603 | (not (assq buffer (window-prev-buffers window)))) | ||
| 2604 | (if (get-buffer-window buffer) | ||
| 2605 | ;; Try to avoid showing a buffer visible in some other window. | ||
| 2606 | (setq visible buffer) | ||
| 2607 | (setq new-buffer buffer) | ||
| 2608 | (set-window-buffer-start-and-point window new-buffer) | ||
| 2609 | (throw 'found t)))) | ||
| 2610 | ;; Scan WINDOW's reverted previous buffers last (must not use | ||
| 2611 | ;; nreverse here!) | ||
| 2612 | (dolist (entry (reverse (window-prev-buffers window))) | ||
| 2613 | (when (and (setq new-buffer (car entry)) | ||
| 2614 | (or (buffer-live-p new-buffer) | ||
| 2615 | (not (setq killed-buffers | ||
| 2616 | (cons new-buffer killed-buffers)))) | ||
| 2617 | (not (eq new-buffer old-buffer))) | ||
| 2618 | (set-window-buffer-start-and-point | ||
| 2619 | window new-buffer (nth 1 entry) (nth 2 entry)) | ||
| 2620 | (throw 'found t))) | ||
| 2621 | |||
| 2622 | ;; Show a buffer visible in another window. | ||
| 2623 | (when visible | ||
| 2624 | (setq new-buffer visible) | ||
| 2625 | (set-window-buffer-start-and-point window new-buffer))) | ||
| 2626 | |||
| 2627 | ;; Remove `new-buffer' from and restore WINDOW's next buffers. | ||
| 2628 | (set-window-next-buffers window (delq new-buffer next-buffers)) | ||
| 2629 | |||
| 2630 | ;; Remove killed buffers from WINDOW's previous and next buffers. | ||
| 2631 | (when killed-buffers | ||
| 2632 | (dolist (buffer killed-buffers) | ||
| 2633 | (set-window-prev-buffers | ||
| 2634 | window (assq-delete-all buffer (window-prev-buffers window))) | ||
| 2635 | (set-window-next-buffers | ||
| 2636 | window (delq buffer (window-next-buffers window))))) | ||
| 2637 | |||
| 2638 | ;; Return new-buffer. | ||
| 2639 | new-buffer)) | ||
| 2640 | |||
| 2641 | (defun get-next-valid-buffer (list &optional buffer visible-ok frame) | ||
| 2642 | "Search LIST for a valid buffer to display in FRAME. | ||
| 2643 | Return nil when all buffers in LIST are undesirable for display, | ||
| 2644 | otherwise return the first suitable buffer in LIST. | ||
| 2645 | |||
| 2646 | Buffers not visible in windows are preferred to visible buffers, | ||
| 2647 | unless VISIBLE-OK is non-nil. | ||
| 2648 | If the optional argument FRAME is nil, it defaults to the selected frame. | ||
| 2649 | If BUFFER is non-nil, ignore occurrences of that buffer in LIST." | ||
| 2650 | ;; This logic is more or less copied from other-buffer. | ||
| 2651 | (setq frame (or frame (selected-frame))) | ||
| 2652 | (let ((pred (frame-parameter frame 'buffer-predicate)) | ||
| 2653 | found buf) | ||
| 2654 | (while (and (not found) list) | ||
| 2655 | (setq buf (car list)) | ||
| 2656 | (if (and (not (eq buffer buf)) | ||
| 2657 | (buffer-live-p buf) | ||
| 2658 | (or (null pred) (funcall pred buf)) | ||
| 2659 | (not (eq (aref (buffer-name buf) 0) ?\s)) | ||
| 2660 | (or visible-ok (null (get-buffer-window buf 'visible)))) | ||
| 2661 | (setq found buf) | ||
| 2662 | (setq list (cdr list)))) | ||
| 2663 | (car list))) | ||
| 2664 | |||
| 2665 | (defun last-buffer (&optional buffer visible-ok frame) | ||
| 2666 | "Return the last buffer in FRAME's buffer list. | ||
| 2667 | If BUFFER is the last buffer, return the preceding buffer | ||
| 2668 | instead. Buffers not visible in windows are preferred to visible | ||
| 2669 | buffers, unless optional argument VISIBLE-OK is non-nil. | ||
| 2670 | Optional third argument FRAME nil or omitted means use the | ||
| 2671 | selected frame's buffer list. If no such buffer exists, return | ||
| 2672 | the buffer `*scratch*', creating it if necessary." | ||
| 2673 | (setq frame (or frame (selected-frame))) | ||
| 2674 | (or (get-next-valid-buffer (nreverse (buffer-list frame)) | ||
| 2675 | buffer visible-ok frame) | ||
| 2676 | (get-buffer "*scratch*") | ||
| 2677 | (let ((scratch (get-buffer-create "*scratch*"))) | ||
| 2678 | (set-buffer-major-mode scratch) | ||
| 2679 | scratch))) | ||
| 2680 | |||
| 2681 | (defun bury-buffer (&optional buffer-or-name) | ||
| 2682 | "Put BUFFER-OR-NAME at the end of the list of all buffers. | ||
| 2683 | There it is the least likely candidate for `other-buffer' to | ||
| 2684 | return; thus, the least likely buffer for \\[switch-to-buffer] to | ||
| 2685 | select by default. | ||
| 2686 | |||
| 2687 | You can specify a buffer name as BUFFER-OR-NAME, or an actual | ||
| 2688 | buffer object. If BUFFER-OR-NAME is nil or omitted, bury the | ||
| 2689 | current buffer. Also, if BUFFER-OR-NAME is nil or omitted, | ||
| 2690 | remove the current buffer from the selected window if it is | ||
| 2691 | displayed there." | ||
| 2692 | (interactive) | ||
| 2693 | (let* ((buffer (normalize-live-buffer buffer-or-name))) | ||
| 2694 | ;; If `buffer-or-name' is not on the selected frame we unrecord it | ||
| 2695 | ;; although it's not "here" (call it a feature). | ||
| 2696 | (unrecord-buffer buffer) | ||
| 2697 | ;; Handle case where `buffer-or-name' is nil and the current buffer | ||
| 2698 | ;; is shown in the selected window. | ||
| 2699 | (cond | ||
| 2700 | ((or buffer-or-name (not (eq buffer (window-buffer))))) | ||
| 2701 | ((not (window-dedicated-p)) | ||
| 2702 | (switch-to-prev-buffer nil 'bury)) | ||
| 2703 | ((frame-root-window-p (selected-window)) | ||
| 2704 | (iconify-frame (window-frame (selected-window)))) | ||
| 2705 | ((window-deletable-p) | ||
| 2706 | (delete-window))) | ||
| 2707 | ;; Always return nil. | ||
| 2708 | nil)) | ||
| 2709 | |||
| 2710 | (defun unbury-buffer () | ||
| 2711 | "Switch to the last buffer in the buffer list." | ||
| 2712 | (interactive) | ||
| 2713 | (switch-to-buffer (last-buffer))) | ||
| 2714 | |||
| 2715 | (defun next-buffer () | ||
| 2716 | "In selected window switch to next buffer." | ||
| 2717 | (interactive) | ||
| 2718 | (switch-to-next-buffer)) | ||
| 2719 | |||
| 2720 | (defun previous-buffer () | ||
| 2721 | "In selected window switch to previous buffer." | ||
| 2722 | (interactive) | ||
| 2723 | (switch-to-prev-buffer)) | ||
| 2724 | |||
| 2725 | (defun delete-windows-on (&optional buffer-or-name frame) | ||
| 2726 | "Delete all windows showing BUFFER-OR-NAME. | ||
| 2727 | BUFFER-OR-NAME may be a buffer or the name of an existing buffer | ||
| 2728 | and defaults to the current buffer. | ||
| 2729 | |||
| 2730 | The following non-nil values of the optional argument FRAME | ||
| 2731 | have special meanings: | ||
| 2732 | |||
| 2733 | - t means consider all windows on the selected frame only. | ||
| 2734 | |||
| 2735 | - `visible' means consider all windows on all visible frames on | ||
| 2736 | the current terminal. | ||
| 2737 | |||
| 2738 | - 0 (the number zero) means consider all windows on all visible | ||
| 2739 | and iconified frames on the current terminal. | ||
| 2740 | |||
| 2741 | - A frame means consider all windows on that frame only. | ||
| 2742 | |||
| 2743 | Any other value of FRAME means consider all windows on all | ||
| 2744 | frames. | ||
| 2745 | |||
| 2746 | When a window showing BUFFER-OR-NAME is dedicated and the only | ||
| 2747 | window of its frame, that frame is deleted when there are other | ||
| 2748 | frames left." | ||
| 2749 | (interactive "BDelete windows on (buffer):\nP") | ||
| 2750 | (let ((buffer (normalize-live-buffer buffer-or-name)) | ||
| 2751 | ;; Handle the "inverted" meaning of the FRAME argument wrt other | ||
| 2752 | ;; `window-list-1' based function. | ||
| 2753 | (all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame)))) | ||
| 2754 | (dolist (window (window-list-1 nil nil all-frames)) | ||
| 2755 | (if (eq (window-buffer window) buffer) | ||
| 2756 | (let ((deletable (window-deletable-p window))) | ||
| 2757 | (cond | ||
| 2758 | ((eq deletable 'frame) | ||
| 2759 | ;; Delete frame. | ||
| 2760 | (delete-frame (window-frame window))) | ||
| 2761 | (deletable | ||
| 2762 | ;; Delete window only. | ||
| 2763 | (delete-window window)) | ||
| 2764 | (t | ||
| 2765 | ;; In window switch to previous buffer. | ||
| 2766 | (set-window-dedicated-p window nil) | ||
| 2767 | (switch-to-prev-buffer window 'bury)))) | ||
| 2768 | ;; If a window doesn't show BUFFER, unrecord BUFFER in it. | ||
| 2769 | (unrecord-window-buffer window buffer))))) | ||
| 2770 | |||
| 2771 | (defun replace-buffer-in-windows (&optional buffer-or-name) | ||
| 2772 | "Replace BUFFER-OR-NAME with some other buffer in all windows showing it. | ||
| 2773 | BUFFER-OR-NAME may be a buffer or the name of an existing buffer | ||
| 2774 | and defaults to the current buffer. | ||
| 2775 | |||
| 2776 | When a window showing BUFFER-OR-NAME is either dedicated, or the | ||
| 2777 | window has no previous buffer, that window is deleted. If that | ||
| 2778 | window is the only window on its frame, the frame is deleted too | ||
| 2779 | when there are other frames left. If there are no other frames | ||
| 2780 | left, some other buffer is displayed in that window. | ||
| 2781 | |||
| 2782 | This function removes the buffer denoted by BUFFER-OR-NAME from | ||
| 2783 | all window-local buffer lists." | ||
| 2784 | (let ((buffer (normalize-live-buffer buffer-or-name))) | ||
| 2785 | (dolist (window (window-list-1 nil nil t)) | ||
| 2786 | (if (eq (window-buffer window) buffer) | ||
| 2787 | (let ((deletable (window-deletable-p window))) | ||
| 2788 | (cond | ||
| 2789 | ((eq deletable 'frame) | ||
| 2790 | ;; Delete frame. | ||
| 2791 | (delete-frame (window-frame window))) | ||
| 2792 | ((and (window-dedicated-p window) deletable) | ||
| 2793 | ;; Delete window. | ||
| 2794 | (delete-window window)) | ||
| 2795 | (t | ||
| 2796 | ;; Switch to another buffer in window. | ||
| 2797 | (set-window-dedicated-p window nil) | ||
| 2798 | (switch-to-prev-buffer window 'kill)))) | ||
| 2799 | ;; Unrecord BUFFER in WINDOW. | ||
| 2800 | (unrecord-window-buffer window buffer))))) | ||
| 2801 | |||
| 2802 | (defun quit-restore-window (&optional window kill) | ||
| 2803 | "Quit WINDOW in some way. | ||
| 2804 | WINDOW must be a live window and defaults to the selected window. | ||
| 2805 | Return nil. | ||
| 2806 | |||
| 2807 | According to information stored in WINDOW's `quit-restore' window | ||
| 2808 | parameter either \(1) delete WINDOW and its frame, \(2) delete | ||
| 2809 | WINDOW, \(3) restore the buffer previously displayed in WINDOW, | ||
| 2810 | or \(4) make WINDOW display some other buffer than the present | ||
| 2811 | one. If non-nil, reset `quit-restore' parameter to nil. | ||
| 2812 | |||
| 2813 | Optional argument KILL non-nil means in addition kill WINDOW's | ||
| 2814 | buffer. If KILL is nil, put WINDOW's buffer at the end of the | ||
| 2815 | buffer list. Interactively, KILL is the prefix argument." | ||
| 2816 | (interactive "i\nP") | ||
| 2817 | (setq window (normalize-live-window window)) | ||
| 2818 | (let ((buffer (window-buffer window)) | ||
| 2819 | (quit-restore (window-parameter window 'quit-restore)) | ||
| 2820 | deletable resize) | ||
| 2821 | (cond | ||
| 2822 | ((and (or (and (memq (car-safe quit-restore) '(new-window new-frame)) | ||
| 2823 | ;; Check that WINDOW's buffer is still the same. | ||
| 2824 | (eq (window-buffer window) (nth 1 quit-restore))) | ||
| 2825 | (window-dedicated-p window)) | ||
| 2826 | (setq deletable (window-deletable-p window))) | ||
| 2827 | ;; WINDOW can be deleted. | ||
| 2828 | (unrecord-buffer buffer) | ||
| 2829 | (if (eq deletable 'frame) | ||
| 2830 | ;; WINDOW's frame can be deleted. | ||
| 2831 | (delete-frame (window-frame window)) | ||
| 2832 | ;; Just delete WINDOW. | ||
| 2833 | (delete-window window)) | ||
| 2834 | ;; If the previously selected window is still alive, select it. | ||
| 2835 | (when (window-live-p (nth 2 quit-restore)) | ||
| 2836 | (select-window (nth 2 quit-restore)))) | ||
| 2837 | ((and (buffer-live-p (nth 0 quit-restore)) | ||
| 2838 | ;; The buffer currently shown in WINDOW must still be the | ||
| 2839 | ;; buffer shown when its `quit-restore' parameter was created | ||
| 2840 | ;; in the first place. | ||
| 2841 | (eq (window-buffer window) (nth 3 quit-restore))) | ||
| 2842 | (setq resize (with-current-buffer buffer temp-buffer-resize-mode)) | ||
| 2843 | ;; Unrecord buffer. | ||
| 2844 | (unrecord-buffer buffer) | ||
| 2845 | (unrecord-window-buffer window buffer) | ||
| 2846 | ;; Display buffer stored in the quit-restore parameter. | ||
| 2847 | (set-window-dedicated-p window nil) | ||
| 2848 | (set-window-buffer window (nth 0 quit-restore)) | ||
| 2849 | (set-window-start window (nth 1 quit-restore)) | ||
| 2850 | (set-window-point window (nth 2 quit-restore)) | ||
| 2851 | (when (and resize (/= (nth 4 quit-restore) (window-total-size window))) | ||
| 2852 | (resize-window | ||
| 2853 | window (- (nth 4 quit-restore) (window-total-size window)))) | ||
| 2854 | ;; Reset the quit-restore parameter. | ||
| 2855 | (set-window-parameter window 'quit-restore nil) | ||
| 2856 | (when (window-live-p (nth 5 quit-restore)) | ||
| 2857 | (select-window (nth 5 quit-restore)))) | ||
| 2858 | (t | ||
| 2859 | ;; Otherwise, show another buffer in WINDOW and reset the | ||
| 2860 | ;; quit-restore parameter. | ||
| 2861 | (set-window-parameter window 'quit-restore nil) | ||
| 2862 | (unrecord-buffer buffer) | ||
| 2863 | (switch-to-prev-buffer window 'bury-or-kill))) | ||
| 2864 | |||
| 2865 | ;; Kill WINDOW's old-buffer if requested | ||
| 2866 | (when kill (kill-buffer buffer)) | ||
| 2867 | nil)) | ||
| 2288 | 2868 | ||
| 2289 | ;;; Splitting windows. | 2869 | ;;; Splitting windows. |
| 2290 | (defsubst window-split-min-size (&optional horizontal) | 2870 | (defsubst window-split-min-size (&optional horizontal) |
| @@ -2569,22 +3149,14 @@ window." | |||
| 2569 | (<= (window-start new-window) old-point) | 3149 | (<= (window-start new-window) old-point) |
| 2570 | (set-window-point new-window old-point) | 3150 | (set-window-point new-window old-point) |
| 2571 | (select-window new-window))) | 3151 | (select-window new-window))) |
| 2572 | (split-window-save-restore-data new-window old-window))) | 3152 | ;; Always copy quit-restore parameter in interactive use. |
| 3153 | (let ((quit-restore (window-parameter old-window 'quit-restore))) | ||
| 3154 | (when quit-restore | ||
| 3155 | (set-window-parameter new-window 'quit-restore quit-restore))) | ||
| 3156 | new-window)) | ||
| 2573 | 3157 | ||
| 2574 | (defalias 'split-window-vertically 'split-window-above-each-other) | 3158 | (defalias 'split-window-vertically 'split-window-above-each-other) |
| 2575 | 3159 | ||
| 2576 | ;; This is to avoid compiler warnings. | ||
| 2577 | (defvar view-return-to-alist) | ||
| 2578 | |||
| 2579 | (defun split-window-save-restore-data (new-window old-window) | ||
| 2580 | (with-current-buffer (window-buffer) | ||
| 2581 | (when view-mode | ||
| 2582 | (let ((old-info (assq old-window view-return-to-alist))) | ||
| 2583 | (when old-info | ||
| 2584 | (push (cons new-window (cons (car (cdr old-info)) t)) | ||
| 2585 | view-return-to-alist)))) | ||
| 2586 | new-window)) | ||
| 2587 | |||
| 2588 | (defun split-window-side-by-side (&optional size) | 3160 | (defun split-window-side-by-side (&optional size) |
| 2589 | "Split selected window into two windows side by side. | 3161 | "Split selected window into two windows side by side. |
| 2590 | The selected window becomes the left one and gets SIZE columns. | 3162 | The selected window becomes the left one and gets SIZE columns. |
| @@ -2603,7 +3175,12 @@ The selected window remains selected. Return the new window." | |||
| 2603 | (when (and size (< size 0) (< (- size) window-min-width)) | 3175 | (when (and size (< size 0) (< (- size) window-min-width)) |
| 2604 | ;; `split-window' would not signal an error here. | 3176 | ;; `split-window' would not signal an error here. |
| 2605 | (error "Size of new window too small")) | 3177 | (error "Size of new window too small")) |
| 2606 | (split-window-save-restore-data (split-window nil size t) old-window))) | 3178 | (setq new-window (split-window nil size t)) |
| 3179 | ;; Always copy quit-restore parameter in interactive use. | ||
| 3180 | (let ((quit-restore (window-parameter old-window 'quit-restore))) | ||
| 3181 | (when quit-restore | ||
| 3182 | (set-window-parameter new-window 'quit-restore quit-restore))) | ||
| 3183 | new-window)) | ||
| 2607 | 3184 | ||
| 2608 | (defalias 'split-window-horizontally 'split-window-side-by-side) | 3185 | (defalias 'split-window-horizontally 'split-window-side-by-side) |
| 2609 | 3186 | ||
| @@ -3545,6 +4122,29 @@ consider all visible or iconified frames on the current terminal." | |||
| 3545 | (window--even-window-heights window-to-use) | 4122 | (window--even-window-heights window-to-use) |
| 3546 | (window--display-buffer-2 buffer window-to-use))))) | 4123 | (window--display-buffer-2 buffer window-to-use))))) |
| 3547 | 4124 | ||
| 4125 | (defun display-buffer-other-frame (buffer) | ||
| 4126 | "Display buffer BUFFER in another frame. | ||
| 4127 | This uses the function `display-buffer' as a subroutine; see | ||
| 4128 | its documentation for additional customization information." | ||
| 4129 | (interactive "BDisplay buffer in other frame: ") | ||
| 4130 | (let ((pop-up-frames t) | ||
| 4131 | same-window-buffer-names same-window-regexps | ||
| 4132 | ;;(old-window (selected-window)) | ||
| 4133 | new-window) | ||
| 4134 | (setq new-window (display-buffer buffer t)) | ||
| 4135 | ;; This may have been here in order to prevent the new frame from hiding | ||
| 4136 | ;; the old frame. But it does more harm than good. | ||
| 4137 | ;; Maybe we should call `raise-window' on the old-frame instead? --Stef | ||
| 4138 | ;;(lower-frame (window-frame new-window)) | ||
| 4139 | |||
| 4140 | ;; This may have been here in order to make sure the old-frame gets the | ||
| 4141 | ;; focus. But not only can it cause an annoying flicker, with some | ||
| 4142 | ;; window-managers it just makes the window invisible, with no easy | ||
| 4143 | ;; way to recover it. --Stef | ||
| 4144 | ;;(make-frame-invisible (window-frame old-window)) | ||
| 4145 | ;;(make-frame-visible (window-frame old-window)) | ||
| 4146 | )) | ||
| 4147 | |||
| 3548 | (defun pop-to-buffer (buffer-or-name &optional other-window norecord) | 4148 | (defun pop-to-buffer (buffer-or-name &optional other-window norecord) |
| 3549 | "Select buffer BUFFER-OR-NAME in some window, preferably a different one. | 4149 | "Select buffer BUFFER-OR-NAME in some window, preferably a different one. |
| 3550 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | 4150 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or |
| @@ -3587,6 +4187,130 @@ at the front of the list of recently selected ones." | |||
| 3587 | ;; input focus and is risen. | 4187 | ;; input focus and is risen. |
| 3588 | (select-frame-set-input-focus new-frame)) | 4188 | (select-frame-set-input-focus new-frame)) |
| 3589 | buffer)) | 4189 | buffer)) |
| 4190 | |||
| 4191 | (defun read-buffer-to-switch (prompt) | ||
| 4192 | "Read the name of a buffer to switch to, prompting with PROMPT. | ||
| 4193 | Return the neame of the buffer as a string. | ||
| 4194 | |||
| 4195 | This function is intended for the `switch-to-buffer' family of | ||
| 4196 | commands since these need to omit the name of the current buffer | ||
| 4197 | from the list of completions and default values." | ||
| 4198 | (let ((rbts-completion-table (internal-complete-buffer-except))) | ||
| 4199 | (minibuffer-with-setup-hook | ||
| 4200 | (lambda () | ||
| 4201 | (setq minibuffer-completion-table rbts-completion-table) | ||
| 4202 | ;; Since rbts-completion-table is built dynamically, we | ||
| 4203 | ;; can't just add it to the default value of | ||
| 4204 | ;; icomplete-with-completion-tables, so we add it | ||
| 4205 | ;; here manually. | ||
| 4206 | (if (and (boundp 'icomplete-with-completion-tables) | ||
| 4207 | (listp icomplete-with-completion-tables)) | ||
| 4208 | (set (make-local-variable 'icomplete-with-completion-tables) | ||
| 4209 | (cons rbts-completion-table | ||
| 4210 | icomplete-with-completion-tables)))) | ||
| 4211 | (read-buffer prompt (other-buffer (current-buffer)) | ||
| 4212 | (confirm-nonexistent-file-or-buffer))))) | ||
| 4213 | |||
| 4214 | (defun normalize-buffer-to-switch-to (buffer-or-name) | ||
| 4215 | "Normalize BUFFER-OR-NAME argument of buffer switching functions. | ||
| 4216 | If BUFFER-OR-NAME is nil, return the buffer returned by | ||
| 4217 | `other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME | ||
| 4218 | exists, return that buffer. If no such buffer exists, create a | ||
| 4219 | buffer with the name BUFFER-OR-NAME and return that buffer." | ||
| 4220 | (if buffer-or-name | ||
| 4221 | (or (get-buffer buffer-or-name) | ||
| 4222 | (let ((buffer (get-buffer-create buffer-or-name))) | ||
| 4223 | (set-buffer-major-mode buffer) | ||
| 4224 | buffer)) | ||
| 4225 | (other-buffer))) | ||
| 4226 | |||
| 4227 | (defun switch-to-buffer (buffer-or-name &optional norecord) | ||
| 4228 | "Switch to buffer BUFFER-OR-NAME in the selected window. | ||
| 4229 | If called interactively, prompt for the buffer name using the | ||
| 4230 | minibuffer. The variable `confirm-nonexistent-file-or-buffer' | ||
| 4231 | determines whether to request confirmation before creating a new | ||
| 4232 | buffer. | ||
| 4233 | |||
| 4234 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | ||
| 4235 | nil. If BUFFER-OR-NAME is a string that does not identify an | ||
| 4236 | existing buffer, create a buffer with that name. If | ||
| 4237 | BUFFER-OR-NAME is nil, switch to the buffer returned by | ||
| 4238 | `other-buffer'. | ||
| 4239 | |||
| 4240 | Optional argument NORECORD non-nil means do not put the buffer | ||
| 4241 | specified by BUFFER-OR-NAME at the front of the buffer list and | ||
| 4242 | do not make the window displaying it the most recently selected | ||
| 4243 | one. Return the buffer switched to. | ||
| 4244 | |||
| 4245 | This function is intended for interactive use only. Lisp | ||
| 4246 | functions should call `pop-to-buffer-same-window' instead." | ||
| 4247 | (interactive | ||
| 4248 | (list (read-buffer-to-switch "Switch to buffer: "))) | ||
| 4249 | (let ((buffer (normalize-buffer-to-switch-to buffer-or-name))) | ||
| 4250 | (if (and (or (window-minibuffer-p) (eq (window-dedicated-p) t)) | ||
| 4251 | (not (eq buffer (window-buffer)))) | ||
| 4252 | ;; Cannot switch to another buffer in a minibuffer or strongly | ||
| 4253 | ;; dedicated window that does not show the buffer already. Call | ||
| 4254 | ;; `pop-to-buffer' instead. | ||
| 4255 | (pop-to-buffer buffer nil norecord) | ||
| 4256 | (unless (eq buffer (window-buffer)) | ||
| 4257 | ;; I'm not sure why we should NOT call `set-window-buffer' here, | ||
| 4258 | ;; but let's keep things as they are (otherwise we could always | ||
| 4259 | ;; call `pop-to-buffer-same-window' here). | ||
| 4260 | (set-window-buffer nil buffer)) | ||
| 4261 | (unless norecord | ||
| 4262 | (select-window (selected-window))) | ||
| 4263 | (set-buffer buffer)))) | ||
| 4264 | |||
| 4265 | (defun switch-to-buffer-other-window (buffer-or-name &optional norecord) | ||
| 4266 | "Select the buffer specified by BUFFER-OR-NAME in another window. | ||
| 4267 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | ||
| 4268 | nil. Return the buffer switched to. | ||
| 4269 | |||
| 4270 | If called interactively, prompt for the buffer name using the | ||
| 4271 | minibuffer. The variable `confirm-nonexistent-file-or-buffer' | ||
| 4272 | determines whether to request confirmation before creating a new | ||
| 4273 | buffer. | ||
| 4274 | |||
| 4275 | If BUFFER-OR-NAME is a string and does not identify an existing | ||
| 4276 | buffer, create a new buffer with that name. If BUFFER-OR-NAME is | ||
| 4277 | nil, switch to the buffer returned by `other-buffer'. | ||
| 4278 | |||
| 4279 | Optional second argument NORECORD non-nil means do not put this | ||
| 4280 | buffer at the front of the list of recently selected ones. | ||
| 4281 | |||
| 4282 | This uses the function `display-buffer' as a subroutine; see its | ||
| 4283 | documentation for additional customization information." | ||
| 4284 | (interactive | ||
| 4285 | (list (read-buffer-to-switch "Switch to buffer in other window: "))) | ||
| 4286 | (let ((pop-up-windows t) | ||
| 4287 | same-window-buffer-names same-window-regexps) | ||
| 4288 | (pop-to-buffer buffer-or-name t norecord))) | ||
| 4289 | |||
| 4290 | (defun switch-to-buffer-other-frame (buffer-or-name &optional norecord) | ||
| 4291 | "Switch to buffer BUFFER-OR-NAME in another frame. | ||
| 4292 | BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or | ||
| 4293 | nil. Return the buffer switched to. | ||
| 4294 | |||
| 4295 | If called interactively, prompt for the buffer name using the | ||
| 4296 | minibuffer. The variable `confirm-nonexistent-file-or-buffer' | ||
| 4297 | determines whether to request confirmation before creating a new | ||
| 4298 | buffer. | ||
| 4299 | |||
| 4300 | If BUFFER-OR-NAME is a string and does not identify an existing | ||
| 4301 | buffer, create a new buffer with that name. If BUFFER-OR-NAME is | ||
| 4302 | nil, switch to the buffer returned by `other-buffer'. | ||
| 4303 | |||
| 4304 | Optional second arg NORECORD non-nil means do not put this | ||
| 4305 | buffer at the front of the list of recently selected ones. | ||
| 4306 | |||
| 4307 | This uses the function `display-buffer' as a subroutine; see its | ||
| 4308 | documentation for additional customization information." | ||
| 4309 | (interactive | ||
| 4310 | (list (read-buffer-to-switch "Switch to buffer in other frame: "))) | ||
| 4311 | (let ((pop-up-frames t) | ||
| 4312 | same-window-buffer-names same-window-regexps) | ||
| 4313 | (pop-to-buffer buffer-or-name t norecord))) | ||
| 3590 | 4314 | ||
| 3591 | (defun set-window-text-height (window height) | 4315 | (defun set-window-text-height (window height) |
| 3592 | "Set the height in lines of the text display area of WINDOW to HEIGHT. | 4316 | "Set the height in lines of the text display area of WINDOW to HEIGHT. |
| @@ -4258,21 +4982,6 @@ active. This function is run by `mouse-autoselect-window-timer'." | |||
| 4258 | (run-hooks 'mouse-leave-buffer-hook)) | 4982 | (run-hooks 'mouse-leave-buffer-hook)) |
| 4259 | (select-window window)))) | 4983 | (select-window window)))) |
| 4260 | 4984 | ||
| 4261 | (defun delete-other-windows-vertically (&optional window) | ||
| 4262 | "Delete the windows in the same column with WINDOW, but not WINDOW itself. | ||
| 4263 | This may be a useful alternative binding for \\[delete-other-windows] | ||
| 4264 | if you often split windows horizontally." | ||
| 4265 | (interactive) | ||
| 4266 | (let* ((window (or window (selected-window))) | ||
| 4267 | (edges (window-edges window)) | ||
| 4268 | (w window) delenda) | ||
| 4269 | (while (not (eq (setq w (next-window w 1)) window)) | ||
| 4270 | (let ((e (window-edges w))) | ||
| 4271 | (when (and (= (car e) (car edges)) | ||
| 4272 | (= (caddr e) (caddr edges))) | ||
| 4273 | (push w delenda)))) | ||
| 4274 | (mapc 'delete-window delenda))) | ||
| 4275 | |||
| 4276 | (defun truncated-partial-width-window-p (&optional window) | 4985 | (defun truncated-partial-width-window-p (&optional window) |
| 4277 | "Return non-nil if lines in WINDOW are specifically truncated due to its width. | 4986 | "Return non-nil if lines in WINDOW are specifically truncated due to its width. |
| 4278 | WINDOW defaults to the selected window. | 4987 | WINDOW defaults to the selected window. |
| @@ -4293,6 +5002,7 @@ Otherwise, consult the value of `truncate-partial-width-windows' | |||
| 4293 | (define-key ctl-x-map "1" 'delete-other-windows) | 5002 | (define-key ctl-x-map "1" 'delete-other-windows) |
| 4294 | (define-key ctl-x-map "2" 'split-window-above-each-other) | 5003 | (define-key ctl-x-map "2" 'split-window-above-each-other) |
| 4295 | (define-key ctl-x-map "3" 'split-window-side-by-side) | 5004 | (define-key ctl-x-map "3" 'split-window-side-by-side) |
| 5005 | (define-key ctl-x-map "o" 'other-window) | ||
| 4296 | (define-key ctl-x-map "^" 'enlarge-window) | 5006 | (define-key ctl-x-map "^" 'enlarge-window) |
| 4297 | (define-key ctl-x-map "}" 'enlarge-window-horizontally) | 5007 | (define-key ctl-x-map "}" 'enlarge-window-horizontally) |
| 4298 | (define-key ctl-x-map "{" 'shrink-window-horizontally) | 5008 | (define-key ctl-x-map "{" 'shrink-window-horizontally) |