วิธีการเปิดบัฟเฟอร์ที่ถูกฆ่าอีกครั้งเช่น CSt ใน Firefox Browser ได้อย่างไร


35

บางครั้งฉันตั้งใจฆ่าบัฟเฟอร์และต้องการเปิดใหม่เช่นเดียวกับ CSt เพื่อเลิกทำการปิดแท็บใน Firefox แต่ไม่มีคำสั่งในตัวใน Emacs defun undo-kill-bufferใน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)))))

ไม่ทำงานเลย หากคุณรู้จักเอลลิสวิธีแก้ปัญหานี้?

หากมันสามารถแสดงรายการของบัฟเฟอร์ปิดและพวกเขาฉันสามารถเลือกหนึ่งจากพวกเขาเพื่อเปิดอีกครั้งนั่นจะดีกว่า


7
ไม่มีคำตอบใดที่ตอบสนองต่อคำถามที่ถูกวางซึ่งเกี่ยวกับ "การเปิดใหม่" หรือการกู้คืนบัฟเฟอร์ที่ถูกฆ่า นั่นเป็นเพราะมันเป็นไปไม่ได้เลยทีเดียวโดยทั่วไปสิ่งที่ดีที่สุดที่สามารถทำได้คือการสร้างมันขึ้นมาใหม่ แต่ถ้าคุณหมายถึงบัฟเฟอร์การเยี่ยมไฟล์เท่านั้นคำตอบนั้นง่ายและคำตอบที่ให้ไว้ที่นี่เหมาะสม หากเป็นกรณีนี้โปรดแก้ไขคำถามของคุณเพื่อแสดงถึงข้อ จำกัด นี้
Drew

2
วิธีอื่นคือไม่ฆ่าบัฟเฟอร์เหล่านั้น บัฟเฟอร์ฝังเป็นสิ่งที่ดี คุณสามารถจินตนาการถึงวิธีที่นักเล่นเช่น (ยังไม่ได้กำหนด) kill-buffer-ภายหลังซึ่งจะทำการฝังบัฟเฟอร์ในทันทีและตั้งค่าตัวจับเวลาเพื่อฆ่าบัฟเฟอร์หลังจากนั้นไม่กี่นาที หรือ kill-buffer-บางที - ในภายหลังซึ่งจะฆ่าบัฟเฟอร์ถ้ามันกำลังเยี่ยมชมไฟล์และชะลอการตายถ้ามันไม่ (อาจเตรียมช่องว่างที่ชื่อของมันเพื่อหลีกเลี่ยงความยุ่งเหยิงเมื่อใช้ Cx b)
YoungFrog

@ YoungFrog แน่นอนว่าฉันได้พูดถึงโอกาสนี้ในคำตอบแล้ว
Mark Karpov

คำตอบ:


27

recentfนี่เป็นอีกหนึ่งทางเลือกที่ง่ายที่ไม่ต้องใช้ การขอฟังก์ชั่นแรกเข้าkill-buffer-hookจะผลักชื่อไฟล์ที่เกี่ยวข้องกับบัฟเฟอร์ไปยังรายการ (โปรดทราบว่าหากคุณฆ่าบัฟเฟอร์ที่ไม่ได้เยี่ยมชมไฟล์มันก็หายดี) ฟังก์ชั่นหลังจะเปิดไฟล์นั้นออกจากรายการและเข้าชม:

(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))))

โปรดทราบว่าkilled-file-listเป็นรายการดังนั้นคุณสามารถเขียนฟังก์ชันที่สลับซับซ้อนมากขึ้นเพื่อวนรอบรายการนั้นแทนที่จะเป็นรายการง่าย ๆ ที่อธิบายไว้ที่นี่: ขึ้นอยู่กับคุณว่าคุณต้องการทำอะไร

แก้ไข:ขอโทษฉันพลาดบทบัญญัติสุดท้ายใน Q ของคุณเกี่ยวกับการต้องการรายชื่อไฟล์ที่จะเลือก ฟังก์ชั่นต่อไปนี้น่ากลัวกว่ารุ่นด้านบนเล็กน้อยเท่าที่มันใช้completing-readเพื่อให้คุณระบุไฟล์ที่ถูกฆ่าที่คุณต้องการ หากคุณกำลังใช้บางสิ่งบางอย่างidoมันจะช่วยให้คุณหมุนเวียนไฟล์ทั้งหมดที่คุณฆ่าในเซสชันปัจจุบันโดยเริ่มต้นเป็นไฟล์ล่าสุด โปรดทราบว่ามันขึ้นอยู่กับว่าคุณต้องการ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

ฉันอยากจะถามคุณว่า:“ คุณต้องการจะฆ่ามันจริงๆเหรอ?” อันที่จริงการฆ่าบัฟเฟอร์เป็นสิ่งที่พบเห็นได้ทั่วไปในโลกของ Emacs แต่เมื่อฆ่าแล้วบัฟเฟอร์จะหายไปและเมื่อคำถามของคุณแสดงให้เห็น

อย่างไรก็ตามเราสามารถเลือกวิธีอื่นเพื่อให้คุณไม่จำเป็นต้องกู้คืนบัฟเฟอร์ที่ฆ่า - เพียงแค่ต้องการฝังเพื่อฆ่า ลองดูที่ ฆ่าหรือบิวรี่ยังมีชีวิตอยู่ในแพคเกจก็สามารถใช้ได้ผ่านทาง MELPA

จากคำอธิบายของแพคเกจ:

คุณเคยฆ่าบัฟเฟอร์บางอย่างที่คุณอาจต้องการให้มีชีวิตอยู่หรือไม่? แรงจูงใจในการฆ่ามักจะ“ หนีไปก่อนแล้ว” และการฆ่าอาจไม่ใช่ตัวเลือกที่ดีที่สุดในหลาย ๆ กรณียกเว้นว่า RAM ของคุณมีข้อ จำกัด มาก แพ็คเกจนี้ช่วยสอน Emacs ที่เราต้องการฆ่าและบัฟเฟอร์ที่เราต้องการฝังมีชีวิตอยู่

เมื่อเราต้องการฆ่าบัฟเฟอร์มันปรากฎว่าบัฟเฟอร์ทั้งหมดไม่ต้องการตายในลักษณะเดียวกัน แพคเกจอนุญาตให้ระบุวิธีการฆ่าบัฟเฟอร์ชนิดต่าง ๆ สิ่งนี้อาจมีประโยชน์อย่างยิ่งเมื่อคุณทำงานกับบัฟเฟอร์บางอย่างที่มีกระบวนการเกี่ยวข้องเช่น

แต่บางครั้งคุณอาจต้องการกำจัดบัฟเฟอร์ส่วนใหญ่และนำ Emacs ไปสู่สถานะบริสุทธิ์มากขึ้นหรือน้อยลง คุณอาจไม่ต้องการที่จะฆ่า scratch buffer และอาจจะเป็นบัฟเฟอร์ที่เกี่ยวข้องกับ ERC ด้วย คุณสามารถระบุบัฟเฟอร์ที่จะกำจัด


4

ฉันใช้โซลูชันนี้จากโพสต์ SO นี้และใช้งานได้ดี

วิธีการแก้ปัญหานั้นสวยงาม แต่ไม่สมบูรณ์แบบ; มันเก็บรายชื่อของบัฟเฟอร์ที่ใช้งานและส่งกลับไฟล์แรกจากรายการล่าสุด f- ที่ไม่ได้อยู่ในรายการของบัฟเฟอร์ที่ใช้งาน

;; เปิดบัฟเฟอร์ที่ถูกฆ่าครั้งล่าสุดอีกครั้ง
;; ที่มา: https://stackoverflow.com/questions/10394213/emacs-reopen-previous-killed-buffer
(ต้องการ 'cl)
(ต้องการ 'recentf)
(โหมด f ล่าสุด 1)
(กำหนดค่าเลิกทำเลิกฆ่าบัฟเฟอร์) ()
  (interactive)
  (ให้ ((ไฟล์ที่ใช้งานอยู่ (วนรอบสำหรับ buf ใน (บัฟเฟอร์รายการ)
                            เมื่อ (บัฟเฟอร์ชื่อไฟล์ buf) รวบรวมมัน))
    (วนซ้ำสำหรับไฟล์ในล่าสุด f-list
          เว้นแต่ (ไฟล์สมาชิกไฟล์ที่ใช้งาน) กลับมา (ไฟล์ค้นหาไฟล์)))

3

recentf-modeคุณจำเป็นต้องเปิด M-x recentf-modeต้องการทำเช่นนั้นวิ่ง จากนั้นฟังก์ชันอาจไม่ทำงานจนกว่าคุณจะเปิดหรือฆ่าบัฟเฟอร์ใหม่ ฉันไม่คิดว่าคุณจะต้องrecentf-listกรอก

หากคุณต้องการเปิดใช้งานสิ่งนี้เมื่อ Emacs เริ่มต้นให้ใส่นี่ในไฟล์ init ของคุณ:

(recentf-mode)

จากนั้นคุณสามารถวางสิ่งที่defunคุณพบในนั้นและผูกมันไว้กับกุญแจหากคุณต้องการ

ข้อเสียของโหมดนี้ดูเหมือนว่าโหมดล่าสุดจะถูกสร้างขึ้นเพื่อติดตามopenedไฟล์ไม่ใช่ไฟล์ที่ถูกฆ่า ดังนั้นหากคุณเรียกใช้ฟังก์ชั่นสองครั้งจะไม่เปิดไฟล์ที่ถูกฆ่าครั้งที่สองที่เพิ่งถูกเปิดใหม่อีกครั้ง


4
แม้ว่า Emacs 24 จะเลือกตัวเลือกนี้อย่างมีประสิทธิภาพสำหรับโหมดรอง แต่ฉันก็ยังอยากจะเขียน(recentf-mode 1)ด้วยอาร์กิวเมนต์ที่ชัดเจนเพื่อให้มีคนประเมินไฟล์ init ของพวกเขาภายใต้ Emacs 23 อีกครั้งไม่ได้จบการสลับโหมดอีกครั้ง
phils

1

ErgoEmacs มีฟังก์ชั่นclose-current-bufferซึ่งโดยเฉพาะอย่างยิ่งเก็บรายการบัฟเฟอร์ที่เพิ่งปิด:

(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)
     )
   )
 )

ดังนั้นการใช้สิ่งเหล่านี้สามารถเปิดเซสชั่นนี้ปิดบัฟเฟอร์ด้วย

;; 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

แก้ไข: ฉันไม่ได้ใส่ใจเมื่อตอบรับและตอบอย่างอื่นที่ OP ไม่ได้ถาม ฉันขอโทษอีกครั้ง ขอบคุณสำหรับคำพูดของคุณ @CodyChan

ฉันไม่ใช่ทหารผ่านศึกของ Emacs และอาจเป็นไปได้ว่ามีเฉพาะในเวอร์ชั่นล่าสุด ฉันรู้ว่าฉันจะมาอีกหลายปีต่อมา แต่อาจเป็นประโยชน์กับคนอื่น ๆ เนื่องจากการค้นหาของฉันทำให้ฉันมาที่นี่

ฉันใช้ Emacs v25.2.1 recentfมีอยู่แล้วที่นี่และมีฟังก์ชั่นพร้อมที่จะทำสิ่งที่คุณต้องการ ฉันเปิดใช้งานแล้วในอดีตกับรุ่นที่เก่ากว่าดังนั้นฉันจึง.emacsมี:

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

และสิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน แน่นอนเปลี่ยนทางลัดสำหรับสิ่งที่คุณพอใจมากขึ้น


2
ดูเหมือนว่าฟังก์ชันนี้มีมานานแล้วซึ่งก็คือปี 2005 ตามไฟล์ ChangeLog ในซอร์สโค้ด Emacs มันใช้งานได้และมันยังสามารถทำงานเพื่อเปิดบัฟเฟอร์ที่ปิดใหม่จากเซสชัน Emacs ก่อนหน้า แต่ดูเหมือนว่ามันจะไม่สามารถแสดงรายการบัฟเฟอร์ที่ปิดไว้เพื่อให้ฉันเลือกหนึ่งรายการจากรายการ
CodyChan

2
ดังนั้นจึงไม่ได้เปิดใหม่เพียงแค่ฆ่าบัฟเฟอร์โดยเฉพาะ แต่เปิดไฟล์ที่เพิ่งเปิดใหม่อีกครั้ง
CodyChan

@CodyChan ฉันเสียใจมากและแน่นอนว่าคุณพูดถูก นั่นเป็นไฟล์ที่เพิ่งเปิดใหม่ไม่ใช่สิ่งที่คุณถาม ฉันจะลบคำตอบในไม่ช้าฉันขอโทษคุณและเพื่อน ๆ
Charles Roberto Canato

3
ลบคำตอบนี้โดยไม่จำเป็นบางทีอาจมีคนต้องการให้โซลูชันของคุณเปิดไฟล์ที่เพิ่งเปิดใหม่อีกครั้ง :)
CodyChan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.