Closed Gleek closed 4 years ago
Hi,
I've been able to hack a small solution using ivy-sort-matches-functions-alist
. But I'm not sure how to apply it to the counsel-projectile-find-file
function.
Adding it to read-file-name-internal
changes the order when running counsel-find-file
to what I expect but doesn't affect counsel-projectile-find-file
.
This is the idea which works loosely on the lines of how I want it to work
(defvar +ivy-project-sort-min-length 1)
(defun +ivy-project-sort--exact-match-file-base-name(name x y)
(cond ((string= (file-name-nondirectory x) name) 1)
((string= (file-name-nondirectory y) name) 2)
(t nil)))
(defun +ivy-project-sort--exact-match-root-name(name x y)
(cond ((string= (file-name-base x) name) 1)
((string= (file-name-base y) name) 2)
(t nil)))
(defun +ivy-project-sort--prefix-match-file-base-name(name x y)
(cond ((string-match-p (concat "\\`" (funcall ivy--regex-function name)) (file-name-nondirectory x)) 1)
((string-match-p (concat "\\`" (funcall ivy--regex-function name)) (file-name-nondirectory y)) 2)
(t nil)))
(defun +ivy-project-sort--match-file-base-name(name x y)
(cond ((string-match-p (regexp-quote name) (file-name-nondirectory x)) 1)
((string-match-p (regexp-quote name) (file-name-nondirectory y)) 2)
(t nil)))
(defun +ivy-project-sort-files(name candidates)
"Assumes all candidates already match name"
(if (>= (length name) +ivy-project-sort-min-length)
(cl-sort (copy-sequence candidates)
(lambda (x y)
(if (eq (or (+ivy-project-sort--exact-match-file-base-name name x y)
(+ivy-project-sort--exact-match-root-name name x y)
(+ivy-project-sort--prefix-match-file-base-name name x y)
(+ivy-project-sort--match-file-base-name name x y)) 2) nil t)))
candidates))
;; FIXME:
;; (add-to-list 'ivy-sort-matches-functions-alist '(read-file-name-internal . +ivy-project-sort-files))
Any help in the modification of the ivy-sort-matches-functions-alist
is appreciated.
Thanks
Ah, seems like I had to write a custom matcher instead. Below is the final code in case anyone is interested. There's probably a better way to write this but this seems to works fine for me.
(defvar +ivy-project-sort-min-length 1)
(defun +ivy-project-sort--exact-match-file-base-name(name x y)
(cond ((string= (file-name-nondirectory x) name) 1)
((string= (file-name-nondirectory y) name) 2)
(t nil)))
(defun +ivy-project-sort--exact-match-root-name(name x y)
(cond ((string= (file-name-base x) name) 1)
((string= (file-name-base y) name) 2)
(t nil)))
(defun +ivy-project-sort--prefix-match-file-base-name(name x y)
(cond ((string-match-p (concat "\\`" (funcall ivy--regex-function name)) (file-name-nondirectory x)) 1)
((string-match-p (concat "\\`" (funcall ivy--regex-function name)) (file-name-nondirectory y)) 2)
(t nil)))
(defun +ivy-project-sort--match-file-base-name(name x y)
(cond ((string-match-p (regexp-quote name) (file-name-nondirectory x)) 1)
((string-match-p (regexp-quote name) (file-name-nondirectory y)) 2)
(t nil)))
(defun +ivy-project-sort-files(name candidates)
"Assumes all candidates already match name"
(if (>= (length name) +ivy-project-sort-min-length)
(cl-sort (copy-sequence candidates)
(lambda (x y)
(if (eq (or (+ivy-project-sort--exact-match-file-base-name name x y)
(+ivy-project-sort--exact-match-root-name name x y)
(+ivy-project-sort--prefix-match-file-base-name name x y)
(+ivy-project-sort--match-file-base-name name x y)) 2) nil t)))
candidates))
(defun +counsel-projectile-find-file-matcher(regexp candidates)
(+ivy-project-sort-files regexp (counsel--find-file-matcher regexp candidates)))
(setq counsel-projectile-find-file-matcher '+counsel-projectile-find-file-matcher)
I have noticed very slight lag when I start typing on very large projects. Seems to run fine for average sized projects.
Anyways, increasing the value of +ivy-project-sort-min-length
should solve for the initial lag by removing any sort.
Closing this. Thank you for this package @ericdanan
Hi, Thank you for the package. I was wondering if it was possible to sort candidates by relevance to the search query, i.e, move the files that are closer to the search query at the top when running
counsel-projectile-find-file
.Setting
(setq counsel-projectile-find-file-matcher 'counsel-projectile-find-file-matcher-basename)
helps by prioritizing the files before sub-directory search but still the sorting order of the files where the basename matches could be improved, imho.Let me explain by an example. Assuming this is the project:
and
(setq counsel-projectile-find-file-matcher 'counsel-projectile-find-file-matcher-basename)
has been executed.Running
counsel-projectile-find-file
here with a stringsuffix
gives these results:In my opinion, the exact matches with the file root should be sorted on top. So the results should be
I'm not sure if such a thing is possible in the current ivy framework. The current
ivy-sort-functions-alist
does provide some sorting mechanism where two files can be compared, but I'm not aware if we could somehow also use the search query to determine the sort. Any pointers in the direction are appreciated. Thanks