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:
parent
d3517de4b4
commit
d7f62ce0cd
2 changed files with 95 additions and 37 deletions
|
|
@ -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")))
|
||||
|
|
|
|||
120
lisp/tab-bar.el
120
lisp/tab-bar.el
|
|
@ -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)))))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue