window configuration 无法恢复已经被 killed 的 buffer

如题,window configuration 很好用,但其痛点是:当window中的原始buffer被killed掉时,便无法恢复到保存时的那个buffer。对于绑定到文件的buffer来说,无论是否被kill,能够随着window布局一起恢复是个很实用的需求。这样每次重新打开emacs,都能快速进入上一次的工作现场。

不知道有没有道友知道现成的 package 或方案?没有话,我就要自己实现一个了。

可以试试 activities.

1 个赞

这个package可以的,多谢。

如果想要window layout和file的绑定,那只能是往一个给定的window layout里面去填装file buffer,仅此而已。第一步,遍历window-list,把每个window的位置参数和buffer-file-name作为成员的属性构建一个window列表。第二步,实现一个restore函数,读取列表并恢复原窗口布局,打开文件,挂到emacs-startup-hook

以下是chat的实现,看上去问题不大:

(defun get-windows-position-and-size ()
  "Return a list of positions and file paths of all windows in the current frame."
  (let ((window-data '()))
    (dolist (window (window-list))
      (when (window-live-p window)
        (let* ((edges (window-edges window))
               (left (nth 0 edges))
               (top (nth 1 edges))
               (width (nth 2 edges))
               (height (nth 3 edges))
               (buffer (window-buffer window))
               (file-path (buffer-file-name buffer)))  ;; Get full file path
          ;; Store the position, size, and file path as an alist for each window
          (push (list :file-path file-path :left left :top top :width width :height height) window-data))))
    ;; Reverse the list since we used `push`
    (reverse window-data)))

(defun recover-windows-from-data (window-data)
  "Recover windows according to WINDOW-DATA, which is a list of alists.
Each element of WINDOW-DATA should be an alist with :file-path, :left,
:top, :width, and :height entries."
  (let ((current-window (selected-window)))
    (delete-other-windows)  ;; Start with a single window
    (let ((frame (selected-frame))) ;; Get the current frame to set position
      (dolist (data window-data)
        (let ((file-path (plist-get data :file-path))
              (left (plist-get data :left))
              (top (plist-get data :top))
              (width (plist-get data :width))
              (height (plist-get data :height)))
          (let ((new-window (split-window current-window)))
            (with-selected-window new-window
              (if (file-exists-p file-path)  ;; Check if the file exists
                  (let ((buffer (find-file-noselect file-path)))  ;; Open the file without selecting it
                    (set-window-buffer new-window buffer)
                    ;; Resize window to specified height
                    (resize-window height t)
                    ;; Set window width (optional)
                    (let ((new-width width))
                      (if (> new-width (frame-width))
                          (setq new-width (frame-width))) ;; Prevent exceeding frame width
                      (if (> new-width 0)
                          (enlarge-window new-width nil))))
                ;; If the file doesn't exist, show error message
                (let ((error-buffer (generate-new-buffer "*Error File Not Found*")))
                  (with-current-buffer error-buffer
                    (insert (format "Error: The file '%s' does not exist." file-path))
                    (insert "\n\nPlease check the file path.")
                    (goto-char (point-min)))  ;; Move to the beginning of the buffer
                  (set-window-buffer new-window error-buffer)  ;; Show the error buffer
                  ;; Resize window to specified height, if needed
                  (resize-window height t)
                  ;; Set window width (optional)
                  (let ((new-width width))
                    (if (> new-width (frame-width))
                        (setq new-width (frame-width))) ;; Prevent exceeding frame width
                    (if (> new-width 0)
                        (enlarge-window new-width nil)))))))
          ;; Optional: Adjust the position
          (set-frame-position frame left top))))
      (setq current-window (next-window current-window)))))  ;; Move to the next window
1 个赞

试试workgroups2.

1 个赞

workgroups2更简单好用,3q ~

1 个赞