]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/tab-bar.el: Store point position and frame buffer-lists in tab.
authorJuri Linkov <juri@linkov.net>
Tue, 29 Oct 2019 22:31:11 +0000 (00:31 +0200)
committerJuri Linkov <juri@linkov.net>
Tue, 29 Oct 2019 22:31:11 +0000 (00:31 +0200)
* 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.

lisp/emacs-lisp/seq.el
lisp/tab-bar.el

index 9a5872c094b01feabf925e783eb7c4a9fe5dd729..810b4792b2b30816bd002da6485968ac2e5c157f 100644 (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")))
index c4763337a2502accfeb9c4384d7921ec46748669..c9829e94ff4b4d9d4ef94d160ff79090258b278c 100644 (file)
@@ -438,7 +438,9 @@ Return its existing value or a new value."
 \f
 (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)
+        (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)
-          (if ws (window-state-put ws (frame-root-window (selected-frame))
-                                   'safe)))
+
+            ;; 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))))
+
+            (puthash (selected-frame)
+                     (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 (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)
-        (puthash (selected-frame)
-                 (and (window-configuration-p (car history-back)) history-back)
-                 tab-bar-history-back)
-        (puthash (selected-frame)
-                 (and (window-configuration-p (car history-forward)) history-forward)
-                 tab-bar-history-forward)
 
         (when from-index
           (setf (nth from-index tabs) from-tab))
@@ -861,6 +902,9 @@ function `tab-bar-tab-name-function'."
 \f
 ;;; 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,52 +914,65 @@ 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)
-                   (gethash (selected-frame) tab-bar-history-back))
-            tab-bar-history-back))
+             (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)))
 
 (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))
+                   tab-bar-history-forward)
+          (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))
+                   tab-bar-history-back)
+          (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)))))))