Rewrite sorting mechanism
See the "Sorting candidates" section of the README.
This commit is contained in:
parent
8f85a392d8
commit
c752c843ef
2 changed files with 86 additions and 35 deletions
15
README.md
15
README.md
|
|
@ -26,6 +26,8 @@
|
||||||
- [Setting `counsel-projectile-org-capture` templates](#setting-counsel-projectile-org-capture-templates)
|
- [Setting `counsel-projectile-org-capture` templates](#setting-counsel-projectile-org-capture-templates)
|
||||||
- [Removing the current project or buffer from the list of candidates](#removing-the-current-project-or-buffer-from-the-list-of-candidates)
|
- [Removing the current project or buffer from the list of candidates](#removing-the-current-project-or-buffer-from-the-list-of-candidates)
|
||||||
- [Initial input for the project search commands](#initial-input-for-the-project-search-commands)
|
- [Initial input for the project search commands](#initial-input-for-the-project-search-commands)
|
||||||
|
- [Matcher for `counsel-projectile-find-file`](#matcher-for-counsel-projectile-find-file)
|
||||||
|
- [Sorting candidates](#sorting-candidates)
|
||||||
- [Upgrading from previous version](#upgrading-from-previous-version)
|
- [Upgrading from previous version](#upgrading-from-previous-version)
|
||||||
- [Key bindings](#key-bindings)
|
- [Key bindings](#key-bindings)
|
||||||
- [Action lists](#action-lists)
|
- [Action lists](#action-lists)
|
||||||
|
|
@ -236,16 +238,21 @@ By default, the command `counsel-projectile-find-file` relies on the the matcher
|
||||||
The matcher specified by `counsel-find-file-ignore-regexp` is also used by `counsel-projectile` to match files.
|
The matcher specified by `counsel-find-file-ignore-regexp` is also used by `counsel-projectile` to match files.
|
||||||
## Sorting candidates
|
## Sorting candidates
|
||||||
The following commands allow to modify the way candidates are sorted:
|
The following commands allow to modify the way candidates are sorted:
|
||||||
- `counsel-projectile`
|
|
||||||
- `cousnel-projectile-switch-project`
|
- `cousnel-projectile-switch-project`
|
||||||
- `counsel-projectile-find-file`
|
- `counsel-projectile-find-file`
|
||||||
- `counsel-projectile-find-dir`
|
- `counsel-projectile-find-dir`
|
||||||
- `counsel-projectile-switch-to-buffer`
|
- `counsel-projectile-switch-to-buffer`
|
||||||
To do so you need to add sorting functions to `ivy-sort-functions-alist`, e.g.
|
Sorting for these commands is controlled by the following variables, respectively:
|
||||||
|
- `counsel-projectile-sort-projects`
|
||||||
|
- `counsel-projectile-sort-files`
|
||||||
|
- `counsel-projectile-sort-directories`
|
||||||
|
- `counsel-projectile-sort-buffers`
|
||||||
|
If one of these variable is nil, the default, the command's candidates are not sorted. If it is non-nil, they are sorted. The sorting criterion can be customized through the variable `ivy-sort-functions-alist`. For instance, if you want files to be sorted from newest to oldest, then you need to add the following entry to this list:
|
||||||
```emacs-lisp
|
```emacs-lisp
|
||||||
(setcdr (assoc 'counsel-projectile-find-file ivy-sort-functions-alist)
|
'(counsel-projectile-find-file . file-newer-than-file-p)
|
||||||
'file-newer-than-file-p)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that the `counsel-projectile` command always sorts buffers before files. Buffers are sorted as in `counsel-projectile-switch-to-buffer` and files are sorted according to `counsel-projectile-find-file`.
|
||||||
# Upgrading from previous version
|
# Upgrading from previous version
|
||||||
If you are upgrading from version `0.1` to version `0.2`, please read below about important changes, some of which may require you to update your configuration.
|
If you are upgrading from version `0.1` to version `0.2`, please read below about important changes, some of which may require you to update your configuration.
|
||||||
## Key bindings
|
## Key bindings
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,15 @@ If anything goes wrong, throw an error and do not modify ACTION-VAR."
|
||||||
|
|
||||||
;;;; counsel-projectile-find-file
|
;;;; counsel-projectile-find-file
|
||||||
|
|
||||||
|
(defcustom counsel-projectile-sort-files nil
|
||||||
|
"Non-nil if files should be sorted in
|
||||||
|
`counsel-projectile-find-file' and `counsel-projectile'.
|
||||||
|
|
||||||
|
The sorting function can be modified by adding an entry for
|
||||||
|
`counsel-projectile-find-file' in `ivy-sort-functions-alist'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'counsel-projectile)
|
||||||
|
|
||||||
(defcustom counsel-projectile-find-file-matcher 'counsel--find-file-matcher
|
(defcustom counsel-projectile-find-file-matcher 'counsel--find-file-matcher
|
||||||
"Function returning candidates matching minibuffer input in
|
"Function returning candidates matching minibuffer input in
|
||||||
`counsel-projectile-find-file', also used to match files in
|
`counsel-projectile-find-file', also used to match files in
|
||||||
|
|
@ -369,19 +378,25 @@ With a prefix ARG, invalidate the cache first."
|
||||||
(projectile-current-project-files)
|
(projectile-current-project-files)
|
||||||
:matcher counsel-projectile-find-file-matcher
|
:matcher counsel-projectile-find-file-matcher
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
:sort counsel-projectile-sort-files
|
||||||
:action counsel-projectile-find-file-action
|
:action counsel-projectile-find-file-action
|
||||||
:caller 'counsel-projectile-find-file))
|
:caller 'counsel-projectile-find-file))
|
||||||
|
|
||||||
(unless (assq #'counsel-projectile-find-file ivy-sort-functions-alist)
|
|
||||||
(push (list #'counsel-projectile-find-file) ivy-sort-functions-alist))
|
|
||||||
|
|
||||||
(ivy-set-display-transformer
|
(ivy-set-display-transformer
|
||||||
'counsel-projectile-find-file
|
'counsel-projectile-find-file
|
||||||
'counsel-projectile-find-file-transformer)
|
'counsel-projectile-find-file-transformer)
|
||||||
|
|
||||||
;;;; counsel-projectile-find-dir
|
;;;; counsel-projectile-find-dir
|
||||||
|
|
||||||
|
(defcustom counsel-projectile-sort-directories nil
|
||||||
|
"Non-nil if directories should be sorted in
|
||||||
|
`counsel-projectile-find-dir'.
|
||||||
|
|
||||||
|
The sorting function can be modified by adding an entry for
|
||||||
|
`counsel-projectile-find-dir' in `ivy-sort-functions-alist'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'counsel-projectile)
|
||||||
|
|
||||||
(counsel-projectile--defcustom-action
|
(counsel-projectile--defcustom-action
|
||||||
'counsel-projectile-find-dir
|
'counsel-projectile-find-dir
|
||||||
'(1
|
'(1
|
||||||
|
|
@ -422,15 +437,22 @@ With a prefix ARG, invalidate the cache first."
|
||||||
(ivy-read (projectile-prepend-project-name "Find dir: ")
|
(ivy-read (projectile-prepend-project-name "Find dir: ")
|
||||||
(counsel-projectile--project-directories)
|
(counsel-projectile--project-directories)
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
:sort counsel-projectile-sort-directories
|
||||||
:action counsel-projectile-find-dir-action
|
:action counsel-projectile-find-dir-action
|
||||||
:caller 'counsel-projectile-find-dir))
|
:caller 'counsel-projectile-find-dir))
|
||||||
|
|
||||||
(unless (assq #'counsel-projectile-find-dir ivy-sort-functions-alist)
|
|
||||||
(push (list #'counsel-projectile-find-dir) ivy-sort-functions-alist))
|
|
||||||
|
|
||||||
;;;; counsel-projectile-switch-to-buffer
|
;;;; counsel-projectile-switch-to-buffer
|
||||||
|
|
||||||
|
(defcustom counsel-projectile-sort-buffers nil
|
||||||
|
"Non-nil if buffers should be sorted in
|
||||||
|
`counsel-projectile-switch-to-buffer' and `counsel-projectile'.
|
||||||
|
|
||||||
|
The sorting function can be modified by adding an entry for
|
||||||
|
`counsel-projectile-switch-to-buffer' in
|
||||||
|
`ivy-sort-functions-alist'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'counsel-projectile)
|
||||||
|
|
||||||
(defcustom counsel-projectile-remove-current-buffer nil
|
(defcustom counsel-projectile-remove-current-buffer nil
|
||||||
"Non-nil if current buffer should be removed from the
|
"Non-nil if current buffer should be removed from the
|
||||||
candidates list of `counsel-projectile-switch-to-buffer' and
|
candidates list of `counsel-projectile-switch-to-buffer' and
|
||||||
|
|
@ -506,14 +528,11 @@ This simply applies the same transformer as in `ivy-switch-buffer', which is `iv
|
||||||
#'counsel-projectile--project-buffers
|
#'counsel-projectile--project-buffers
|
||||||
:matcher #'ivy--switch-buffer-matcher
|
:matcher #'ivy--switch-buffer-matcher
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
:sort counsel-projectile-sort-buffers
|
||||||
:action counsel-projectile-switch-to-buffer-action
|
:action counsel-projectile-switch-to-buffer-action
|
||||||
:keymap counsel-projectile-switch-to-buffer-map
|
:keymap counsel-projectile-switch-to-buffer-map
|
||||||
:caller 'counsel-projectile-switch-to-buffer))
|
:caller 'counsel-projectile-switch-to-buffer))
|
||||||
|
|
||||||
(unless (assq #'counsel-projectile--project-buffers ivy-sort-functions-alist)
|
|
||||||
(push (list #'counsel-projectile--project-buffers) ivy-sort-functions-alist))
|
|
||||||
|
|
||||||
(ivy-set-display-transformer
|
(ivy-set-display-transformer
|
||||||
'counsel-projectile-switch-to-buffer
|
'counsel-projectile-switch-to-buffer
|
||||||
'counsel-projectile-switch-to-buffer-transformer)
|
'counsel-projectile-switch-to-buffer-transformer)
|
||||||
|
|
@ -911,6 +930,16 @@ The capture templates are read from the variables
|
||||||
|
|
||||||
;;;; counsel-projectile-switch-project
|
;;;; counsel-projectile-switch-project
|
||||||
|
|
||||||
|
(defcustom counsel-projectile-sort-projects nil
|
||||||
|
"Non-nil if projects should be sorted in
|
||||||
|
`counsel-projectile-switch-project'.
|
||||||
|
|
||||||
|
The sorting function can be modified by adding an entry for
|
||||||
|
`counsel-projectile-switch-project' in
|
||||||
|
`ivy-sort-functions-alist'."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'counsel-projectile)
|
||||||
|
|
||||||
(defcustom counsel-projectile-remove-current-project nil
|
(defcustom counsel-projectile-remove-current-project nil
|
||||||
"Non-nil if current project should be removed from the
|
"Non-nil if current project should be removed from the
|
||||||
candidates list of `counsel-projectile-switch-project'."
|
candidates list of `counsel-projectile-switch-project'."
|
||||||
|
|
@ -1110,12 +1139,9 @@ action."
|
||||||
(abbreviate-file-name (projectile-project-root)))
|
(abbreviate-file-name (projectile-project-root)))
|
||||||
:action counsel-projectile-switch-project-action
|
:action counsel-projectile-switch-project-action
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
:sort counsel-projectile-sort-projects
|
||||||
:caller 'counsel-projectile-switch-project))
|
:caller 'counsel-projectile-switch-project))
|
||||||
|
|
||||||
(unless (assq #'counsel-projectile-switch-project ivy-sort-functions-alist)
|
|
||||||
(push (list #'counsel-projectile-switch-project) ivy-sort-functions-alist))
|
|
||||||
|
|
||||||
;;;; counsel-projectile
|
;;;; counsel-projectile
|
||||||
|
|
||||||
(counsel-projectile--defcustom-action
|
(counsel-projectile--defcustom-action
|
||||||
|
|
@ -1155,17 +1181,39 @@ action."
|
||||||
(defun counsel-projectile--project-buffers-and-files (&rest _)
|
(defun counsel-projectile--project-buffers-and-files (&rest _)
|
||||||
;; The ignored arguments are so that the function can be used as
|
;; The ignored arguments are so that the function can be used as
|
||||||
;; collection function in `counsel-projectile'.
|
;; collection function in `counsel-projectile'.
|
||||||
"Return a list of buffers and files in the current project."
|
"Return a list of buffers and non-visited files in the current
|
||||||
(append
|
project. Buffers and files are separately sorted depending on
|
||||||
(setq counsel-projectile--buffers
|
`counsel-projectile-sort-buffers' and
|
||||||
(counsel-projectile--project-buffers))
|
`counsel-projectile-sort-files', respectively."
|
||||||
(setq counsel-projectile--non-visited-files
|
(let ((buffers (counsel-projectile--project-buffers))
|
||||||
(let ((root (projectile-project-root))
|
(files (projectile-current-project-files))
|
||||||
(files (projectile-current-project-files))
|
(root (projectile-project-root))
|
||||||
file)
|
file sort-fn)
|
||||||
(dolist (buffer counsel-projectile--buffers files)
|
;; Remove files that are visited by a buffer:
|
||||||
(when (setq file (buffer-file-name (get-buffer buffer)))
|
(dolist (buffer buffers files)
|
||||||
(setq files (remove (file-relative-name file root) files))))))))
|
(when (setq file (buffer-file-name (get-buffer buffer)))
|
||||||
|
(setq files (remove (file-relative-name file root) files))))
|
||||||
|
;; Sort buffers and files depending on
|
||||||
|
;; `counsel-projectile-sort-buffers' and
|
||||||
|
;; `counsel-projectile-sort-files', respectively.
|
||||||
|
;; We need to do this here because matching will be done against
|
||||||
|
;; the variables `counsel-projectile--buffers' and
|
||||||
|
;; `counsel-projectile--non-visited-files', not against the
|
||||||
|
;; returned collection, so ivy's native sorting mechanism won't
|
||||||
|
;; work.
|
||||||
|
(when (and counsel-projectile-sort-buffers
|
||||||
|
(<= (length buffers) ivy-sort-max-size)
|
||||||
|
(setq sort-fn (ivy--sort-function 'counsel-projectile-switch-to-buffer)))
|
||||||
|
(setq buffers (sort (copy-sequence buffers) sort-fn)))
|
||||||
|
(when (and counsel-projectile-sort-files
|
||||||
|
(<= (length files) ivy-sort-max-size)
|
||||||
|
(setq sort-fn (ivy--sort-function 'counsel-projectile-find-file)))
|
||||||
|
(setq files (sort (copy-sequence files) sort-fn)))
|
||||||
|
;; Finally, bind `counsel-projectile--buffers' and
|
||||||
|
;; `counsel-projectile--non-visited-files' and return the whole
|
||||||
|
;; collection.
|
||||||
|
(append (setq counsel-projectile--buffers buffers)
|
||||||
|
(setq counsel-projectile--non-visited-files files))))
|
||||||
|
|
||||||
(defun counsel-projectile--matcher (regexp _candidates)
|
(defun counsel-projectile--matcher (regexp _candidates)
|
||||||
"Return REGEXP-matching CANDIDATES for `counsel-projectile'.
|
"Return REGEXP-matching CANDIDATES for `counsel-projectile'.
|
||||||
|
|
@ -1237,14 +1285,10 @@ If not inside a project, call `counsel-projectile-switch-project'."
|
||||||
#'counsel-projectile--project-buffers-and-files
|
#'counsel-projectile--project-buffers-and-files
|
||||||
:matcher #'counsel-projectile--matcher
|
:matcher #'counsel-projectile--matcher
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
|
||||||
:action counsel-projectile-action
|
:action counsel-projectile-action
|
||||||
:keymap counsel-projectile-map
|
:keymap counsel-projectile-map
|
||||||
:caller 'counsel-projectile)))
|
:caller 'counsel-projectile)))
|
||||||
|
|
||||||
(unless (assq #'counsel-projectile--project-buffers-and-files ivy-sort-functions-alist)
|
|
||||||
(push (list #'counsel-projectile--project-buffers-and-files) ivy-sort-functions-alist))
|
|
||||||
|
|
||||||
(ivy-set-display-transformer
|
(ivy-set-display-transformer
|
||||||
'counsel-projectile
|
'counsel-projectile
|
||||||
'counsel-projectile-transformer)
|
'counsel-projectile-transformer)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue