1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-03 18:41:25 -08:00

* lisp/tab-bar.el: Store point position and frame buffer-lists in tab.

* lisp/tab-bar.el (tab-bar--tab): Store additionally point-marker,
frame parameters buffer-list and buried-buffer-list, both for wc and ws.
Use seq-filter.
(tab-bar-select-tab): Restore point-marker after restoring
window-configuration.  Also restore frame parameters buffer-list
and buried-buffer-list both for window-configuration and window-state.
(tab-bar-history-limit, tab-bar-history--minibuffer-depth): New variables.
(tab-bar-history-current): Rename from tab-bar-history--pre-change.
(tab-bar-history--pre-change): Set tab-bar-history-current.
(tab-bar--history-change): Use seq-take for tab-bar-history-limit.
(tab-bar-history-back, tab-bar-history-forward): Restore point-marker.
(tab-bar-list-noselect): Use seq-remove.

* lisp/emacs-lisp/seq.el (seq-take, seq-filter): Add autoload cookie.
This commit is contained in:
Juri Linkov 2019-10-30 00:31:11 +02:00
parent d3517de4b4
commit d7f62ce0cd
2 changed files with 95 additions and 37 deletions

View file

@ -223,6 +223,7 @@ If N is a negative integer or zero, SEQUENCE is returned."
(let ((length (seq-length sequence)))
(seq-subseq sequence (min n length) length))))
;;;###autoload
(cl-defgeneric seq-take (sequence n)
"Take the first N elements of SEQUENCE and return the result.
The result is a sequence of the same type as SEQUENCE.
@ -306,6 +307,7 @@ list."
(`list (seq--into-list sequence))
(_ (error "Not a sequence type name: %S" type))))
;;;###autoload
(cl-defgeneric seq-filter (pred sequence)
"Return a list of all the elements for which (PRED element) is non-nil in SEQUENCE."
(let ((exclude (make-symbol "exclude")))

View file

@ -438,7 +438,9 @@ Return its existing value or a new value."
(defun tab-bar--tab ()
(let* ((tab (assq 'current-tab (frame-parameter nil 'tabs)))
(tab-explicit-name (cdr (assq 'explicit-name tab))))
(tab-explicit-name (cdr (assq 'explicit-name tab)))
(bl (seq-filter #'buffer-live-p (frame-parameter nil 'buffer-list)))
(bbl (seq-filter #'buffer-live-p (frame-parameter nil 'buried-buffer-list))))
`(tab
(name . ,(if tab-explicit-name
(cdr (assq 'name tab))
@ -446,10 +448,15 @@ Return its existing value or a new value."
(explicit-name . ,tab-explicit-name)
(time . ,(time-convert nil 'integer))
(wc . ,(current-window-configuration))
(wc-point . ,(point-marker))
(wc-bl . ,bl)
(wc-bbl . ,bbl)
(wc-history-back . ,(gethash (selected-frame) tab-bar-history-back))
(wc-history-forward . ,(gethash (selected-frame) tab-bar-history-forward))
(ws . ,(window-state-get
(frame-root-window (selected-frame)) 'writable))
(history-back . ,(gethash (selected-frame) tab-bar-history-back))
(history-forward . ,(gethash (selected-frame) tab-bar-history-forward)))))
(ws-bl . ,(mapcar #'buffer-name bl))
(ws-bbl . ,(mapcar #'buffer-name bbl)))))
(defun tab-bar--current-tab (&optional tab)
;; `tab` here is an argument meaning 'use tab as template'. This is
@ -505,9 +512,7 @@ to the numeric argument. ARG counts from 1."
(let* ((from-tab (tab-bar--tab))
(to-tab (nth to-index tabs))
(wc (cdr (assq 'wc to-tab)))
(ws (cdr (assq 'ws to-tab)))
(history-back (cdr (assq 'history-back to-tab)))
(history-forward (cdr (assq 'history-forward to-tab))))
(ws (cdr (assq 'ws to-tab))))
;; During the same session, use window-configuration to switch
;; tabs, because window-configurations are more reliable
@ -515,18 +520,54 @@ to the numeric argument. ARG counts from 1."
;; But after restoring tabs from a previously saved session,
;; its value of window-configuration is unreadable,
;; so restore its saved window-state.
(if (window-configuration-p wc)
(set-window-configuration wc)
(if ws (window-state-put ws (frame-root-window (selected-frame))
'safe)))
(cond
((window-configuration-p wc)
(let ((wc-point (cdr (assq 'wc-point to-tab)))
(wc-bl (seq-filter #'buffer-live-p (cdr (assq 'wc-bl to-tab))))
(wc-bbl (seq-filter #'buffer-live-p (cdr (assq 'wc-bbl to-tab))))
(wc-history-back (cdr (assq 'wc-history-back to-tab)))
(wc-history-forward (cdr (assq 'wc-history-forward to-tab))))
(set-window-configuration wc)
;; set-window-configuration does not restore the value of
;; point in the current buffer, so restore it separately.
(when (and (markerp wc-point)
(marker-buffer wc-point)
;; FIXME: After dired-revert, marker relocates to 1.
;; window-configuration restores point to global point
;; in this dired buffer, not to its window point,
;; but this is slightly better than 1.
(not (eq 1 (marker-position wc-point))))
(goto-char wc-point))
(when wc-bl (modify-frame-parameters
nil (list (cons 'buffer-list wc-bl))))
(when wc-bbl (modify-frame-parameters
nil (list (cons 'buried-buffer-list wc-bbl))))
(setq tab-bar-history-omit t)
(puthash (selected-frame)
(and (window-configuration-p (car history-back)) history-back)
(and (window-configuration-p (cdr (assq 'wc (car wc-history-back))))
wc-history-back)
tab-bar-history-back)
(puthash (selected-frame)
(and (window-configuration-p (car history-forward)) history-forward)
tab-bar-history-forward)
(and (window-configuration-p (cdr (assq 'wc (car wc-history-forward))))
wc-history-forward)
tab-bar-history-forward)))
(ws
(window-state-put ws (frame-root-window (selected-frame)) 'safe)
(let ((ws-bl (seq-filter #'buffer-live-p
(mapcar #'get-buffer (cdr (assq 'ws-bl to-tab)))))
(ws-bbl (seq-filter #'buffer-live-p
(mapcar #'get-buffer (cdr (assq 'ws-bbl to-tab))))))
(when ws-bl (modify-frame-parameters
nil (list (cons 'buffer-list ws-bl))))
(when ws-bbl (modify-frame-parameters
nil (list (cons 'buried-buffer-list ws-bbl)))))))
(setq tab-bar-history-omit t)
(when from-index
(setf (nth from-index tabs) from-tab))
@ -861,6 +902,9 @@ function `tab-bar-tab-name-function'."
;;; Tab history mode
(defvar tab-bar-history-limit 3
"The number of history elements to keep.")
(defvar tab-bar-history-omit nil
"When non-nil, omit window-configuration changes from the current command.")
@ -870,24 +914,29 @@ function `tab-bar-tab-name-function'."
(defvar tab-bar-history-forward (make-hash-table)
"History of forward changes in every tab per frame.")
(defvar tab-bar-history--pre-change nil
"Window configuration and minibuffer depth before the current command.")
(defvar tab-bar-history-current nil
"Window configuration before the current command.")
(defvar tab-bar-history--minibuffer-depth 0
"Minibuffer depth before the current command.")
(defun tab-bar-history--pre-change ()
(setq tab-bar-history--pre-change
(list (current-window-configuration)
(minibuffer-depth))))
(setq tab-bar-history--minibuffer-depth (minibuffer-depth)
tab-bar-history-current
`((wc . ,(current-window-configuration))
(wc-point . ,(point-marker)))))
(defun tab-bar--history-change ()
(when (and (not tab-bar-history-omit)
tab-bar-history--pre-change
tab-bar-history-current
;; Entering the minibuffer
(zerop (nth 1 tab-bar-history--pre-change))
(zerop tab-bar-history--minibuffer-depth)
;; Exiting the minibuffer
(zerop (minibuffer-depth)))
(puthash (selected-frame)
(cons (nth 0 tab-bar-history--pre-change)
(seq-take (cons tab-bar-history-current
(gethash (selected-frame) tab-bar-history-back))
tab-bar-history-limit)
tab-bar-history-back))
(when tab-bar-history-omit
(setq tab-bar-history-omit nil)))
@ -895,27 +944,35 @@ function `tab-bar-tab-name-function'."
(defun tab-bar-history-back ()
(interactive)
(setq tab-bar-history-omit t)
(let ((wc (pop (gethash (selected-frame) tab-bar-history-back))))
(let* ((history (pop (gethash (selected-frame) tab-bar-history-back)))
(wc (cdr (assq 'wc history)))
(wc-point (cdr (assq 'wc-point history))))
(if (window-configuration-p wc)
(progn
(puthash (selected-frame)
(cons (current-window-configuration)
(cons tab-bar-history-current
(gethash (selected-frame) tab-bar-history-forward))
tab-bar-history-forward)
(set-window-configuration wc))
(set-window-configuration wc)
(when (and (markerp wc-point) (marker-buffer wc-point))
(goto-char wc-point)))
(message "No more tab back history"))))
(defun tab-bar-history-forward ()
(interactive)
(setq tab-bar-history-omit t)
(let ((wc (pop (gethash (selected-frame) tab-bar-history-forward))))
(let* ((history (pop (gethash (selected-frame) tab-bar-history-forward)))
(wc (cdr (assq 'wc history)))
(wc-point (cdr (assq 'wc-point history))))
(if (window-configuration-p wc)
(progn
(puthash (selected-frame)
(cons (current-window-configuration)
(cons tab-bar-history-current
(gethash (selected-frame) tab-bar-history-back))
tab-bar-history-back)
(set-window-configuration wc))
(set-window-configuration wc)
(when (and (markerp wc-point) (marker-buffer wc-point))
(goto-char wc-point)))
(message "No more tab forward history"))))
(define-minor-mode tab-bar-history-mode
@ -1000,10 +1057,9 @@ marked for deletion."
The list is displayed in a buffer named `*Tabs*'.
For more information, see the function `tab-bar-list'."
(let* ((tabs (delq nil (mapcar (lambda (tab) ; remove current tab
(unless (eq (car tab) 'current-tab)
tab))
(funcall tab-bar-tabs-function))))
(let* ((tabs (seq-remove (lambda (tab)
(eq (car tab) 'current-tab))
(funcall tab-bar-tabs-function)))
;; Sort by recency
(tabs (sort tabs (lambda (a b) (< (cdr (assq 'time b))
(cdr (assq 'time a)))))))