Closed gety9 closed 9 months ago
This is not an Orderless issue. In the issue on reddit, the candidates are generated by consult-ls-git, which is responsible for the filtering and sorting.
This is out of scope for orderless since orderless only deals with strings and has no idea what a file path is!
Fortunately, Orderless is highly configurable, so users can handle this sort of thing in their own configuration. For example:
(defun match-only-file-name (pattern _index _total)
(when (string-prefix-p "/" pattern)
(cons 'orderless-regexp
(rx (group (literal (substring pattern 1)))
(zero-or-more (not ?/)) string-end))))
(push #'match-only-file-name orderless-style-dispatchers)
This makes /ll
match ll
but only if there are no slashes after it, i.e., in the file portion of a file path. You can make different choices: for example you could decide not to require any special prefix and to always use the style when you are matching files (which requires knowing what completion category is indicated by the commands you want to use it for):
(defun match-only-file-name (pattern _index _total)
(when (memq (completion-metadata-get
(completion-metadata
(buffer-substring-no-properties
(minibuffer-prompt-end)
(max (minibuffer-prompt-end) (point)))
minibuffer-completion-table
minibuffer-completion-predicate)
'category)
'(file project-file)) ; add whatever categories you need
(cons 'orderless-regexp
(rx (group (literal pattern))
(zero-or-more (not ?/)) string-end))))
Please let me know if you need help tweaking those style dispatchers for your exact use case.
(By the way, rx
is growing on me. I haven't memorized the syntax and still lookup its docstring every time I use it, but while I find writing regexps easier, I vastly prefer reading rx
calls.)
@oantolin The matcher you wrote will work nicely for filtering in recentf-open (or post filtering in consult-fd or consult-ls-git), but iiuc this is not what the issue is about, see https://www.reddit.com/r/emacs/comments/1758q2c/consultvertigoorderless_how_to_not_include/. I think the goal is to change the way fd or git find and order the files.
Maybe, @minad, I'm not sure. I had interpreted this issue and that reddit post as asking two slightly different things: this issue asks to match only in the file name part and that reddit post talks about scoring, giving file name matches priority.
@oantolin thank you for the code, you interpreted me right
@minad you are right, reddit post was on "consult-ls-git" :) i didn't even notice. I was talking about regular recentf (in find-file or consult-buffer)
@oantolin
I just now get back home (had small vocation), and tested the code you've suggested. Not working for me: query for "cfg" should've brought only binv__cfg.toml (but it also brings files in /Books/AppCfg/ dir (all of them are in this folder, it's just that i truncate long names))
Same for other queries.. ex "binv" should've brought only files having binv in name (but it also brings other files in "Binv" dir)...
Could pleaese tell what am i doing wrong?
Config:
(use-package consult
:config
(consult-customize
consult-buffer :preview-key ">"
consult-line :preview-key ">"))
(use-package embark
:demand t)
(use-package embark-consult)
(defun my/vertico-truncate-candidates (args)
(if-let ((arg (car args))
(type (get-text-property 0 'multi-category arg))
((eq (car-safe type) 'file))
(w (max 25 (- (window-width) 55)))
(l (length arg))
((> l w)))
(setcar args (concat "…" (truncate-string-to-width arg l (- l w)))))
args)
(advice-add #'vertico--format-candidate :filter-args #'my/vertico-truncate-candidates)
(use-package vertico
:init
(vertico-mode))
(use-package marginalia
:init
(marginalia-mode))
(defun my/match-only-file-name (pattern _index _total)
(when (memq (completion-metadata-get
(completion-metadata
(buffer-substring-no-properties
(minibuffer-prompt-end)
(max (minibuffer-prompt-end) (point)))
minibuffer-completion-table
minibuffer-completion-predicate)
'category)
'(file project-file))
(cons 'orderless-regexp
(rx (group (literal pattern))
(zero-or-more (not ?/)) string-end))))
(use-package orderless
:demand t
:init
(setq completion-styles '(orderless)
orderless-smart-case nil
read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t
completion-ignore-case t)
:config
(push #'my/match-only-file-name orderless-style-dispatchers))
Imho from user experience point of view in 95% of the cases if person searching for file he wants only to match file name (it's file search, not directory search)
I my opinion it should be default, if not at least to have option to set it to true with setq / customize.
Here is person trying to achieve same thing https://www.reddit.com/r/emacs/comments/1758q2c/consultvertigoorderless_how_to_not_include/ (seems like it's possible with custom dispatacher... but shouldn't it be easier to set (if not default?))