How to disable prescient in counsel-find-file?
Hi, for some reason adding find-file or counsel-find-file to a negated list in ivy-prescient-sort-commands has no effect, and the function continues to have its candidates sorted. I can tell it is prescient that is doing this because disabling ivy-prescient-mode automatically disables sorting of find-file. Any ideas on how I can get this to work?
I have configured the variable in the following manner:
(use-package prescient
:config
(setq prescient-save-file (concat acg/history-dir "prescient-save.el"))
(prescient-persist-mode 1))
(use-package ivy-prescient
:after (prescient ivy)
:config
(setq ivy-prescient-sort-commands '(:not swiper swiper-isearch ivy-switch-buffer counsel-find-file counsel-recentf))
(ivy-prescient-mode 1))
(use-package company-prescient
:after (prescient company)
:config (company-prescient-mode 1))
You could check to make sure the command you expect is being run, with C-h k C-x C-f. Aside from that, however, your configuration looks exactly correct and I would suspect a bug in Ivy.
Thank you @raxod502. The function being run is indeed find-file (or counsel-find-file); both calls result in the same Ivy interface, and adding any or both to ivy-prescient-sort-commands has no effect. I also tried adding the many subfunctions that Counsel leverages to find file (like counsel--find-file-1) with no success.
It must be something with the way counsel-find-file works, but I couldn't figure out exactly what. What is strange is that negating counsel-recentf in ivy-prescient-sort-commands works, but not counsel-find-file.
Yeah, I'm afraid I'm not sure what's happening there. It does sure seem like counsel-find-file is getting passed as the CALLER argument to ivy-read. You have probably found a bug in something. See also #65.
Yep. This is almost certainly an edge case. Here
https://github.com/abo-abo/swiper/blob/d2891aab7b816aebf21ebd01ce33933a6ac6244f/ivy.el#L2271-L2317
there's an explicit call to ivy--sorted-files (probably because ivy sorts directories first by default) and it uses (ivy--sort-function #'read-file-name-internal) which evaluates to ivy-prescient--enable-sort-commands. I don't think there's a way to fix this on the ivy side (and I kinda understand why selectrum is a thing now), but we can probs setup a workaround in prescient.
I've managed to get file-name completion back to normal using this:
(add-hook 'ivy-prescient-mode-hook
(defun ivy-prescient-disable-sort-find-file+ ()
(when (and (eq (car ivy-prescient-sort-commands) :not)
(memq 'counsel-find-file
(cdr ivy-prescient-sort-commands)))
(ivy--alist-set 'ivy-sort-functions-alist
#'read-file-name-internal #'ivy-sort-file-function-default))))
but it doesn't disable sorting based on ivy-prescient-sort-commands so it's not really a fix for this issue. It's good enough for my use cases so I'm leaving it here :-).
Is there something similar to disable it for selectrum-prescient.el for certain commands?
@unhammer
There's selectrum-should-sort-p which you can set to nil to disable sorting. However for functions like find-file the sorting already appears to be garbled which makes it kind of useless. If you want ivy like sorting with find-file you can try this:
(defvar selectrum-find-file-keep-prescient-sorting+ nil
"When true, `selectrum-find-file' keeps sorting based on `prescient-sort' but
still tries to group directories before files..")
(defun selectrum-prescient-preprocess+ (func cands)
(cond
;; Finding file-names should sort directories first.
((eq minibuffer-completion-table 'read-file-name-internal)
(if selectrum-find-file-keep-prescient-sorting+
;; WARN: Adapted from ivy, doesn't maintain prescient based sorting
(cl-loop for cand in (funcall func cands)
with dirs = nil
with files = nil
do (if (eq (aref cand (- (length cand) 1)) ?/)
(setq dirs (cons cand dirs))
(setq files (cons cand files)))
finally return `(,@(nreverse dirs) ,@(nreverse files)))
(sort cands
(lambda (x y)
(let ((x-dir (eq (aref x (- (length x) 1)) ?/))
(y-dir (eq (aref y (- (length y) 1)) ?/)))
(cond
((and x-dir y-dir)
(string< (directory-file-name x) (directory-file-name y)))
(x-dir t)
(y-dir nil)
(t (string< x y))))))))
(t (funcall func cands))))
(advice-add 'selectrum-prescient--preprocess :around #'selectrum-prescient-preprocess+)
Just found selectrum-should-sort-p, seems to work for my uses :-)
Is there something similar to disable it for selectrum-prescient.el for certain commands?
See also discussion on the Selectrum side about adding a way to configure completion behavior on a per-command basis: https://github.com/raxod502/selectrum/issues/265
Fair warning, it is nontrivial, assuming that we actually want to do it in a reliable and not-surprising-to-the-user way, rather than as a hack.