reddit / emacs
Orderless + Corfu: Make '*' the component separator?
Desmesura · 2022-01-31 15:18
I'm using these two amazing packages for my completion set-up. Here's my config for them:
(setq corfu-auto t
corfu-quit-no-match t
corfu-quit-at-boundary t)
(setq completion-styles '(orderless)
completion-category-defaults nil
orderless-component-separator "*")
(add-hook 'minibuffer-setup-hook
(lambda () (setq-local orderless-component-separator " ")))
Basically this means that for in-buffer completion, the `*` character is used as separator for substrings, and for minibuffer completion this character is `SPC` instead.
I really cannot understand how anyone would keep `corfu-quit-at-boundry` to `nil`, plus `SPC` as the default component separator. Writing code like this is hell, every time I press space after defining a new variable, corfu keeps searching for an existing variable instead.
The problem with my configuration is that `*` is sometimes (e.g. in `php-mode`) seen as a non-word character and therefore completion stops after inputting it. Is there a way to add `*` to the character list considered to be a word? For example, this setup does work in `shell-mode`.
Thanks a lot in advance!
krjonovo · 2022-01-31 17:55
I don't know the exact answer but I can point you to syntax-tables. There should be some variable like `php-mode-syntax-table` and you should change it so that `*` is considered to be an element of a word.
Maybe this wiki page can help with the details [https://www.emacswiki.org/emacs/EmacsSyntaxTable](https://www.emacswiki.org/emacs/EmacsSyntaxTable)
Desmesura · 2022-01-31 19:43
Nice, I supposed it had to do with the specifics of how Emacs handles syntax for the different languages. Thanks for the lead, I'll research further
EDIT:
Although now that I think about it maybe changing something like this: changing `*` to be a `word` instead of `punctuation`, messes other things up such as syntax hightlighting or some `lsp` functionality.
Maybe I should think about what character would work the best as component separator, for all languages...
abbreviatedman · 2022-02-01 05:30
You've got me thinking about it, and I've come to the same general solution area: finding a character that works as a good separator that is also NOT a word boundary in any language--or, at least, not in many.
`_` is my current thought!
Desmesura · 2022-02-01 10:24
I was literally thinking the same, searching for a character like that. It looks like `_` would be a good option. The only caveat I can think about is for some languages in which symbol's contain `_` (e.g. shell script), you might get some unexpected matches.
E.g. you might be writing: `do_some` and you get as matches: `do_some_one` `do_some_two`, `something_done`, `something_to_do`, etc.. While you'd normally just want the first two, since you meant the `_` literally, not as a component separator.
Although it's probably still the best option.
abbreviatedman · 2022-02-02 03:10
N of 1, but `_` worked well enough for me today that I may remap my keyboard to make it more convenient.
JDRiverRun · 2022-02-03 02:33
I use orderless + corfu in buffer with SPACE as the separator fairly happily. The key for me was to setup a [corfu-commit-predicate](https://github.com/minad/corfu/wiki#auto-commit) that aggressively commits when:
1. A selection was made, aside from entering SPACE.
2. Just one candidate exists, and we continue to non-symbol info.
3. The 1st match is exact, and we have continued typing.
"Commit" means accept the selected result btw. This still leads to "false positives", i.e. when a space means "I'm done with this leave me alone", but I stand ready with C-g in those cases. Since I also use orderless with vertico in the minibuffer and other places, it would be a mental burden to switch from SPACE to some other separator character.
Desmesura · 2022-02-03 10:18
Thanks for the info! I don't know why I skipped on that when reading the docs/wiki. I'm trying it like this (also setting `corfu-quit-at-boundary` back to `nil`, of course) for now and I'll see if it feels right.
JDRiverRun · 2022-02-04 00:28
As you'll probably find, there are still lots of false positives. And as the corfu developer points out, a fine-tuned solution isn't too useful for the general orderless + corfu combo.
I had another thought based on your post: find a unicode character that is in the word syntax table, that could serve as a good visual orderless separator, and bind it to `S-SPC`. I also want it to be in my main buffer font to keep line height from changing. There are many choices, but I settled on:
(setq orderless-component-separator "\u268b")
(global-set-key (kbd "S-SPC")
(lambda () (interactive) (insert #x268b)))
Desmesura · 2022-02-04 13:13
Damn.. actually a great idea... I think I'm switching back again. It still didn't feel right to leave it as SPC. Thanks!
JDRiverRun · 2022-02-04 13:51
I found using this a bit that I actually type S-SPC at the beginning of sentences without knowing it. So I went with your space-in-minibuffer idea, and changed the binding to:
(global-set-key (kbd "S-SPC")
(lambda () (interactive)
(insert (if completion-in-region-mode
#x268b ? ))))
Desmesura · 2022-02-04 15:07
I just set it to "M-SPC" instead, is easier to type and I rarely use the default `just-one-space` command.
JDRiverRun · 2022-02-04 22:44
In that case perhaps just bind it within Corfu's map:
:bind (:map corfu-map
("M-SPC" . (lambda () (interactive)
(insert #x268b))) ; custom orderless sep
("C-S-g" . (lambda () (interactive)
(corfu--goto -1)
(corfu-reset)
(corfu-quit))))
The latter is to revert any input and quit.
JDRiverRun · 2022-02-07 22:14
This discussion led to some [significant improvements](https://github.com/minad/corfu#orderless-auto-completion) that make using corfu and orderless in buffer much easier, especially with auto-complete enabled. As of v0.19, just enter M-SPC for your first separator, and after that, you can use any arbitrary orderless filters. This really cuts way down on the unwanted completion pane issue.
divinedominion · 2022-07-22 07:43
Did you stick with setting the default/global `orderless-component-separator` or have you added this to a hook to only change that during corfu completion?
I'm looking into
(define-key map "\M- " #'corfu-insert-separator)
And using
corfu-quit-at-boundary 'separator
instead
JDRiverRun · 2022-07-22 13:37
All of this has been superseded in recent versions of corfu. Just hit M-SPC for the first orderless separator, and normal space after that.
divinedominion · 2022-07-22 14:02
I see, didn't notice the timeline!