Ibuffer is an advanced replacement for BufferMenu, which lets you operate on buffers much in the same manner as Dired. The most important Ibuffer features are highlighting and various alternate layouts. Ibuffer is part of Emacs 22.
If you don’t have Ibuffer, you can get it from GIT:ibuffer.el (there’s also a probably out-of-date project at gna.org). Here’s how to install it:
(global-set-key (kbd "C-x C-b") 'ibuffer) (autoload 'ibuffer "ibuffer" "List buffers." t)
See also: BufferMenuPlus, which also provides highlighting and other enhancements of BufferMenu.
‘M-s a C-s’ - Do incremental search in the marked buffers.‘M-s a C-M-s’ - Isearch for regexp in the marked buffers.‘U’ - Replace by regexp in each of the marked buffers.‘Q’ - Query replace in each of the marked buffers.‘I’ - As above, with a regular expression.‘0’ - Run occur on the marked buffers.With Icicles, you can use ‘M-s i’ in Ibuffer to search all marked buffers and possibly replace search hits. You have available all of the Icicles Search features, including accessing search hits directly, in any order.
Here’s how to hide all buffers starting with an asterisk.
(add-to-list 'ibuffer-never-show-regexps "^\\*")It does not contain in emacs 23.2’s ibuffer.el, use following instead – coldnew
(require 'ibuf-ext) (add-to-list 'ibuffer-never-show-predicates "^\\*")
Also try ibuffer’s “limiting” feature (‘/’), which allows you to just view a subset of your buffers.
Ibuffer can show you the differences between an unsaved buffer and the file on disk with `=’.
Ibuffer has an excellent implementation of Gnus-style grouping. Try this:
(setq ibuffer-saved-filter-groups
(quote (("default"
("dired" (mode . dired-mode))
("perl" (mode . cperl-mode))
("erc" (mode . erc-mode))
("planner" (or
(name . "^\\*Calendar\\*$")
(name . "^diary$")
(mode . muse-mode)))
("emacs" (or
(name . "^\\*scratch\\*$")
(name . "^\\*Messages\\*$")))
("gnus" (or
(mode . message-mode)
(mode . bbdb-mode)
(mode . mail-mode)
(mode . gnus-group-mode)
(mode . gnus-summary-mode)
(mode . gnus-article-mode)
(name . "^\\.bbdb$")
(name . "^\\.newsrc-dribble"))))))) (add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-switch-to-saved-filter-groups "default")))Then M-x dired then M-x ibuffer and you should see your dired buffer in a group. Open more of them and they all endup in there. This means that when browsing buffers you can skip over the items you are used to seeing. Anything not grouped goes at the bottom of the ibuffer buffer. – PhilJackson
It looks as though the default filterings are as follows:
predicate
content
size-lt
size-gt
filename
name
used-mode
modeSince filename can work for any part of the path, if you filter on a partial (or complete) directory, anything you have open from the directory is now grouped:
("journal" (filename . "/personal/journal/"))
I’m not familiar with gnus, and have been unsuccessful tracking written docs on filtering – I extracted the above from a reading of ibuf-ext.el and then onto the contents of ibuffer-filtering-alist. If there is anything out there, somebody please add it in, and edit this note. --OtherMichael
The last two lines of the ibuffer provide some information about each column. These two lines may be hidden by setting the ibuffer-display-summary variable to nil. The first two lines of the ibuffer are headers describing the contents of the columns. I don’t find these headers so useful and didn’t find a quick way to turn them off. So here is an advice that does the trick:
(defadvice ibuffer-update-title-and-summary (after remove-column-titles) (save-excursion (set-buffer "*Ibuffer*") (toggle-read-only 0) (goto-char 1) (search-forward "-\n" nil t) (delete-region 1 (point)) (let ((window-min-height 1)) ;; save a little screen estate (shrink-window-if-larger-than-buffer)) (toggle-read-only))) (ad-activate 'ibuffer-update-title-and-summary)
This extension to ibuffer-mode can dynamically create filter groups for the listed files’ version-control trees, and show their status (e.g. up-to-date, modified etc.).
This extension (based on ibuffer-vc) to ibuffer-mode can dynamically create filter groups for TRAMP buffers.
I’m not quite sure where to add this, but to be able to sort by pathname (thereby grouping file buffers with dired buffers). PeterMielke
Ibuffer should now use ‘dired-directory’ when appropriate. If you are able/willing to sign an assignment (see LegalMatters) then please send a patch defining an Ibuffer ‘filename’ sorter that falls back to ‘dired-directory’ for dired buffers – JohnPaulWallington.
Was it eventually added to Emacs? – DianeMurray
(defun my-ibuffer-hook () ;; add another sorting method for ibuffer (allow the grouping of ;; filenames and dired buffers (ibuffer-define-sorter pathname (:documentation "Sort the buffers by their pathname." :description "path") (string-lessp (with-current-buffer (car a) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")) (with-current-buffer (car b) (or buffer-file-name (if (eq major-mode 'dired-mode) (expand-file-name dired-directory)) ;; so that all non pathnames are at the end "~")))) ;; add key binding (define-key ibuffer-mode-map (kbd "s p") 'ibuffer-do-sort-by-pathname)) (add-hook 'ibuffer-mode-hooks 'my-ibuffer-hook)
I modified the above, works with GNU Emacs 22.0.92.1, should this work? --DavidBoon
(define-ibuffer-sorter filename-or-dired
"Sort the buffers by their pathname."
(:description "filenames plus dired")
(string-lessp
(with-current-buffer (car a)
(or buffer-file-name
(if (eq major-mode 'dired-mode)
(expand-file-name dired-directory))
;; so that all non pathnames are at the end
"~"))
(with-current-buffer (car b)
(or buffer-file-name
(if (eq major-mode 'dired-mode)
(expand-file-name dired-directory))
;; so that all non pathnames are at the end
"~"))))
(define-key ibuffer-mode-map (kbd "s p") 'ibuffer-do-sort-by-filename-or-dired)I didn’t really want a new filter; I just wanted the existing filename filter to also include dired buffers. Re-defining that filter in my init file as follows did the trick:
;; Enable ibuffer-filter-by-filename to filter on directory names too. (eval-after-load "ibuf-ext" '(define-ibuffer-filter filename "Toggle current view to buffers with file or directory name matching QUALIFIER." (:description "filename" :reader (read-from-minibuffer "Filter by file/directory name (regexp): ")) (ibuffer-awhen (or (buffer-local-value 'buffer-file-name buf) (buffer-local-value 'dired-directory buf)) (string-match qualifier it))))
I don’t like default “Size” column, so I write a human readable column instead of original one. – coldnew
;; Use human readable Size column instead of original one (define-ibuffer-column size-h (:name "Size" :inline t) (cond ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0))) ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0))) ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0))) (t (format "%8d" (buffer-size))))) ;; Modify the default ibuffer-formats (setq ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide) " " (size-h 9 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process)))
I have some buffer groups that i prefer do be collapsed by default. Since i found no way to have this working i adviced ibuffer like this:
(setq mp/ibuffer-collapsed-groups (list "Helm" "*Internal*")) (defadvice ibuffer (after collapse-helm) (dolist (group mp/ibuffer-collapsed-groups) (progn (goto-char 1) (when (search-forward (concat "[ " group " ]") (point-max) t) (progn (move-beginning-of-line nil) (ibuffer-toggle-filter-group) ) ) ) ) (goto-char 1) (search-forward "[ " (point-max) t) ) (ad-activate 'ibuffer)
With this, when you press ‘up’ or `down` to the top/bottom of IBuffer, the cursor wraps around to the bottom/top, so you can continue from there.
(defun ibuffer-previous-line () (interactive) (previous-line) (if (<= (line-number-at-pos) 2) (goto-line (- (count-lines (point-min) (point-max)) 2))))
(defun ibuffer-next-line () (interactive) (next-line) (if (>= (line-number-at-pos) (- (count-lines (point-min) (point-max)) 1)) (goto-line 3))) (define-key ibuffer-mode-map (kbd "<up>") 'ibuffer-previous-line) (define-key ibuffer-mode-map (kbd "<down>") 'ibuffer-next-line)
– kuanyui
With this improvement you do not need to hard code the line numbers, you just need copy, compile and run. Moreover, the keys ‘up’ and ‘down’ do the same thing but they skip the names of the filtered groups, and you can move to the beginning or the end of a group with ‘left’ and ‘right’.
(defun ibuffer-advance-motion (direction) (forward-line direction) (beginning-of-line) (if (not (get-text-property (point) 'ibuffer-filter-group-name)) t (ibuffer-skip-properties '(ibuffer-filter-group-name) direction) nil))
(defun ibuffer-previous-line (&optional arg) "Move backwards ARG lines, wrapping around the list if necessary." (interactive "P") (or arg (setq arg 1)) (let (err1 err2) (while (> arg 0) (cl-decf arg) (setq err1 (ibuffer-advance-motion -1) err2 (if (not (get-text-property (point) 'ibuffer-title)) t (goto-char (point-max)) (beginning-of-line) (ibuffer-skip-properties '(ibuffer-summary ibuffer-filter-group-name) -1) nil))) (and err1 err2))) (defun ibuffer-next-line (&optional arg) "Move forward ARG lines, wrapping around the list if necessary." (interactive "P") (or arg (setq arg 1)) (let (err1 err2) (while (> arg 0) (cl-decf arg) (setq err1 (ibuffer-advance-motion 1) err2 (if (not (get-text-property (point) 'ibuffer-summary)) t (goto-char (point-min)) (beginning-of-line) (ibuffer-skip-properties '(ibuffer-summary ibuffer-filter-group-name ibuffer-title) 1) nil))) (and err1 err2)))
(defun brust/ibuffer-next-header () (interactive) (while (ibuffer-next-line))) (defun brust/ibuffer-previous-header () (interactive) (while (ibuffer-previous-line)))
(define-key ibuffer-mode-map (kbd "<up>") 'ibuffer-previous-line) (define-key ibuffer-mode-map (kbd "<down>") 'ibuffer-next-line) (define-key ibuffer-mode-map (kbd "<right>") 'ibuffer-previous-header) (define-key ibuffer-mode-map (kbd "<left>") 'ibuffer-next-header)
– brust
Is there any way to configure ibuffer so that switching to ibuffer puts the cursor on the most recent buffer? I’m finding that the cursor stays on the same line it was on the previous time ibuffer was invoked, which is a bit confusing when the buffers are sorted in visited order.
Thanks - dab
(defun my-ibuffer () "Open ibuffer with cursour pointed to most recent buffer name" (interactive) (let ((recent-buffer-name (buffer-name))) (ibuffer) (ibuffer-jump-to-buffer recent-buffer-name))) (global-set-key [(f12)] 'my-ibuffer)
– Alexander Litvinov
That can be converted to advice, to make it more seamless.
;; Switching to ibuffer puts the cursor on the most recent buffer (defadvice ibuffer (around ibuffer-point-to-most-recent) () "Open ibuffer with cursor pointed to most recent buffer name" (let ((recent-buffer-name (buffer-name))) ad-do-it (ibuffer-jump-to-buffer recent-buffer-name))) (ad-activate 'ibuffer)
Here’s a snippet using the new advice system
(defun ninrod/ibuffer-recent-buffer (old-ibuffer &rest arguments) () "Open ibuffer with cursor pointed to most recent buffer name" (let ((recent-buffer-name (buffer-name))) (apply old-ibuffer arguments) (ibuffer-jump-to-buffer recent-buffer-name))) (advice-add #'ibuffer :around #'ninrod/ibuffer-recent-buffer)
– Ninrod
This will cause an error if you ever enter ibuffer from the minibuffer. Ibuffer complains about “No buffer with name *Minibuf-1*”. Here’s my fix:
(defadvice ibuffer (around ibuffer-point-to-most-recent) () "Open ibuffer with cursor pointed to most recent (non-minibuffer) buffer name" (let ((recent-buffer-name (if (minibufferp (buffer-name)) (buffer-name (window-buffer (minibuffer-selected-window))) (buffer-name (other-buffer))))) ad-do-it (ibuffer-jump-to-buffer recent-buffer-name))) (ad-activate 'ibuffer)
I set ibuffer-filter-groups like this: (setq ibuffer-filter-groups ‘((“Dired” ((mode . dired-mode)))))
but it doesn’t work. Is there an example to show how to set the varibale involved?
– YeWenbin
(require 'ibuf-ext nil t) (when (featurep 'ibuf-ext) (add-hook 'ibuffer-mode-hook (lambda () (setq ibuffer-filter-groups '( ("*buffer*" (name . "\\*.*\\*")) ("TAGS" (name . "^TAGS\\(<[0-9]+>\\)?$")) ("dired" (mode . dired-mode)) )))))
But How to move the Default group to display first?
Hi, see above (my original group suggestion) for the answer – PhilJackson
(defadvice ibuffer-generate-filter-groups (after reverse-ibuffer-groups () activate) (setq ad-return-value (nreverse ad-return-value)))
When used with ElScreen, Ibuffer tends to remove it’s header line with tabs.
To prevent it, set ibuffer-use-header-line to nil and use the following:
(defadvice ibuffer-update (around ibuffer-preserve-prev-header activate) "Preserve line-header used before Ibuffer if it doesn't set one" (let ((prev-line-header header-line-format)) ad-do-it (unless header-line-format (setq header-line-format prev-line-header))))
How can I set the number of characters that the name will truncate to? Right now, when I use uniquify to get uniqe buffer names, many of my buffer names look like this: ‘somedirectory:so…’ and I have to look at the filename column to find out that the file in questions was ‘somefile’. I would like to raise the number of chars displayed in the name column by ten och fifteen.
/Jeff
Read the documentation for ‘ibuffer-formats’ and you shall be enlightened.
I use ibuffer with the scratch buffer hidden. Sometimes I want to kill all the unhidden buffers, but then ibuffer complains about there being “No buffers!”. The relevant error code is in ibuffer-update and ibuffer-redisplay. Currently I’ve just redefined these functions with the error code commented out. Is there a better way to do this? Perhaps there could be a simple flag to determine whether ibuffer complains about killing all buffers.
/ Geoff