Closed WeissP closed 3 weeks ago
@WeissP your number 3 above is already the case. When there are other candidates found like your example above, then you can put the cursor on the minibuffer input itself (and not any candidates) and hit enter (or maybe shift+enter depending on your vertico or other completion setup) then the input string is taken as a new item, and it is passed to the :on-new
function. You can even do this before any potential candidates are found. I show this in the screenshot below. The first time I wait for candidates to get populated, but the second time I don't wait. I just hit enter right away and that selects the input and uses it as a new item:
@WeissP For the rest of your feature request here is my response:
I thought about what you are asking before, but in most cases, it really does not make sense to try to guess what the user wants when they type in a non-existing candidate in a multi-source search. This is because in this case consult--read
only returns the string that the user types and no metadata. So we have to do extra work to guess what the user meant. Is this a new candidate for a new note or a new candidate for a goolge search, etc.? This is somewhat what the current implementation does, but instead of using the sources in the search we define all the possible options of what to do with the new candidate in consult-omni-default-new-function
(see number 1 below for explanation).
Now for your work flow, I do not understand why you want to start with a multi-source search and then narrow down to just one. Why don't you simply call the interactive command for that one source if you know you want to narrow down to it anyway?
Depending on the answer you have different options.
If you are simply trying to streamline your workflow and always start with the same command, then you can:
(add-to-list 'consult-omni--search-engine-alist '("new note" . #'consult-omni--notes-new))
Note that the first element above is the name you get presented with and the second element is the function that the candidate will get passed to (in this case the candidate would be the string you type in the minibuffer for the new candidate).
Beyond that you can also hack your own solution by defining a new function and binding consult-omni-default-new-function
to it. If you want you can then figure out the state of consult narrow down and find the relevant sources and get their :on-new
functions from consult-omni-sources-alist
by calling consult-omni--get-source-prop
with the name of the source and :on-new
as prop. Then query the user to pick from one of the sources and pass your candidate to the :on-new function for that source. I won't implement this as a general solution in the package because I think the current solution with number 1 above is more meaningful and more flexible and customizable. For example it can be that the user starts a search and does some narrow down, but still decides to run that as a new search on google at the end. So instead of forcing the choices of what to do with the new item based on narrowed state, we just use a function that can do anything the user wishes. Of course in this case the user has to customize things to get the exact behaior they want, but one line of elisp her and there is not too bad for the kinf of users that choose to use consult-omni
.
If there is some reason number 1 and 2 are not good enough, you always have the option of embark-become
. You can start with a multi-source search and narrow down and when you are done run embark-become
and change it to the single-source command.
Thanks for the detailed response!
I do not understand why you want to start with a multi-source search and then narrow down to just one. Why don’t you simply call the interactive command for that one source if you know you want to narrow down to it anyway?
I may have a slightly different usage. I treat this great package as a way to combine synchronous and asynchronous consult sources (but not a web search engine). Right now I have placed all common sources together as my most frequent search backend. With the same idea, I also don't want to remember different shortcut keys to create new items for different sources. And as I described above, I also don't like the idea of narrowing down to a single source :)
Here is what I did for the second idea.
(defun consult-omni--choose-new (cand &rest args)
"Create a new item based on the chosen source."
(interactive)
(let* ((source (completing-read
"Create a new item on source: "
consult-omni-multi-sources))
(action (consult-omni--get-source-prop source :on-new)))
(funcall action cand)))
(setq consult-omni-default-new-function #'consult-omni--choose-new)
I created this issue because I thought it was a common requirement, but based on what you replied, maybe it’s not. However, anyone who happens to have a similar usage can just copy and paste my code above :)
I may have a slightly different usage. I treat this great package as a way to combine synchronous and asynchronous consult sources (but not a web search engine). Right now I have placed all common sources together as my most frequent search backend. With the same idea, I also don't want to remember different shortcut keys to create new items for different sources. And as I described above, I also don't like the idea of narrowing down to a single source :)
That makes sense. I think for the example funciton above, one should add some checks to see which sources have :on-new
and only use them in comspleting-read
and perhaps also check if the action is a function e.g. (if (funcitonp action) ...)
just to make a it a bit more robust and uinversally applicable.
Another useful suggestion would be to add the function above under "Other" category to the search engine alist for people who want to keep both the web engines as options for new items. So it would look like this:
(defun consult-omni--choose-new (cand)
"Create a new item based on the chosen source."
(interactive)
(let* ((sources (cl-remove-duplicates (delq nil (mapcar (lambda (item)
(when-let ((new (consult-omni--get-source-prop item :on-new))
(name (consult-omni--get-source-prop item :name)))
(when (not (eq new #'consult-omni--default-new))
(cons name new))))
consult-omni-multi-sources))))
(action (consult--read sources
:prompt "Create a new item on source: "
:lookup #'consult--lookup-cdr
)))
(if (functionp action)
(funcall action cand)
(error "Do not know how to make a new item for that source!"))))
(add-to-list 'consult-omni--search-engine-alist '("Other" . #'consult-omni--choose-new))
I think, it might be a good idea to add this to the default value for consult-omni--search-engine-alist
. I am going to do that in the develop now perhaps with some better naming convention.
I am going to do that in the develop now perhaps with some better naming convention.
Really looking forward to it!
First thanks for creating such a COOL package, I really like it!
Is your feature request related to a problem? Please describe. If I run a single
consult-omni
source, theon-new
action can be executed perfectly. However, noon-new
actions will be executed if they come from multiple sources, because the new item will be forwarded toconsult-omni-default-new-function
.For me personally, this doesn't help in most cases.
Describe the solutions you'd like
consult
, I normally first narrow down to a single source, and then the correspondingon-new
action can be executed. However, it is actually not that intuitive, as it is always easy to forget to first narrow the sources and then pressreturn
.consult-omni-default-new-function
, which will prompt you to choose a source and execute theon-new
action of that source. I personally like this idea the most.(consult-omni-notes-search "emacs")
, it will show:where the last item is not a note but an action to create a new note named "emacs".