Làm cách nào để mở lại bộ đệm vừa bị giết, như CSt trong Firefox Browser?


35

Đôi khi, tôi vô tình giết một bộ đệm và muốn mở lại nó, giống như CSt để hoàn tác tab đã đóng trong Firefox, nhưng không có lệnh tích hợp nào trong Emacs, defun undo-kill-buffertrong http://www.emacswiki.org/RecentFiles :

(defun undo-kill-buffer (arg)
  "Re-open the last buffer killed.  With ARG, re-open the nth buffer."
  (interactive "p")
  (let ((recently-killed-list (copy-sequence recentf-list))
     (buffer-files-list
      (delq nil (mapcar (lambda (buf)
                  (when (buffer-file-name buf)
                (expand-file-name (buffer-file-name buf)))) (buffer-list)))))
    (mapc
     (lambda (buf-file)
       (setq recently-killed-list
         (delq buf-file recently-killed-list)))
     buffer-files-list)
    (find-file
     (if arg (nth arg recently-killed-list)
       (car recently-killed-list)))))

hoàn toàn không hoạt động. Nếu bạn biết elisp, làm thế nào để giải quyết vấn đề này?

Nếu nó có thể hiển thị một danh sách các bộ đệm đã đóng và chúng tôi có thể chọn một trong số chúng để mở lại, điều đó sẽ tốt hơn.


7
Không có câu trả lời nào được đưa ra cho đến nay trả lời cho câu hỏi như được đặt ra, đó là về "mở lại", hoặc khôi phục, một bộ đệm bị giết. Đó là bởi vì điều đó là khá nhiều không thể, nói chung - điều tốt nhất có thể được thực hiện là tạo lại nó. Nhưng nếu bạn có nghĩa là chỉ có bộ đệm truy cập tệp thì câu trả lời là dễ dàng và câu trả lời được đưa ra ở đây là phù hợp. Nếu đây là trường hợp thì xin vui lòng chỉnh sửa câu hỏi của bạn để phản ánh hạn chế này.
vẽ

2
Một cách tiếp cận khác là không giết những bộ đệm đó. chôn-đệm là tốt đẹp. Bạn cũng có thể tưởng tượng ra một cách tiếp cận fancier, ví dụ như một bộ đệm kill (chưa được xác định) sau này sẽ chôn bộ đệm ngay lập tức và thiết lập một bộ đếm thời gian để giết bộ đệm sau vài phút. Hoặc một bộ đệm-giết-có thể sẽ giết bộ đệm nếu nó truy cập một tệp và trì hoãn cái chết của nó nếu không (cũng có thể thêm một khoảng trắng vào tên của nó để tránh sự lộn xộn khi sử dụng Cx b).
YoungFrog

@YoungFrog, Chính xác, tôi đã giải quyết cơ hội này trong câu trả lời của mình.
Đánh dấu Karpov

Câu trả lời:


27

Đây là một cách khác, đơn giản thay thế mà không cần recentf. Việc nối hàm đầu tiên vào kill-buffer-hooksẽ đẩy tên tệp được liên kết với bộ đệm vào danh sách. (Lưu ý rằng, nếu bạn giết một bộ đệm không truy cập tệp, nó sẽ biến mất.) Hàm sau sẽ bật tệp đó ra khỏi danh sách và truy cập vào tệp:

(defvar killed-file-list nil
  "List of recently killed files.")

(defun add-file-to-killed-file-list ()
  "If buffer is associated with a file name, add that file to the
`killed-file-list' when killing the buffer."
  (when buffer-file-name
    (push buffer-file-name killed-file-list)))

(add-hook 'kill-buffer-hook #'add-file-to-killed-file-list)

(defun reopen-killed-file ()
  "Reopen the most recently killed file, if one exists."
  (interactive)
  (when killed-file-list
    (find-file (pop killed-file-list))))

Lưu ý rằng đó killed-file-listlà một danh sách, ví dụ, bạn có thể viết một hàm phức tạp hơn để chuyển qua danh sách đó, thay vì một danh sách đơn giản được mô tả ở đây: tùy thuộc vào mức độ bạn muốn làm với nó.

EDIT: xin lỗi, tôi đã bỏ lỡ điều khoản cuối cùng trong Q của bạn về việc muốn có một danh sách các tệp để chọn. Các chức năng sau đây hơi lạ hơn phiên bản trên trong chừng mực vì nó sử dụng completing-readđể cho phép bạn chỉ định tệp nào bị giết mà bạn muốn. Nếu bạn đang sử dụng một cái gì đó như ido, nó sẽ cho phép bạn duyệt qua tất cả các tệp bạn đã giết trong phiên hiện tại, mặc định là gần đây nhất. Lưu ý rằng nó giả định rằng bạn đã yêu cầu cl-lib:

(defun reopen-killed-file-fancy ()
  "Pick a file to revisit from a list of files killed during this
Emacs session."
  (interactive)
  (if killed-file-list
      (let ((file (completing-read "Reopen killed file: " killed-file-list
                                   nil nil nil nil (car killed-file-list))))
        (when file
          (setq killed-file-list (cl-delete file killed-file-list :test #'equal))
          (find-file file)))
    (error "No recently-killed files to reopen")))

5

Tôi muốn hỏi bạn: Bạn có thực sự muốn giết nó không? Thật vậy, giết một bộ đệm là một điều phổ biến trong thế giới Emacs, nhưng một khi đã bị giết, bộ đệm sẽ biến mất, và như câu hỏi của bạn chứng minh, không phải lúc nào cũng mong muốn.

Tuy nhiên, chúng ta có thể chọn một cách khác, để bạn không bao giờ cần khôi phục bộ đệm bị giết - chỉ thích chôn vùi hơn để giết. Hãy xem gói Kill hoặc Bury Alive , nó có sẵn thông qua MELPA .

Từ mô tả của gói:

Bạn đã bao giờ giết một số bộ đệm mà bạn có thể muốn để lại sống? Động lực cho việc giết chóc thường là ra khỏi đường của tôi cho đến bây giờ, và giết chóc có thể không phải là lựa chọn tốt nhất trong nhiều trường hợp trừ khi RAM của bạn rất hạn chế. Gói này cho phép dạy Emacs bộ đệm nào chúng ta muốn giết và cái nào chúng ta muốn chôn sống.

Khi chúng ta thực sự muốn giết một bộ đệm, hóa ra không phải tất cả các bộ đệm đều muốn chết theo cùng một cách. Gói cho phép chỉ định cách giết các loại bộ đệm khác nhau. Điều này có thể đặc biệt hữu ích khi bạn làm việc với một số bộ đệm có quy trình liên quan, ví dụ.

Nhưng đôi khi bạn có thể muốn thoát khỏi hầu hết các bộ đệm và đưa Emacs đến một số trạng thái trinh tiết ít nhiều. Bạn có thể không muốn giết bộ đệm đầu và có thể cả bộ đệm liên quan đến ERC. Bạn có thể chỉ định bộ đệm nào để thanh lọc.


4

Tôi sử dụng giải pháp này từ bài SO này và nó hoạt động tốt.

Giải pháp là thanh lịch nhưng không hoàn hảo; nó lưu trữ một danh sách các bộ đệm hoạt động và trả về tệp đầu tiên từ danh sách gần đây không thuộc danh sách các bộ đệm hoạt động.

;; Mở lại bộ đệm bị giết cuối cùng
;; Nguồn: https://stackoverflow.com/questions/10394213/emacs-reopen-preingly-kills-buffer
(yêu cầu 'cl)
(yêu cầu 'Recentf)
(chế độ gần đây 1)
(defun undo-kill-buffer ()
  (tương tác)
  (let ((tệp hoạt động (vòng lặp cho buf trong (danh sách bộ đệm)
                            khi (bộ đệm tên tệp buf) thu thập nó)))
    (vòng lặp cho tập tin trong danh sách Recentf
          trừ khi (tệp thành viên tệp hoạt động) trả về (tệp tìm tệp))))

3

Bạn cần bật recentf-mode. Để làm điều đó, chạy M-x recentf-mode. Sau đó, chức năng có thể không hoạt động cho đến khi bạn mở hoặc giết một số bộ đệm mới; Tôi không nghĩ bạn sẽ recentf-listđiền vào.

Nếu bạn muốn bật tính năng này khi Emacs khởi động, hãy đặt nó vào tệp init của bạn:

(recentf-mode)

Sau đó, bạn có thể đặt những defungì bạn tìm thấy trong đó và liên kết nó với một khóa, nếu bạn muốn.

Một nhược điểm của chế độ này dường như là chế độ Recentf được xây dựng để theo dõi openedcác tệp chứ không phải các tệp bị giết. Vì vậy, nếu bạn chạy chức năng hai lần, nó sẽ không mở lại tệp bị giết gần đây thứ hai của bạn.


4
Mặc dù Emacs 24 thực hiện tùy chọn này một cách hiệu quả cho các chế độ nhỏ, tôi vẫn có xu hướng viết (recentf-mode 1)với đối số rõ ràng, để ai đó đánh giá lại tệp init của họ trong Emacs 23 không kết thúc việc tắt chế độ.
phils

1

ErgoEmacs có một chức năng close-current-bufferđặc biệt giữ một danh sách các bộ đệm đã đóng gần đây:

(defvar recently-closed-buffers (cons nil nil) "A list of recently closed buffers. The max number to track is controlled by the variable recently-closed-buffers-max.")
(defvar recently-closed-buffers-max 10 "The maximum length for recently-closed-buffers.")

(defun close-current-buffer ()
"Close the current buffer.

Similar to (kill-buffer (current-buffer)) with the following addition:

• prompt user to save if the buffer has been modified even if the buffer is not associated with a file.
• make sure the buffer shown after closing is a user buffer.
• if the buffer is a file, add the path to the list recently-closed-buffers.

A emacs buffer is one who's name starts with *.
Else it is a user buffer."
 (interactive)
 (let (emacsBuff-p isEmacsBufferAfter)
   (if (string-match "^*" (buffer-name))
       (setq emacsBuff-p t)
     (setq emacsBuff-p nil))

   ;; offer to save buffers that are non-empty and modified, even for non-file visiting buffer. (because kill-buffer does not offer to save buffers that are not associated with files)
   (when (and (buffer-modified-p)
              (not emacsBuff-p)
              (not (string-equal major-mode "dired-mode"))
              (if (equal (buffer-file-name) nil) 
                  (if (string-equal "" (save-restriction (widen) (buffer-string))) nil t)
                t
                )
              )
     ;; (progn ;; I'VE ADDED THIS LINE
     ;;   (switch-to-buffer (buffer-name)) ;; AND THIS LINE
     (if (y-or-n-p
          (concat "Buffer " (buffer-name) " modified; Do you want to save?"))
         (save-buffer)
       (set-buffer-modified-p nil))
     ;; ) ;; AND ALSO A PARENTHESIS HERE
     )

   ;; save to a list of closed buffer
   (when (not (equal buffer-file-name nil))
     (setq recently-closed-buffers
           (cons (cons (buffer-name) (buffer-file-name)) recently-closed-buffers))
     (when (> (length recently-closed-buffers) recently-closed-buffers-max)
           (setq recently-closed-buffers (butlast recently-closed-buffers 1))
           )
     )

   ;; close
   (kill-buffer (current-buffer))

   ;; if emacs buffer, switch to a user buffer
   (if (string-match "^*" (buffer-name))
       (setq isEmacsBufferAfter t)
     (setq isEmacsBufferAfter nil))
   (when isEmacsBufferAfter
     (next-user-buffer)
     )
   )
 )

Vì vậy, bằng cách sử dụng một trong những có thể mở lại bộ đệm đóng phiên này với

;; undo close this-session buffer:
(defun ergo-undo-close-buffer ()
  "Opens some this-session closed buffer."
  (interactive)
  (let* ((mylist (delq nil (delete-dups (mapcar 'car recently-closed-buffers))))
         (baseName (ido-completing-read "Open this session closed buffer: " mylist))
         (fileName (cdr (assoc baseName recently-closed-buffers))))
    (find-file fileName)))

1

EDIT: Tôi đã không chú ý khi trả lời, và đã trả lời những điều khác mà OP không hỏi. Một lần nữa, tôi xin lỗi. Cảm ơn lời nói của bạn, @CodyChan.

Chà, tôi không phải là cựu chiến binh Emacs, và có lẽ điều này có thể đã trở nên có sẵn chỉ trên các phiên bản gần đây. Tôi biết rằng tôi sẽ đến một vài năm sau đó, nhưng có lẽ nó có thể hữu ích cho những người khác, vì tìm kiếm của tôi đã đưa tôi đến đây.

Tôi đang sử dụng Emacs v25.2.1, recentfđã có sẵn ở đây và có chức năng sẵn sàng thực hiện những gì bạn cần. Tôi đã kích hoạt nó trong quá khứ trên các phiên bản cũ hơn, vì vậy tôi .emacscó:

(recentf-mode 1)
(global-set-key (kbd "C-S-t") 'recentf-open-most-recent-file)

Và điều này làm việc hoàn hảo cho tôi. Tất nhiên, thay đổi phím tắt cho bất cứ điều gì làm bạn hài lòng hơn.


2
Có vẻ như chức năng này đã tồn tại từ lâu, đó là năm 2005 theo tệp ChangeLog trong cây mã nguồn Emacs. Nó hoạt động và thậm chí có thể hoạt động để mở lại bộ đệm đã đóng từ phiên Emacs trước đó, nhưng có vẻ như nó không thể liệt kê các bộ đệm đã đóng để cho tôi chọn một bộ đệm từ danh sách.
CodyChan

2
Vì vậy, nó không mở lại bộ đệm bị giết cụ thể mà mở lại các tệp đã mở gần đây.
CodyChan

@CodyChan, tôi rất xin lỗi và tất nhiên là bạn đúng. Đó sẽ là tệp được mở gần đây và không phải là những gì bạn đã hỏi. Tôi sẽ xóa câu trả lời sớm, tôi xin lỗi bạn và những người bạn khác.
Charles Roberto Canato

3
Không cần thiết phải xóa câu trả lời này, có thể ai đó chỉ muốn giải pháp của bạn chỉ đơn giản là mở lại các tệp đã mở gần đây. :)
CodyChan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.