aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS16
-rw-r--r--lisp/dired.el20
-rw-r--r--lisp/tab-bar.el16
-rw-r--r--lisp/window.el72
4 files changed, 124 insertions, 0 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 47275db47e3..2654d9d7995 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -309,9 +309,25 @@ It specifies how 'set-window-configuration' and 'window-state-put'
309should proceed with windows whose buffer was killed after the 309should proceed with windows whose buffer was killed after the
310corresponding configuration or state was recorded. 310corresponding configuration or state was recorded.
311 311
312*** New variable 'window-point-context-set-function'.
313It can be used to set a context for window point in all windows by
314'window-point-context-set' before calling 'current-window-configuration'
315and 'window-state-get'. Then later another new variable
316'window-point-context-use-function' can be used by
317'window-point-context-use' after 'set-window-configuration' and
318'window-state-put' to restore positions of window points
319according to the context stored in a window parameter.
320
312** Tab Bars and Tab Lines 321** Tab Bars and Tab Lines
313 322
314--- 323---
324*** New user option 'tab-bar-select-restore-context'.
325It uses 'window-point-context-set' to save contexts where
326window points were located before switching away from the tab,
327and 'window-point-context-use' to restore positions of window
328points after switching back to that tab.
329
330---
315*** New user option 'tab-bar-select-restore-windows'. 331*** New user option 'tab-bar-select-restore-windows'.
316It defines what to do with windows whose buffer was killed 332It defines what to do with windows whose buffer was killed
317since the tab was last selected. By default it displays 333since the tab was last selected. By default it displays
diff --git a/lisp/dired.el b/lisp/dired.el
index 9e3b888df14..f0113c002a4 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2743,6 +2743,26 @@ Keybindings:
2743 '(dired-font-lock-keywords t nil nil beginning-of-line)) 2743 '(dired-font-lock-keywords t nil nil beginning-of-line))
2744 (setq-local desktop-save-buffer 'dired-desktop-buffer-misc-data) 2744 (setq-local desktop-save-buffer 'dired-desktop-buffer-misc-data)
2745 (setq-local grep-read-files-function #'dired-grep-read-files) 2745 (setq-local grep-read-files-function #'dired-grep-read-files)
2746 (setq-local window-point-context-set-function
2747 (lambda (w)
2748 (with-current-buffer (window-buffer w)
2749 (let ((point (window-point w)))
2750 (save-excursion
2751 (goto-char point)
2752 (if-let ((f (dired-get-filename nil t)))
2753 `((dired-filename . ,f))
2754 `((position . ,(point)))))))))
2755 (setq-local window-point-context-use-function
2756 (lambda (w context)
2757 (with-current-buffer (window-buffer w)
2758 (let ((point (window-point w)))
2759 (save-excursion
2760 (if-let ((f (alist-get 'dired-filename context)))
2761 (dired-goto-file f)
2762 (when-let ((p (alist-get 'position context)))
2763 (goto-char p)))
2764 (setq point (point)))
2765 (set-window-point w point)))))
2746 (setq dired-switches-alist nil) 2766 (setq dired-switches-alist nil)
2747 (hack-dir-local-variables-non-file-buffer) ; before sorting 2767 (hack-dir-local-variables-non-file-buffer) ; before sorting
2748 (dired-sort-other dired-actual-switches t) 2768 (dired-sort-other dired-actual-switches t)
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index fa22500a04e..05631c3c8f3 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1292,6 +1292,9 @@ tab bar might wrap to the second line when it shouldn't.")
1292 frame 'buffer-list))) 1292 frame 'buffer-list)))
1293 (bbl (seq-filter #'buffer-live-p (frame-parameter 1293 (bbl (seq-filter #'buffer-live-p (frame-parameter
1294 frame 'buried-buffer-list)))) 1294 frame 'buried-buffer-list))))
1295 (when tab-bar-select-restore-context
1296 (window-point-context-set))
1297
1295 `(tab 1298 `(tab
1296 (name . ,(if tab-explicit-name 1299 (name . ,(if tab-explicit-name
1297 (alist-get 'name tab) 1300 (alist-get 'name tab)
@@ -1442,6 +1445,16 @@ if it was visiting a file."
1442 (setq buffer-read-only t) 1445 (setq buffer-read-only t)
1443 (set-window-buffer window new-buffer)))))) 1446 (set-window-buffer window new-buffer))))))
1444 1447
1448(defcustom tab-bar-select-restore-context t
1449 "If this is non-nil, try to restore window points from their contexts.
1450This will try to find the same position in every window where point was
1451before switching away from this tab. After selecting this tab,
1452point in every window will be moved to its previous position
1453in the buffer even when the buffer was modified."
1454 :type 'boolean
1455 :group 'tab-bar
1456 :version "30.1")
1457
1445(defvar tab-bar-minibuffer-restore-tab nil 1458(defvar tab-bar-minibuffer-restore-tab nil
1446 "Tab number for `tab-bar-minibuffer-restore-tab'.") 1459 "Tab number for `tab-bar-minibuffer-restore-tab'.")
1447 1460
@@ -1539,6 +1552,9 @@ Negative TAB-NUMBER counts tabs from the end of the tab bar."
1539 (select-window (get-mru-window))) 1552 (select-window (get-mru-window)))
1540 (window-state-put ws nil 'safe))) 1553 (window-state-put ws nil 'safe)))
1541 1554
1555 (when tab-bar-select-restore-context
1556 (window-point-context-use))
1557
1542 ;; Select the minibuffer when it was active before switching tabs 1558 ;; Select the minibuffer when it was active before switching tabs
1543 (when (and minibuffer-was-active (active-minibuffer-window)) 1559 (when (and minibuffer-was-active (active-minibuffer-window))
1544 (select-window (active-minibuffer-window))) 1560 (select-window (active-minibuffer-window)))
diff --git a/lisp/window.el b/lisp/window.el
index 46de1819c69..3867f6fa6ef 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10838,6 +10838,78 @@ displaying that processes's buffer."
10838 (set-process-window-size process (cdr size) (car size)))))))))) 10838 (set-process-window-size process (cdr size) (car size))))))))))
10839 10839
10840(add-hook 'window-configuration-change-hook 'window--adjust-process-windows) 10840(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
10841
10842
10843;;; Window point context
10844
10845(defun window-point-context-set ()
10846 "Set context near the window point.
10847Call function specified by `window-point-context-set-function' for every
10848live window on the selected frame with that window as sole argument.
10849The function called is supposed to return a context of the window's point
10850that can be later used as argument for `window-point-context-use-function'.
10851Remember the returned context in the window parameter `context'."
10852 (walk-windows
10853 (lambda (w)
10854 (when-let ((fn (buffer-local-value 'window-point-context-set-function
10855 (window-buffer w)))
10856 ((functionp fn))
10857 (context (funcall fn w)))
10858 (set-window-parameter w 'context (cons (buffer-name) context))))
10859 'nomini))
10860
10861(defun window-point-context-use ()
10862 "Use context to relocate the window point.
10863Call function specified by `window-point-context-use-function' to move the
10864window point according to the previously saved context. For every live
10865window on the selected frame this function is called with two arguments:
10866the window and the context data structure saved by
10867`window-point-context-set-function' in the window parameter `context'.
10868The function called is supposed to set the window point to the location
10869found by the provided context."
10870 (walk-windows
10871 (lambda (w)
10872 (when-let ((fn (buffer-local-value 'window-point-context-use-function
10873 (window-buffer w)))
10874 ((functionp fn))
10875 (context (window-parameter w 'context))
10876 ((equal (buffer-name) (car context))))
10877 (funcall fn w (cdr context))
10878 (set-window-parameter w 'context nil)))
10879 'nomini))
10880
10881(add-to-list 'window-persistent-parameters '(context . writable))
10882
10883(defun window-point-context-set-default-function (w)
10884 "Set context of file buffers to the front and rear strings."
10885 (with-current-buffer (window-buffer w)
10886 (when buffer-file-name
10887 (let ((point (window-point w)))
10888 `((front-context-string
10889 . ,(buffer-substring-no-properties
10890 point (min (+ point 16) (point-max))))
10891 (rear-context-string
10892 . ,(buffer-substring-no-properties
10893 point (max (- point 16) (point-min)))))))))
10894
10895(defun window-point-context-use-default-function (w context)
10896 "Restore context of file buffers by the front and rear strings."
10897 (with-current-buffer (window-buffer w)
10898 (let ((point (window-point w)))
10899 (save-excursion
10900 (goto-char point)
10901 (when-let ((f (alist-get 'front-context-string context))
10902 ((search-forward f (point-max) t)))
10903 (goto-char (match-beginning 0))
10904 (when-let ((r (alist-get 'rear-context-string context))
10905 ((search-backward r (point-min) t)))
10906 (goto-char (match-end 0))
10907 (setq point (point)))))
10908 (set-window-point w point))))
10909
10910(defvar window-point-context-set-function 'window-point-context-set-default-function)
10911(defvar window-point-context-use-function 'window-point-context-use-default-function)
10912
10841 10913
10842;; Some of these are in tutorial--default-keys, so update that if you 10914;; Some of these are in tutorial--default-keys, so update that if you
10843;; change these. 10915;; change these.