.emacs.d / files / ibuffer.el

(require 'ibuffer)
;; filter groups
(setq ibuffer-saved-filter-groups
      (quote (("default"
               ("Org" ;; all org-related buffers
                (mode . org-mode))
                (or (predicate
                     (let ((bfn (buffer-file-name (current-buffer))))
                       (when bfn
                         (and (string-match-p "\\.emacs\\.d" bfn)
                              (eq major-mode 'emacs-lisp-mode)))))))
                (or (mode . emacs-lisp-mode)
                    (mode . lisp-interaction-mode)
                    (mode . inferior-emacs-lisp-mode)))
                (or (mode . tex-mode)
                    (mode . plain-tex-mode)
                    (mode . latex-mode)))
               ("Markdown" (or (mode . markdown-mode)
                               (mode . gfm-mode)))
                (or (mode . html-mode)
                    (mode . css-mode)
                    (mode . php-mode)
                    (mode . js-mode)))
                (mode . sr-mode))
                (mode . dired-mode))
                (or (name . "tramp")))
               ("Programming" ;; prog stuff not already in MyProjectX
                 (mode . c-mode)
                 (mode . perl-mode)
                 (mode . python-mode)
                 (mode . cc-mode)
                 ;; etc

;; column settings
(defun my-transform-buffer-name (name)
  "Transform buffer name for display in `ibuffer'."
   ((string-match " *(Sunrise)" name)
    (substring name 0 (match-beginning 0)))
   (t name)))

(define-ibuffer-column name-trans
  (:inline t
   :header-mouse-map ibuffer-name-header-map
   ('mouse-face 'highlight 'keymap ibuffer-name-map
        'ibuffer-name-column t
        'help-echo '(if tooltip-mode
                "mouse-1: mark this buffer\nmouse-2: select this buffer\nmouse-3: operate on this buffer"
                  "mouse-1: mark buffer   mouse-2: select buffer   mouse-3: operate"))
   (lambda (strings)
     (let ((bufs (length strings)))
       (cond ((zerop bufs) "No buffers")
         ((= 1 bufs) "1 buffer")
         (t (format "%s buffers" bufs))))))
  (propertize (my-transform-buffer-name (buffer-name))
              'font-lock-face (ibuffer-buffer-name-face buffer mark)))

(define-ibuffer-column size-h
  (:name "Size"
   :inline t
   (lambda (column-strings)
     (let ((total 0))
       (dolist (string column-strings)
         (setq total
               ;; like, ewww ...
                (let ((number (float (string-to-number string))))
                   ((string-match-p "K" string)
                    (* number 1000))
                   ((string-match-p "M" string)
                    (* number 1000000))
                   (t number)))
       (file-size-human-readable total 'si))))
  (file-size-human-readable (buffer-size) 'si))

;; Modify the default ibuffer-formats
(setq ibuffer-formats
  '((mark modified read-only
          " " (name-trans 25 25 :left :elide)
          " " (size-h 9 -1 :right)
          " " (mode 16 16 :left :elide)
          " " filename-and-process)
    (mark " " (name 16 -1)
          " " filename)))

;; startup function
(defun customize-ibuffer-mode ()
  "Startup function."
  (ibuffer-switch-to-saved-filter-groups "default")
  (add-to-list 'ibuffer-hidden-filter-groups "Sunrise")
  (add-to-list 'ibuffer-hidden-filter-groups "Tramp"))
(add-hook 'ibuffer-mode-hook 'customize-ibuffer-mode)

;; Switching to ibuffer puts the cursor on the most recent buffer
(defadvice ibuffer (around ibuffer-point-to-most-recent activate) ()
  "Open ibuffer with cursor pointed to most recent buffer name"
  (let ((recent-buffer-name (buffer-name)))
    (ibuffer-jump-to-buffer recent-buffer-name)))