How can I close all unmodified buffers?
Usually after a day of work - I've got a ton of buffers / frames open. Right now I have to navigate to each frame and close it - which then prompts me if the file has been modified.
One way would be to use ibuffer:
M-x ibufferwill work.)
For frames, you can use
delete-other-frames (C-x 5 1).
If you do this often you may want to define your own command. Here's a starting point:
(defun my-clean-frames-and-buffers () "Kills all unmodified buffers and closes all but the selected frame." (interactive) (save-window-excursion (dolist (buffer (buffer-list)) (and (buffer-live-p buffer) (not (buffer-modified-p buffer)) (kill-buffer buffer)))) (delete-other-frames))
This won't prompt you and might kill more than you want, so some tweaking might be required.
There are two parts to your question:
Kill all unmodified buffers.
Delete their frames.
For #2, do you really mean frames? In Emacs, a "frame" is a window-manager window, and an (Emacs) "window" is a pane of an Emacs frame (a frame shows one or more windows). Do you really want to delete a frame that might be showing an unmodified buffer in one of its windows?
I'm guessing that you instead want to delete all Emacs windows showing unmodified buffers, at the same time that you kill those buffers.
If you use library
misc-cmds.el then you can use command (function)
kill-buffer-and-its-windows. It kills a buffer and deletes all windows showing it (on whatever frames).
This is automatically used by the solution for #1, below, provided you have library
misc-cmds.el in your
load-path, so it can be
All you need to do is use
C-x k, followed by
C-x * -, followed by
C-!. That kills all of the unmodified buffers and deletes all of their windows.
If you want to see which buffers are being acted on you can use
TAB anytime after
C-x k. For example,
C-x k TAB shows you the names of all buffers, and
C-x k C-x * - TAB shows you the names of all buffers that are modified (and only those buffers).
C-! acts on all of the completion candidates. In this case, the candidates are buffer names, and after you use
C-x * - the candidates are only the unmodified buffers. The action is
kill-buffer, so all of the unmodified buffers are killed.
A multi-command is an Icicles command that lets you act on multiple completion candidates (and on the same candidate multiple times) within the same invocation of the command.
C-! always performs the command action on all of the current completion candidates.
In this case, you just needed to filter the buffer-name candidates to remove those for modified buffers, before hitting
C-! to kill the rest.
Yes, it's not obvious here that
C-x * - filters out the modified buffers. But
C-h k C-x k tells you about this. (Actually, it refers you to the doc for
icicle-buffer, which provides a pretty complete description of all Icicles multi-commands that read a buffer name.) The more complete doc for this is here: Icicle - Buffer-Name Input.
C-x k), like
C-x b) is not only a multi-commmand. In addition, completion candidates are in fact multi-completions, with two parts. Each of your inputs can have two patterns, which match those parts:
If you just type some text, that matches the buffer name. To then match also the buffer content, you use
C-M-j and then type the content-matching pattern. (If you want to match only content and not also names, then just start with
C-M-j at the prompt.)
So for example, you could kill all unmodified buffers that contain text that matches the regexp
C-x k S-TAB -- Show all buffers
C-x * - -- Remove modified buffers as candidates
C-M-j -- Don't bother to match buffer names
foo.*bar.*toto -- Match buffer content (removing names of buffers that don't match)
C-! -- Kill the remaining buffers, which are unmodified and have text that matches
In Icicles completion,
S-TAB performs apropos completion, which does regexp matching.
If you really did mean that you want to delete the frames and not just the windows showing unmodified buffers, then library
frame-cmds.el can help. It advises function
delete-window so that the frame showing the window to be deleted is also deleted, provided that it its sole window. This is the advice:
(defadvice delete-window (around delete-frame-if-one-win activate) "If WINDOW is the only one in its frame, then `delete-frame' too." (with-selected-window (or (ad-get-arg 0) (selected-window)) (if (one-window-p t) (delete-frame) ad-do-it)))