¿Cómo volver a abrir el búfer recién apagado, como CSt en el navegador Firefox?

35

A veces, accidentalmente mato un búfer y quiero volver a abrirlo, al igual que CSt para deshacer la pestaña cerrada en Firefox, pero no hay un comando incorporado en Emacs, defun undo-kill-bufferen 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)))))

no funciona en absoluto Si conoce elisp, ¿cómo resolver este problema?

Si puede mostrar una lista de los buffers cerrados y puedo elegir uno de ellos para reabrir, sería mejor.

CodyChan
fuente
77
Ninguna de las respuestas dadas hasta ahora responde a la pregunta planteada, que se trata de "reabrir" o restaurar un búfer muerto. Eso es porque eso es prácticamente imposible, en general: lo mejor que se podría hacer sería volver a crearlo. Pero si se refiere solo a los buffers de visita de archivos, entonces la respuesta es fácil, y las respuestas que se dan aquí son apropiadas. Si este es el caso , edite su pregunta para reflejar esta restricción.
Dibujó el
2
Un enfoque alternativo es no matar esos búferes. Bury-buffer es agradable. También podría imaginar un enfoque más elegante, por ejemplo, un (aún por definir) kill-buffer-later que enterraría el buffer inmediatamente y configuraría un temporizador para matar el buffer después de unos minutos. O un kill-buffer-maybe-later que mataría al buffer si está visitando un archivo, y retrasaría su muerte si no lo está (quizás también anteponga un espacio a su nombre para evitar el desorden cuando se usa Cx b).
YoungFrog
@YoungFrog, exactamente, he abordado esta oportunidad en mi respuesta.
Mark Karpov

Respuestas:

27

Aquí hay otra alternativa simple que no requiere recentf. Conectando la primera función kill-buffer-hookempujará el nombre de archivo asociado con el búfer a una lista. (Tenga en cuenta que, si elimina un búfer que no está visitando un archivo, se ha ido para siempre). La última función saca ese archivo de la lista y lo visita:

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

Tenga en cuenta que killed-file-listes una lista, por lo que podría, por ejemplo, escribir una función más compleja para recorrer esa lista, en lugar de la simple que se describe aquí: depende de usted cuánto desea hacer con ella.

EDITAR: lo siento, me perdí la última disposición en su Q sobre querer una lista de archivos para elegir. La siguiente función es un poco más elegante que la versión anterior en la medida en que se utiliza completing-readpara permitirle especificar cuál de los archivos eliminados desea. Si está utilizando algo como esto ido, le permitirá recorrer todos los archivos que ha eliminado en la sesión actual, por defecto al más reciente. Tenga en cuenta que supone que ya ha requerido 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")))
Dan
fuente
5

Me gustaría preguntarte: "¿De verdad quieres matarlo?". De hecho, matar un búfer es algo muy común en el mundo de Emacs, pero una vez muerto, el búfer desaparece y, como lo demuestra su pregunta, no siempre es deseable.

Sin embargo, podemos elegir otra forma, de modo que nunca necesite restaurar el búfer muerto, solo prefiera enterrar a matar. Eche un vistazo al paquete Kill o Bury Alive , está disponible a través de MELPA .

De la descripción del paquete:

¿Alguna vez has matado algún búfer que quieras dejar con vida? La motivación para matar suele ser "salir de mi camino por ahora", y matar puede no ser la mejor opción en muchos casos a menos que su RAM sea muy, muy limitada. Este paquete permite enseñarle a Emacs qué buffers queremos matar y cuáles preferimos enterrar vivos.

Cuando realmente queremos matar un búfer, resulta que no a todos los búferes les gustaría morir de la misma manera. El paquete permite especificar cómo matar varios tipos de buffers. Esto puede ser especialmente útil cuando trabajas con algún búfer que tiene un proceso asociado, por ejemplo.

Pero a veces es posible que desee deshacerse de la mayoría de los amortiguadores y llevar Emacs a un estado más o menos virgen. Probablemente no desee eliminar el búfer de memoria virtual y quizás también los búferes relacionados con ERC. Puede especificar qué búferes purgar.

Mark Karpov
fuente
4

Utilizo esta solución de esta publicación SO y funciona bien.

La solución es elegante pero no perfecta; almacena una lista de buffers activos y devuelve el primer archivo de la listaf reciente que no pertenece a la lista de buffers activos.

;; Vuelva a abrir el último búfer muerto
;; Fuente: https://stackoverflow.com/questions/10394213/emacs-reopen-previous-killed-buffer
(requiere 'cl)
(requiere 'recientef)
(reciente-modo 1)
(defundo deshacer-matar-buffer ()
  (interactivo)
  (let ((active-files (loop for buf in (buffer-list))
                            cuando (buffer-file-name buf) recógelo)))
    (bucle para archivo en lista -f reciente
          a menos que (archivo miembro active-files) devuelva (find-file file))))
Kaushal Modi
fuente
3

Necesitas encenderlo recentf-mode. Para hacer eso, corre M-x recentf-mode. Entonces, la función podría no funcionar hasta que abra o elimine algunos buffers nuevos; No creo que lo hayas recentf-listcompletado.

Si desea que esto esté habilitado cuando se inicie Emacs, colóquelo en su archivo de inicio:

(recentf-mode)

Luego puede poner el defunque encontró allí y vincularlo a una clave, si lo desea.

Una desventaja de este modo parece ser que el modo reciente está diseñado para rastrear openedarchivos, no archivos matados. Entonces, si ejecuta la función dos veces, no volverá a abrir su segundo archivo eliminado más recientemente.

zck
fuente
44
Aunque Emacs 24 efectivamente hizo esto opcional para modos menores, todavía me inclinaría a escribir (recentf-mode 1)con el argumento explícito, de modo que alguien que reevalúe su archivo de inicio en Emacs 23 no termine desactivando el modo nuevamente.
phils
1

ErgoEmacs tiene una función close-current-bufferque en particular mantiene una lista de buffers cerrados recientemente:

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

Por lo tanto, usar estos puede volver a abrir este búfer cerrado de sesión con

;; 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)))
Adobe
fuente
1

EDITAR: No presté atención al responder, y respondí algo más que el OP no preguntó. Una vez más, lo siento. Gracias por tus palabras, @CodyChan.

Bueno, no soy un veterano de Emacs, y tal vez esto posiblemente esté disponible solo en versiones recientes. Sé que vendré algunos años después, pero tal vez pueda ser útil para otros, ya que mi búsqueda me trajo aquí.

Estoy en Emacs v25.2.1, recentfya está disponible aquí y tiene una función lista que hace lo que necesita. Ya lo activé en el pasado en versiones anteriores, así que .emacstengo:

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

Y esto funcionó perfectamente para mí. Por supuesto, cambie el atajo para lo que más le agrade.

Charles Roberto Canato
fuente
2
Parece que la función ya existía hace mucho tiempo, que es 2005 según el archivo ChangeLog en el árbol de código fuente de Emacs. Funciona, e incluso puede funcionar para volver a abrir el búfer cerrado de la sesión anterior de Emacs, pero parece que no puede enumerar los búferes cerrados para permitirme elegir uno de la lista.
CodyChan
2
Por lo tanto, no vuelve a abrir solo el búfer apagado específicamente, sino que vuelve a abrir los archivos abiertos recientemente.
CodyChan
@CodyChan, lo siento mucho y, por supuesto, tienes razón. Ese sería el archivo abierto más recientemente y no lo que has pedido. Eliminaré la respuesta pronto, me disculpo contigo y con otros compañeros.
Charles Roberto Canato
3
Innecesariamente para eliminar esta respuesta, tal vez alguien solo quiera que su solución simplemente vuelva a abrir los archivos abiertos recientemente. :)
CodyChan