cp-find-file: make matcher customizable and provide basename matcher
Closes #72
This commit is contained in:
parent
e8eee886b7
commit
222b6ac531
2 changed files with 73 additions and 4 deletions
|
|
@ -224,6 +224,10 @@ Templates contexts are read from the variable `counsel-projectile-org-capture-te
|
||||||
By default, when calling `counsel-projectile-switch-project`, the current project (if any) is included in the candidates list and preselected. Similarly, when calling `counsel-projectile-switch-to-buffer`, the current buffer is included in the candidates list and preselected. If you prefer removing these elements from the candidate lists of these commands, you can set the variables `counsel-projectile-remove-current-project` and `counsel-projectile-remove-current-buffer` accordingly.
|
By default, when calling `counsel-projectile-switch-project`, the current project (if any) is included in the candidates list and preselected. Similarly, when calling `counsel-projectile-switch-to-buffer`, the current buffer is included in the candidates list and preselected. If you prefer removing these elements from the candidate lists of these commands, you can set the variables `counsel-projectile-remove-current-project` and `counsel-projectile-remove-current-buffer` accordingly.
|
||||||
## Initial input for the project search commands
|
## Initial input for the project search commands
|
||||||
If you want some initial input to be inserted in the minibuffer every time you call `counsel-projectile-grep`, `counsel-projectile-ag`, or `counsel-projectile-rg`, you can customize the variables `counsel-projectile-grep-initial-input`, `counsel-projectile-ag-initial-input`, or `counsel-projectile-rg-initial-input` accordingly. Each of these variable, if non `nil`, should hold a Lisp expression whose evaluation yields the initial input string. If you use the Customize interface, some choices are proposed based on various versions of the `thing-at-point` function. Note that you can always insert the value of `(ivy-thing-at-point)` by hitting <kbd>M-n</kbd> in the minibuffer.
|
If you want some initial input to be inserted in the minibuffer every time you call `counsel-projectile-grep`, `counsel-projectile-ag`, or `counsel-projectile-rg`, you can customize the variables `counsel-projectile-grep-initial-input`, `counsel-projectile-ag-initial-input`, or `counsel-projectile-rg-initial-input` accordingly. Each of these variable, if non `nil`, should hold a Lisp expression whose evaluation yields the initial input string. If you use the Customize interface, some choices are proposed based on various versions of the `thing-at-point` function. Note that you can always insert the value of `(ivy-thing-at-point)` by hitting <kbd>M-n</kbd> in the minibuffer.
|
||||||
|
## Matcher for `counsel-projectile-find-file`
|
||||||
|
By default, the command `counsel-projectile-find-file` relies on the the matcher of the command `counsel-find-file` to display files matching minibuffer input, allowing to ignore some files based on the variable `counsel-find-file-ignore-regexp`. It is possible to use another matcher by setting the variable `counsel-projectile-find-file-matcher`. Some choices are proposed if you use the Customize interface, in particular the `counsel-projectile-find-file-matcher-basename` matcher which is provided by counsel-projectile and only displays files whose basename matches the minibuffer input (if there is none, it shows all matching 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`
|
- `counsel-projectile`
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,35 @@ If anything goes wrong, throw an error and do not modify ACTION-VAR."
|
||||||
|
|
||||||
;;;; counsel-projectile-find-file
|
;;;; counsel-projectile-find-file
|
||||||
|
|
||||||
|
(defcustom counsel-projectile-find-file-matcher 'counsel--find-file-matcher
|
||||||
|
"Function returning candidates matching minibuffer input in
|
||||||
|
`counsel-projectile-find-file', also used to match files in
|
||||||
|
`counsel-projectile'.
|
||||||
|
|
||||||
|
Several choices are proposed:
|
||||||
|
|
||||||
|
- Ivy generic matcher (`ivy--re-filter'). This is the matcher
|
||||||
|
used by default in all ivy commands.
|
||||||
|
|
||||||
|
- Counsel matcher (`counsel--find-file-matcher'). This is the
|
||||||
|
matcher used in `counsel-find-file', allowing to ignore some
|
||||||
|
files based on `counsel-find-file-ignore-regexp'.
|
||||||
|
|
||||||
|
- Counsel-projectile basename
|
||||||
|
matcher (`counsel-projectile-basename-matcher'). This one only
|
||||||
|
displays files whose basename matches minibuffer input, or if
|
||||||
|
there is none all files whose name (relative to the project
|
||||||
|
root) matches. It also uses the counsel matcher to ignore some
|
||||||
|
files.
|
||||||
|
|
||||||
|
It is also possible to use a custom matcher. It must be a function taking two argument, the regexp and the candidates (see e.g. `counsel--find-file-matcher')."
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Ivy generic matcher" ivy--re-filter)
|
||||||
|
(const :tag "Counsel matcher" counsel--find-file-matcher)
|
||||||
|
(const :tag "Counsel-projectile basename matcher" counsel-projectile-find-file-matcher-basename)
|
||||||
|
(function :tag "Custom function"))
|
||||||
|
:group 'counsel-projectile)
|
||||||
|
|
||||||
(counsel-projectile--defcustom-action
|
(counsel-projectile--defcustom-action
|
||||||
'counsel-projectile-find-file
|
'counsel-projectile-find-file
|
||||||
'(1
|
'(1
|
||||||
|
|
@ -261,6 +290,41 @@ If anything goes wrong, throw an error and do not modify ACTION-VAR."
|
||||||
"switch project"))
|
"switch project"))
|
||||||
'counsel-projectile)
|
'counsel-projectile)
|
||||||
|
|
||||||
|
(defun counsel-projectile-find-file-matcher-basename (regexp candidates)
|
||||||
|
"Return the list of CANDIDATES whose basename matches REGEXP,
|
||||||
|
or if there is none the list of all CANDIDATES matching REGEXP.
|
||||||
|
Also uses `counsel--find-file-matcher' to ignore candidates based
|
||||||
|
on `counsel-find-file-ignore-regexp'."
|
||||||
|
(let ((cands (ivy--re-filter regexp candidates)))
|
||||||
|
(or (and (not (string= ivy-text ""))
|
||||||
|
;; We first filter `cands' to retain only matches in file
|
||||||
|
;; basename. This is almost copied from `ivy--re-filter'
|
||||||
|
;; because we can't quite use it directly.
|
||||||
|
(let ((re-list (if (stringp regexp)
|
||||||
|
(list (cons regexp t))
|
||||||
|
regexp))
|
||||||
|
(res cands))
|
||||||
|
(dolist (re re-list)
|
||||||
|
(setq res
|
||||||
|
(ignore-errors
|
||||||
|
(funcall
|
||||||
|
(if (cdr re)
|
||||||
|
#'cl-remove-if-not
|
||||||
|
#'cl-remove-if)
|
||||||
|
(let ((re-str (car re)))
|
||||||
|
(lambda (x)
|
||||||
|
(string-match re-str
|
||||||
|
(file-name-nondirectory x))))
|
||||||
|
res))))
|
||||||
|
;; We then apply `counsel--find-file-matcher' to `res'
|
||||||
|
;; so we can honor `ivy-use-ignore', but we don't need
|
||||||
|
;; to filter again.
|
||||||
|
(counsel--find-file-matcher nil res)))
|
||||||
|
;; We apply `counsel--find-file-matcher' to `cands' so we can
|
||||||
|
;; honor `ivy-use-ignore', but we don't need to filter
|
||||||
|
;; again.
|
||||||
|
(counsel--find-file-matcher nil cands))))
|
||||||
|
|
||||||
(defun counsel-projectile-find-file-action (file)
|
(defun counsel-projectile-find-file-action (file)
|
||||||
"Find FILE and run `projectile-find-file-hook'."
|
"Find FILE and run `projectile-find-file-hook'."
|
||||||
(find-file (projectile-expand-root file))
|
(find-file (projectile-expand-root file))
|
||||||
|
|
@ -303,7 +367,7 @@ With a prefix ARG, invalidate the cache first."
|
||||||
(projectile-maybe-invalidate-cache arg)
|
(projectile-maybe-invalidate-cache arg)
|
||||||
(ivy-read (projectile-prepend-project-name "Find file: ")
|
(ivy-read (projectile-prepend-project-name "Find file: ")
|
||||||
(projectile-current-project-files)
|
(projectile-current-project-files)
|
||||||
:matcher #'counsel--find-file-matcher
|
:matcher counsel-projectile-find-file-matcher
|
||||||
:require-match t
|
:require-match t
|
||||||
:sort t
|
:sort t
|
||||||
:action counsel-projectile-find-file-action
|
:action counsel-projectile-find-file-action
|
||||||
|
|
@ -1071,10 +1135,11 @@ action."
|
||||||
(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'.
|
||||||
|
|
||||||
Relies on `ivy--switch-buffer-matcher' and
|
Relies on `ivy--switch-buffer-matcher' for buffers and the
|
||||||
`counsel--find-file-matcher'."
|
matcher specified in `counsel-projectile-find-file-matcher' for
|
||||||
|
files."
|
||||||
(append (ivy--switch-buffer-matcher regexp counsel-projectile--buffers)
|
(append (ivy--switch-buffer-matcher regexp counsel-projectile--buffers)
|
||||||
(counsel--find-file-matcher regexp counsel-projectile--non-visited-files)))
|
(funcall counsel-projectile-find-file-matcher regexp counsel-projectile--non-visited-files)))
|
||||||
|
|
||||||
(defun counsel-projectile-action (name)
|
(defun counsel-projectile-action (name)
|
||||||
"Switch to buffer or find file named NAME."
|
"Switch to buffer or find file named NAME."
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue