0 | |
;;; ibuffer-projectile.el --- Group ibuffer's list by projectile root
|
|
0 |
;;; ibuffer-projectile.el --- Group ibuffer's list by projectile root -*- lexical-binding: t -*-
|
1 | 1 |
;;
|
2 | 2 |
;; Copyright (C) 2011-2014 Steve Purcell
|
3 | 3 |
;;
|
4 | 4 |
;; Author: Steve Purcell <steve@sanityinc.com>
|
5 | |
;; Keywords: themes
|
6 | |
;; Package-Requires: ((projectile "0.11.0"))
|
|
5 |
;; Keywords: convenience
|
|
6 |
;; Package-Requires: ((projectile "0.11.0") (emacs "24.1"))
|
7 | 7 |
;; URL: http://github.com/purcell/ibuffer-projectile
|
8 | 8 |
;; Package-Version: 0
|
9 | 9 |
;;
|
|
43 | 43 |
;; to programmatically obtain a list of filter groups that you can
|
44 | 44 |
;; combine with your own custom groups.
|
45 | 45 |
;;
|
|
46 |
;; To display filenames relative to the project root, use project-relative-file
|
|
47 |
;; in `ibuffer-formats', e.g.:
|
|
48 |
;;
|
|
49 |
;; (setq ibuffer-formats
|
|
50 |
;; '((mark modified read-only " "
|
|
51 |
;; (name 18 18 :left :elide)
|
|
52 |
;; " "
|
|
53 |
;; (size 9 -1 :right)
|
|
54 |
;; " "
|
|
55 |
;; (mode 16 16 :left :elide)
|
|
56 |
;; " "
|
|
57 |
;; project-relative-file)))
|
|
58 |
|
46 | 59 |
;;; Code:
|
47 | 60 |
|
48 | 61 |
(require 'ibuffer)
|
|
70 | 83 |
:type 'function
|
71 | 84 |
:group 'ibuffer-projectile)
|
72 | 85 |
|
|
86 |
(defcustom ibuffer-projectile-prefix "Projectile:"
|
|
87 |
"Prefix string for generated filter groups."
|
|
88 |
:type 'string
|
|
89 |
:group 'ibuffer-projectile)
|
|
90 |
|
|
91 |
(defcustom ibuffer-projectile-group-name-function 'ibuffer-projectile-default-group-name
|
|
92 |
"Function used to produce the name for a group.
|
|
93 |
The function is passed two arguments: the projectile project
|
|
94 |
name, and the root directory path."
|
|
95 |
:type 'function
|
|
96 |
:group 'ibuffer-projectile)
|
|
97 |
|
|
98 |
(defun ibuffer-projectile-default-group-name (project-name root-dir)
|
|
99 |
"Produce an ibuffer group name string for PROJECT-NAME and ROOT-DIR."
|
|
100 |
(format "%s%s" ibuffer-projectile-prefix project-name))
|
|
101 |
|
73 | 102 |
(defun ibuffer-projectile--include-file-p (file)
|
74 | 103 |
"Return t iff FILE should be included in ibuffer-projectile's filtering."
|
75 | 104 |
(and file
|
|
78 | 107 |
(funcall ibuffer-projectile-include-function file)))
|
79 | 108 |
|
80 | 109 |
(defun ibuffer-projectile-root (buf)
|
81 | |
"Return root-dir for BUF.
|
|
110 |
"Return a cons cell (project-name . root-dir) for BUF.
|
82 | 111 |
If the file is not in a project, then nil is returned instead."
|
83 | 112 |
(with-current-buffer buf
|
84 | |
(let ((file-name (or buffer-file-name default-directory)))
|
85 | |
(when (ibuffer-projectile--include-file-p file-name)
|
86 | |
(let ((projectile-require-project-root nil))
|
87 | |
(projectile-project-root))))))
|
|
113 |
(let ((file-name (ibuffer-buffer-file-name))
|
|
114 |
(root (ignore-errors (projectile-project-root))))
|
|
115 |
(when (and file-name
|
|
116 |
root
|
|
117 |
(ibuffer-projectile--include-file-p file-name))
|
|
118 |
(cons (projectile-project-name) root)))))
|
88 | 119 |
|
89 | 120 |
(define-ibuffer-filter projectile-root
|
90 | 121 |
"Toggle current view to buffers with projectile root dir QUALIFIER."
|
91 | 122 |
(:description "projectile root dir"
|
92 | |
:reader (read-from-minibuffer "Filter by projectile root dir (regexp): "))
|
|
123 |
:reader (read-regexp "Filter by projectile root dir (regexp): "))
|
93 | 124 |
(ibuffer-awhen (ibuffer-projectile-root buf)
|
94 | |
(equal qualifier it)))
|
|
125 |
(if (stringp qualifier)
|
|
126 |
(or (string-match-p qualifier (car it))
|
|
127 |
(string-match-p qualifier (cdr-safe it)))
|
|
128 |
(equal qualifier it))))
|
|
129 |
|
|
130 |
;;;###autoload (autoload 'ibuffer-make-column-project-name "ibuffer-projectile")
|
|
131 |
(define-ibuffer-column project-name
|
|
132 |
(:name "Project")
|
|
133 |
(projectile-project-name))
|
|
134 |
|
|
135 |
;;;###autoload (autoload 'ibuffer-do-sort-by-project-name "ibuffer-projectile")
|
|
136 |
(define-ibuffer-sorter project-name
|
|
137 |
"Sort the buffers by their project name."
|
|
138 |
(:description "project")
|
|
139 |
(let ((project1 (with-current-buffer (car a)
|
|
140 |
(projectile-project-name)))
|
|
141 |
(project2 (with-current-buffer (car b)
|
|
142 |
(projectile-project-name))))
|
|
143 |
(if (and project1 project2)
|
|
144 |
(string-lessp project1 project2)
|
|
145 |
(not (null project1)))))
|
|
146 |
|
|
147 |
;;;###autoload (autoload 'ibuffer-make-column-project-relative-file "ibuffer-projectile")
|
|
148 |
(define-ibuffer-column project-relative-file
|
|
149 |
(:name "Filename")
|
|
150 |
(when buffer-file-name
|
|
151 |
(let ((root (cdr (ibuffer-projectile-root buffer))))
|
|
152 |
(if root
|
|
153 |
(file-relative-name buffer-file-name root)
|
|
154 |
(abbreviate-file-name buffer-file-name)))))
|
95 | 155 |
|
96 | 156 |
;;;###autoload
|
97 | 157 |
(defun ibuffer-projectile-generate-filter-groups ()
|
|
99 | 159 |
(let ((roots (ibuffer-remove-duplicates
|
100 | 160 |
(delq nil (mapcar 'ibuffer-projectile-root (buffer-list))))))
|
101 | 161 |
(mapcar (lambda (root)
|
102 | |
(cons (abbreviate-file-name root)
|
|
162 |
(cons (funcall ibuffer-projectile-group-name-function (car root) (cdr root))
|
103 | 163 |
`((projectile-root . ,root))))
|
104 | 164 |
roots)))
|
105 | 165 |
|
106 | 166 |
;;;###autoload
|
107 | 167 |
(defun ibuffer-projectile-set-filter-groups ()
|
108 | |
"Set the current filter groups to filter by vc root dir."
|
|
168 |
"Set the current filter groups to filter by projectile root dir."
|
109 | 169 |
(interactive)
|
110 | 170 |
(setq ibuffer-filter-groups (ibuffer-projectile-generate-filter-groups))
|
111 | 171 |
(message "ibuffer-projectile: groups set")
|