FirefoxブラウザのCStのように、強制終了したバッファを再度開く方法は?


35

Firefoxで閉じたタブを元に戻すCStのように、誤ってバッファを強制的に削除して開き直したい場合がありますが、Emacsには組み込みコマンドがないdefun undo-kill-bufferhttp://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)))))

まったく機能しません。elispを知っているなら、この問題を解決する方法は?

閉じたバッファとそれらのリストを表示できる場合は、それらの中から1つを選択して再度開くことができます。


7
これまでに与えられた答えはどれも、提示された質問に応答しません。これは、強制終了したバッファを「再開」または復元することです。それは、一般に、それがほとんど不可能だからです。できることは、それを再作成することです。しかし、ファイルを訪問するバッファのみを意味する場合、答えは簡単であり、ここで与えられる答えは適切です。この場合、質問編集してこの制限を反映してください
ドリュー

2
別のアプローチは、これらのバッファーを強制終了しないことです。bury-bufferはいいですね。また、すぐにバッファを埋め、数分後にバッファを強制終了するタイマーを設定する(まだ定義されていない)kill-buffer-laterなどの、より手の込んだアプローチを想像することもできます。または、ファイルを訪問している場合はバッファを強制終了し、そうでない場合はその終了を遅らせるkill-buffer-maybe-later(Cx bを使用するときの混乱を避けるために名前にスペースを追加することもできます)。
YoungFrog

@YoungFrog、まさに、私は答えでこの機会に対処しました。
マークカルポフ

回答:


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の世界ではバッファーを殺すのはとても一般的なことですが、一度殺すとバッファーがなくなるので、あなたの質問が示すように、それは必ずしも望ましいとは限りません。

ただし、別の方法を選択することもできます。そのため、キルされたバッファを復元する必要はありません。キルするよりも埋めることを好むだけです。KillまたはBury Aliveパッケージを見 てください。これはMELPAから入手できます

パッケージの説明から:

生き残らせたいバッファを殺したことがありますか?殺害の動機は通常「今のところ邪魔にならない」ことであり、RAMが非常に制限されていない限り、殺害は多くの場合最良の選択ではないかもしれません。このパッケージを使用すると、Emacsにどのバッファーを削除するか、どのバッファーを生きた状態に埋めたいかを教えることができます。

本当にバッファを殺したいとき、すべてのバッファが同じように死にたいわけではないことがわかります。このパッケージでは、さまざまな種類のバッファーを強制終了する方法を指定できます。これは、たとえば、関連付けられたプロセスを持つバッファーを使用している場合に特に便利です。

しかし、ほとんどのバッファを取り除き、Emacsを多少なりとも新しい状態にしたい場合があります。おそらく、スクラッチバッファーやおそらくERC関連のバッファーも削除したくないでしょう。削除するバッファを指定できます。


4

私はこのSO投稿からこのソリューションを使用し、うまく機能しています。

ソリューションはエレガントですが、完璧ではありません。アクティブなバッファのリストを保存し、アクティブなバッファのリストに属していないrecentf-listの最初のファイルを返します。

;; 最後に強制終了したバッファーを再度開きます
;; ソース:https://stackoverflow.com/questions/10394213/emacs-reopen-previous-killed-buffer
( 'clが必要)
( 'recentfが必要)
(recentfモード1)
(defun undo-kill-buffer()
  (インタラクティブ)
  (let((active-files(loop for buf in(buffer-list)
                            when(buffer-file-name buf)collect it)))
    (recentf-list内のファイルのループ
          (メンバーファイルアクティブファイル)リターン(ファイル検索ファイル))))を除いて

3

電源を入れる必要がありrecentf-modeます。それを行うには、を実行しM-x recentf-modeます。その後、新しいバッファーを開くか強制終了するまで、関数は機能しない可能性があります。あなたがrecentf-list記入したとは思わない。

Emacsの起動時にこれを有効にしたい場合は、これをinitファイルに入れてください:

(recentf-mode)

その後、defun見つけたものをそこに置き、必要に応じてキーにバインドできます。

このモードの欠点の1つは、recentfモードが、強制終了されたopenedファイルではなく、ファイルを追跡するために構築されていることです。そのため、関数を2回実行しても、最後から2番目に削除されたファイルは開きません。


4
Emacs 24はこれをマイナーモードでは事実上オプションにしました(recentf-mode 1)が、Emacs 23でinitファイルを再評価する人がモードを再びオフに切り替えないように、明示的な引数で記述したいと思っています。
フィル14年

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
EmacsソースコードツリーのChangeLogファイルによると、この機能は2005年にすでに存在していたようです。それは機能し、以前のEmacsセッションからクローズドバッファを再度開くことさえできますが、リストから1つを選択するためにクローズドバッファをリストできないようです。
コディチャン

2
そのため、強制終了したバッファだけを再度開くのではなく、最近開いたファイルを再度開きます。
CodyChan

@CodyChan、すみません、もちろんあなたは正しいです。それは最近開いたファイルであり、あなたが尋ねたものではないでしょう。すぐに答えを削除します、あなたと他の仲間に謝罪します。
チャールズロベルトカナト

3
この回答を不必要に削除するために、誰かがあなたのソリューションに最近開いたファイルを単純に再度開きたいだけかもしれません。:)
CodyChan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.