ibuffer-vc-0.11/0000755000175000017500000000000013630023231013306 5ustar dogslegdogslegibuffer-vc-0.11/ibuffer-vc.el0000644000175000017500000002076513630023231015672 0ustar dogslegdogsleg;;; ibuffer-vc.el --- Group ibuffer's list by VC project, or show VC status -*- lexical-binding: t -*- ;; ;; Copyright (C) 2011-2014 Steve Purcell ;; ;; Author: Steve Purcell ;; Keywords: convenience ;; Package-Requires: ((emacs "24.1") (cl-lib "0.2")) ;; URL: http://github.com/purcell/ibuffer-vc ;; Version: DEV ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;; ;;; Commentary: ;; ;; Adds functionality to ibuffer for grouping buffers by their parent ;; vc root directory, and for displaying and/or sorting by the vc ;; status of listed files. ;; ;;; Use: ;; ;; To group buffers by vc parent dir: ;; ;; M-x ibuffer-vc-set-filter-groups-by-vc-root ;; ;; or, make this the default: ;; ;; (add-hook 'ibuffer-hook ;; (lambda () ;; (ibuffer-vc-set-filter-groups-by-vc-root) ;; (unless (eq ibuffer-sorting-mode 'alphabetic) ;; (ibuffer-do-sort-by-alphabetic)))) ;; ;; Alternatively, use `ibuffer-vc-generate-filter-groups-by-vc-root' ;; to programmatically obtain a list of filter groups that you can ;; combine with your own custom groups. ;; ;; To include vc status info in the ibuffer list, add either ;; vc-status-mini or vc-status to `ibuffer-formats': ;; ;; (setq ibuffer-formats ;; '((mark modified read-only vc-status-mini " " ;; (name 18 18 :left :elide) ;; " " ;; (size 9 -1 :right) ;; " " ;; (mode 16 16 :left :elide) ;; " " ;; (vc-status 16 16 :left) ;; " " ;; vc-relative-file))) ;; ;; To sort by vc status, use `ibuffer-do-sort-by-vc-status', which can ;; also be selected by repeatedly executing ;; `ibuffer-toggle-sorting-mode' (bound to "," by default). ;; ;;; Code: ;; requires (require 'ibuffer) (require 'ibuf-ext) (require 'vc-hooks) (require 'cl-lib) (defgroup ibuffer-vc nil "Group ibuffer entries according to their version control status." :prefix "ibuffer-vc-" :group 'convenience) (defcustom ibuffer-vc-skip-if-remote t "If non-nil, don't query the VC status of remote files." :type 'boolean :group 'ibuffer-vc) (defcustom ibuffer-vc-include-function 'identity "A function which tells whether a given file should be grouped. The function is passed a filename, and should return non-nil if the file is to be grouped. This option can be used to exclude certain files from the grouping mechanism." :type 'function :group 'ibuffer-vc) ;;; Group and filter ibuffer entries by parent vc directory (defun ibuffer-vc--include-file-p (file) "Return t iff FILE should be included in ibuffer-vc's filtering." (and file (or (null ibuffer-vc-skip-if-remote) (not (file-remote-p file))) (funcall ibuffer-vc-include-function file))) (defun ibuffer-vc--deduce-backend (file) "Return the vc backend for FILE, or nil if not under VC supervision." (if (fboundp 'vc-responsible-backend) (ignore-errors (vc-responsible-backend file)) (or (vc-backend file) (cl-loop for backend in vc-handled-backends when (vc-call-backend backend 'responsible-p file) return backend)))) (defun ibuffer-vc-root (buf) "Return a cons cell (backend-name . root-dir) for BUF. If the file is not under version control, nil is returned instead." (let ((file-name (with-current-buffer buf (file-truename (or buffer-file-name default-directory))))) (when (ibuffer-vc--include-file-p file-name) (let ((backend (ibuffer-vc--deduce-backend file-name))) (when backend (let* ((root-fn-name (intern (format "vc-%s-root" (downcase (symbol-name backend))))) (root-dir (cond ((fboundp root-fn-name) (funcall root-fn-name file-name)) ; git, svn, hg, bzr (at least) ((memq backend '(darcs DARCS)) (vc-darcs-find-root file-name)) ((memq backend '(cvs CVS)) (vc-find-root file-name "CVS")) ((memq backend '(rcs RCS)) (or (vc-find-root file-name "RCS") (concat file-name ",v"))) ((memq backend '(src SRC)) (or (vc-find-root file-name ".src") (concat file-name ",v"))) (t (error "ibuffer-vc: don't know how to find root for vc backend '%s' - please submit a bug report or patch" backend))))) (cons backend root-dir))))))) (defun ibuffer-vc-read-filter () "Read a cons cell of (backend-name . root-dir)." (cons (car (read-from-string (completing-read "VC backend: " vc-handled-backends nil t))) (read-directory-name "Root directory: " nil nil t))) (define-ibuffer-filter vc-root "Toggle current view to buffers with vc root dir QUALIFIER." (:description "vc root dir" :reader (ibuffer-vc-read-filter)) (ibuffer-awhen (ibuffer-vc-root buf) (equal qualifier it))) ;;;###autoload (defun ibuffer-vc-generate-filter-groups-by-vc-root () "Create a set of ibuffer filter groups based on the vc root dirs of buffers." (let ((roots (ibuffer-remove-duplicates (delq nil (mapcar 'ibuffer-vc-root (buffer-list)))))) (mapcar (lambda (vc-root) (cons (format "%s: %s" (car vc-root) (cdr vc-root)) `((vc-root . ,vc-root)))) roots))) ;;;###autoload (defun ibuffer-vc-set-filter-groups-by-vc-root () "Set the current filter groups to filter by vc root dir." (interactive) (setq ibuffer-filter-groups (ibuffer-vc-generate-filter-groups-by-vc-root)) (message "ibuffer-vc: groups set") (let ((ibuf (get-buffer "*Ibuffer*"))) (when ibuf (with-current-buffer ibuf (pop-to-buffer ibuf) (ibuffer-update nil t))))) ;;; Display vc status info in the ibuffer list (defun ibuffer-vc--state (file) "Return the `vc-state' for FILE, or nil if unregistered." (ignore-errors (vc-state file))) (defun ibuffer-vc--status-string () "Return a short string to represent the current buffer's status." (when (and buffer-file-name (ibuffer-vc--include-file-p buffer-file-name)) (let ((state (ibuffer-vc--state buffer-file-name))) (if state (symbol-name state) "-")))) ;;;###autoload (autoload 'ibuffer-make-column-vc-status "ibuffer-vc") (define-ibuffer-column vc-status (:name "VC status") (ibuffer-vc--status-string)) ;;;###autoload (autoload 'ibuffer-make-column-vc-relative-file "ibuffer-vc") (define-ibuffer-column vc-relative-file (:name "Filename") (if buffer-file-name (let ((root (cdr (ibuffer-vc-root buffer)))) (if root (file-relative-name buffer-file-name root) (abbreviate-file-name buffer-file-name))) "")) ;;;###autoload (autoload 'ibuffer-make-column-vc-status-mini "ibuffer-vc") (define-ibuffer-column vc-status-mini (:name "V") (if (and buffer-file-name (ibuffer-vc--include-file-p buffer-file-name)) (let ((state (ibuffer-vc--state buffer-file-name))) (cond ((eq 'added state) "A") ((eq 'removed state) "D") ((eq 'up-to-date state) "=") ((eq 'edited state) "*") ((eq 'needs-update state) "O") ((memq state '(conflict needs-merge unlocked-changes)) "!") ((eq 'ignored state) "I") ((memq state '(() unregistered missing)) "?"))) " ")) ;;;###autoload (autoload 'ibuffer-do-sort-by-vc-status "ibuffer-vc") (define-ibuffer-sorter vc-status "Sort the buffers by their vc status." (:description "vc status") (let ((file1 (with-current-buffer (car a) buffer-file-name)) (file2 (with-current-buffer (car b) buffer-file-name))) (if (and file1 file2) (string-lessp (with-current-buffer (car a) (ibuffer-vc--status-string)) (with-current-buffer (car b) (ibuffer-vc--status-string))) (not (null file1))))) (provide 'ibuffer-vc) ;;; ibuffer-vc.el ends here ibuffer-vc-0.11/README.md0000644000175000017500000000263213630023231014570 0ustar dogslegdogsleg[![Melpa Status](http://melpa.org/packages/ibuffer-vc-badge.svg)](http://melpa.org/#/ibuffer-vc) [![Melpa Stable Status](http://stable.melpa.org/packages/ibuffer-vc-badge.svg)](http://stable.melpa.org/#/ibuffer-vc) Support me # ibuffer-vc: Group buffers in ibuffer list by VC project # Emacs' `ibuffer-mode` is a wonderful replacement for the built-in `list-buffer` command, and allows buffers to be grouped programatically, e.g. by major mode. If, like me, you mostly work on version-controlled files, you might like to see your buffers grouped by the associated version control project. That's where `ibuffer-vc` comes in: it lets you: * Group your buffers by their parent vc root directory * See the VC status of the associated files * Sort buffers by their VC status * Display buffer filenames that are relative to their VC root ## Screenshot ## ![ibuffer-vc screenshot](http://i.imgur.com/RUYRJ.png) ## How to install ## See `ibuffer-vc.el`, or (preferred) install from [MELPA][MELPA]. [MELPA]: http://melpa.org "MELPA"
[💝 Support this project and my other Open Source work](https://www.patreon.com/sanityinc) [💼 LinkedIn profile](https://uk.linkedin.com/in/stevepurcell) [✍ sanityinc.com](http://www.sanityinc.com/) [🐦 @sanityinc](https://twitter.com/sanityinc)