Long ago, I added a key to Emacs to quickly close a buffer. I used to use Alt+F3, because that's what I used with Turbo Pascal. These days I use Cmd+W to match the Macintosh key for closing windows. The trouble is that when it's easy to close buffers, I do it often, and I occasionally close a buffer I shouldn't have closed. The solution is to make Emacs ask me for confirmation if the buffer hasn't been saved.

In both GNU Emacs and XEmacs, the answer is in a variable named kill-buffer-query-functions:

kill-buffer-query-functions is a variable defined 
in `C source code'.

Documentation:
List of functions called with no args to query before 
killing a buffer. The buffer being killed will be current 
while the functions are running. If any of them returns nil,
the buffer is not killed.

Emacs will call each function listed in kill-buffer-query-functions before killing a buffer. If any of these functions returns nil, Emacs will not kill the buffer. So I defined a function that would ask for confirmation if the buffer hadn't been saved:

(defun ask-before-killing-buffer ()
  (cond
   ((and buffer-file-name (buffer-modified-p))
    (y-or-n-p (format "Buffer %s modified; kill anyway? " 
                  (buffer-name))))
   (t t)))
(add-to-list 'kill-buffer-query-functions 
             'ask-before-killing-buffer)

I then extended this function to not kill the *scratch* buffer, and ask for confirmation before killing shell buffers that have an active process:

(defun ask-before-killing-buffer ()
  (let ((buffer (current-buffer)))
    (cond
     ((equal (buffer-name) "*scratch*")
      ;; Never kill *scratch*
      nil)
     ((and buffer-file-name (buffer-modified-p))
      ;; If there's a file associated with the buffer, 
      ;; make sure it's saved
      (y-or-n-p (format "Buffer %s modified; kill anyway? " 
                    (buffer-name))))
     ((get-buffer-process buffer)
      ;; If there's a process associated with the buffer, 
      ;; make sure it's dead
      (y-or-n-p (format "Process %s active; kill anyway? "
                    (process-name (get-buffer-process buffer)))))
     (t t))))
(add-to-list 'kill-buffer-query-functions 
             'ask-before-killing-buffer)

The ironic thing is that since I wrote that function, I haven't accidentally tried to close a buffer...

Labels:

2 comments:

Amit wrote at Sunday, April 22, 2007 at 9:00:00 AM PDT

I should note that sometimes I get asked twice if I want to kill a buffer and I haven't figured out why.

Alok wrote at Wednesday, April 25, 2007 at 6:31:00 AM PDT

>I should note that sometimes I get asked twice if I want to kill a buffer and I haven't figured out why.

Must be related to why at the end of the Snake game in Emacs you get two buffers with the score tables.