(defun my-kill () "Kill buffer, taking gnuclient into account." (interactive) (if (buffer-modified-p) (error "Buffer has unsaved changes") (if server-buffer-clients (server-edit) (kill-buffer (current-buffer)))))
I like this. It made me realise how cumbersome it is to have to hit enter and assume the default buffer using the normal kill buffer mechanism. I also think erroring out rather than prompting to save is a better user interface decision. CVS gnu emacs doesn’t seem to have some of the variables you are using, so here’s an alternative -- DamienElmes
(defun context-kill (arg) "Kill buffer, taking gnuclient into account." (interactive "p") (when (and (buffer-modified-p) (not (string-match "\\*.*\\*" (buffer-name))) (= 1 arg)) (if (y-or-n-p (format "<%s> is modified, save " (buffer-name))) (save-buffer))) (if (and (boundp 'gnuserv-minor-mode) gnuserv-minor-mode) (gnuserv-edit) (let ((buffer-modified-p nil)) (kill-buffer (current-buffer)))))
I was using this bound to C-x k but annoyed that I had to do C-u C-x k to kill unwanted modified buffers. So, I’ve added the prompt for saving. – LathI
This is the sort of thing DedicatedKeys tries to avoid - with a y-or-n prompt, it’s pretty easy to get into the habit of accidently hitting n when you want to close the buffer. The habit of hitting C-u C-x k to discard buffer contents is also habit forming, though. I think I really want a general purpose “KillKey” which automatically displays an electric diff and ask for confirmation. I might come back with something that does that at one point.. – DamienElmes
Here is a version that works on any buffer (not just the current one):
(defun query-kill-unconditionally (buf) (interactive "b") (set-buffer-modified-p nil) (kill-buffer buf))
On XEmacs21 and Emacs20, at least, buffer-modified-p is a function, not a variable. The following function works for me to kill a buffer unconditionally.
(defun lrd-kill-buffer-unconditionally (&optional buffer) (if (not buffer) (setq buffer (current-buffer))) (set-buffer-modified-p nil buffer) (kill-buffer buffer))
From there, it’s simple to apply the rest – LarryDaffner?
I use the following code (some of it modified from ibuffer.el) to display a diff of the buffer with its associated file when I try and kill a buffer that has unsaved changes. If I decide I don’t want the buffer anyway, hitting c-u <killkey> will kill the file unconditionally and also tidy up the diff buffer.
(defun diff-buffer-with-associated-file () "View the differences between BUFFER and its associated file. This requires the external program \"diff\" to be in your `exec-path'. Returns nil if no differences found, 't otherwise." (interactive) (let ((buf-filename buffer-file-name) (buffer (current-buffer))) (unless buf-filename (error "Buffer %s has no associated file" buffer)) (let ((diff-buf (get-buffer-create (concat "*Assoc file diff: " (buffer-name) "*")))) (with-current-buffer diff-buf (setq buffer-read-only nil) (erase-buffer)) (let ((tempfile (make-temp-file "buffer-to-file-diff-"))) (unwind-protect (progn (with-current-buffer buffer (write-region (point-min) (point-max) tempfile nil 'nomessage)) (if (zerop (apply #'call-process "diff" nil diff-buf nil (append (when (and (boundp 'ediff-custom-diff-options) (stringp ediff-custom-diff-options)) (list ediff-custom-diff-options)) (list buf-filename tempfile)))) (progn (message "No differences found") nil) (progn (with-current-buffer diff-buf (goto-char (point-min)) (if (fboundp 'diff-mode) (diff-mode) (fundamental-mode))) (display-buffer diff-buf) t))) (when (file-exists-p tempfile) (delete-file tempfile))))))) ;; tidy up diffs when closing the file (defun kill-associated-diff-buf () (let ((buf (get-buffer (concat "*Assoc file diff: " (buffer-name) "*")))) (when (bufferp buf) (kill-buffer buf)))) (add-hook 'kill-buffer-hook 'kill-associated-diff-buf) (global-set-key (kbd "C-c d") 'diff-buffer-with-associated-file) (defun de-context-kill (arg) "Kill buffer, taking gnuclient into account." (interactive "p") (when (and (buffer-modified-p) buffer-file-name (not (string-match "\\*.*\\*" (buffer-name))) ;; erc buffers will be automatically saved (not (eq major-mode 'erc-mode)) (= 1 arg)) (let ((differences 't)) (when (file-exists-p buffer-file-name) (setq differences (diff-buffer-with-associated-file))) (error (if differences "Buffer has unsaved changes" "Buffer has unsaved changes, but no differences wrt. the file")))) (if (and (boundp 'gnuserv-minor-mode) gnuserv-minor-mode) (gnuserv-edit) (set-buffer-modified-p nil) (kill-buffer (current-buffer)))) (global-set-key (kbd "C-x k") 'de-context-kill)
You’ll probably want to do
(setq ediff-custom-diff-options "-u") at least. --MikaelBrockman
I’ve put that in a file and munged it to work with XEmacs – should I upload, or send to you, or…? (I’m not clear on what the license situation is…) --JohnAnderson
in case of “No differences found”, diff-buffer-with-associated-file calls message, but the output is immediately overwritten. I find that confusing. Either i should see the 2 lines of messages, or … i applied my modification. --Mmc
I have some code in e-functions.el at http://emacro.sourceforge.net/ which I bind to C-f4, which is the CUA keybinding for closing a window. This goes beyond the above code, closing frames and windows, before closing a buffer, and works well with gnuclient or emacsclient. – BruceIngalls?
Sorry for not noticing this for so long. I wrote the above code (minus diff-buffer-with-associated-file, which is pulled from the emacs sources). Of course, it’s free for all to use. --DamienElmes