-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API deprecation discussion #443
Comments
Thanks, good to have an issue about it. Regarding the faces there is a pending PR on the prescient side. Regarding |
Sure, I just thought I mention it. Maybe some of the internals around this feature could be simplified, but I would have to give it a try to see if there exists a potential for improvements. For example one simple change could be to just use the default minibuffer completion table (instead of a dynamic candidates function) and flag it as dynamic, such that it is called for every keypress. This dynamic flag feature could then be used for dynamic minibuffer tables (#114), if it is decided to special case some of them at some point. |
Maybe it's also okay to keep them? They don't conflict with the completing-read API as far as I know. |
Okay sure, my motivation to internalize them is only to discourage its use in favor of annotation functions. But maybe it is justified to keep them. I do not feel so strongly about that. |
Okay good, I think @raxod502 wanted to keep them but maybe his opinion has changed with the new situation and generally improved eco system surrounding Selectrum. |
Some update regarding the selectrum-dependent packages:
;;; -*- lexical-binding: t -*-
;; consult--sync wrapper, maybe make this part of Consult
(defun consult--sync (fun)
(let ((async (consult--async-sink)))
(lambda (action)
(pcase action
('setup
;; consume the full input, no completion style filtering!
(consult--split-setup (lambda (input _) (list input "" 0)))
(funcall async 'setup))
((pred stringp)
;; flush the old candidates, generate new candidates and refresh
(funcall async 'flush)
(funcall async (funcall fun action))
(funcall async 'refresh))
(_ (funcall async action))))))
;; Usage example
(consult--read
(consult--sync (lambda (input)
(list (format "%s1" input)
(format "%s2" input)
(format "%s3" input))))) The only thing which is really hard/inefficient to emulate using Consult is this input rewriting which Selectrum offers. As long as the input string splitting is separate from the candidate generation step everything is fine (e.g. the splitting of |
For reference, the emulation would look like this: (defun dynamic-candidates (input)
`((candidates . (,(format "foo %s 1" input)
,(format "foo %s 2" input)
,(format "foo %s 3" input)))
(input . "foo")))
(selectrum--read "Test: " #'dynamic-candidates)
(defun consult--emulate-selectrum (fun)
(let ((async (consult--async-sink)))
(lambda (action)
(pcase action
('setup
(consult--split-setup (lambda (input _)
(let ((ninput (alist-get 'input (funcall fun input)))) ;; FIRST CALL!
(list input ninput (length ninput)))))
(funcall async 'setup))
((pred stringp)
(funcall async 'flush)
(funcall async (alist-get 'candidates (funcall fun action))) ;; SECOND CALL!
(funcall async 'refresh))
(_ (funcall async action))))))
(consult--read (consult--emulate-selectrum #'dynamic-candidates)) |
Hm, it doesn't look like org-z does use the dynamic input feature? In that case it should ideally just pass a dynamic table to |
Yes, but Selectrum does not support that, right? The |
As I proposed before, we may want to consider is to add dynamic candidate table support to Selectrum but only enable it manually via a flag in order to avoid performance regressions. The flag could either be added to the completion metadata, by setting a flag variable before invoking completing-read or in the minibuffer setup hook. (let ((selectrum-dynamic t))
(completing-read ...) The experiments I made above are basically just toy examples to check if the current Consult api is powerful enough to emulate what is missing if the Selectrum api is not to be used directly. This does not mean that people should necessarily use this in the end. |
Yes I agree we should do that, sounds like a good compromise. |
Another idea - We could propose to Emacs upstream to add a |
I like the idea of a dynamic metadata flag, too but I also agree that it would probably hard to get through but we could at least try. There is also the problem with automatically using |
Ideally a dynamic tbale should always be allowed to return any candidates but the way |
Yes, but why would we need that? The dynamic table just takes control over the filtering itself. The only step which we are saving is this preprocessing step? Is this expensive? Maybe it is - sorting all the time. And as soon as you let the completion table do the filtering itself you are bound to use completion styles. Prescient wouldn't work anymore for example, but this could easily be rewritten as a completion style. |
The problem is that |
This does not sound right, I mean Icomplete and default completion work with non-default completion styles like orderless, for example when calling |
Oops you are right, but I currently have no clue why 😆 |
I just edebuged it and it looks like they also pass the empty string for the |
I wonder why then input dependent tables work where you need to pass the input? |
Well it seems this is not supported at all, I don't know why I thought it would be the case. |
I will look into that tomorrow I'm to tired to think right now 😴 |
This is very weird then. You are right, I also checked it. Probably dynamic tables don't really work ;) |
So, these dynamic tables - is this actually only some fantasy? If that's the case then the The documentation (https://www.gnu.org/software/emacs/manual/html_node/elisp/Programmed-Completion.html) is really confusing with respect to that, it talks about the passed in string for the t action. Maybe at some point this was considered as design but never implemented for whatever reason. Obtaining the completions goes through (completion-all-completions "test" (lambda (str pred action)
(message "%S %S %S" str pred action)
(complete-with-action action '(alpha beta gamma) str pred)
) nil 0) But if one uses instead (all-completions "test" (lambda (str pred action)
(message "%S %S %S" str pred action)
(complete-with-action action '(alpha beta gamma) str pred)
)
nil) EDIT: The filtering happens actually in |
Hm the table could also use |
Yes sure. This is basically what Consult is doing. But if the minibuffer-contents are used to generate candidates, then the completion style must also somehow understand this and perform some kind of splitting similar to Consult. |
Well whatever - I guess in the end it boils down to the question if the preprocessing step is worth being separate/cached or not. Have a good night! |
Thanks, I was already sleeping ;) Maybe the behavior depends on completion-boundaries? In that case only tables which return an non empty string would need to be called on each input. |
I don't think boundaries have anything to do with this. This is only meant to restrict the filtering to a certain substring of the input. Does Selectrum handle this correctly? Maybe I could use this for the consult async functionality to split the string such that completion only takes the filter part of |
You can indeed use boundaries to depend on the input: (defun checko (string pred action)
(if (eq (car-safe action) 'boundaries)
(cons 'boundaries
(cons 1 0))
(if (eq action t)
(cond ((string= string "a")
'("a1" "a2"))
((string= string "b")
'("b3" "b4")))
(complete-with-action action nil string pred))))
(completing-read "Check: " 'checko) |
It seems this all assumes file like completion (appending the result to the present input and proceed filtering from there) which is also the only table which depends on input which I actually know about. |
Currently not but I think we could adjust to handle |
I just noticed the example above only kind of works when using orderless. |
On another note, the breaking changes left are the removal of the faces but I think it is okay to postpone this so I will wait now for a while if there are no other unexpected bugs introduced by recent changes and then use the current ad9d9f0 for the 4.0 release. |
It would be nice if this checko example from above would work with Selectrum. I agree with you that it is kind of weird that the returned result is the the concatenation of the prefix string and the completion. But I could actually use that instead of the current Consult async splitting. Maybe this is an improvement over the status quo, where I am using a custom completion style which performs this input splitting, simply ignoring the prefix input. However the current solution is potentially much more flexible since I can do arbitrary splitting of the input string, but in practice as of now only the suffix is used for completion filtering.
Maybe there are more functions you want to internalize, I am not sure? Is there a point in having all these selectrum-read-buffer etc functions public? Maybe there is a point since users want to set these functions as advices/replacements? I think that selectrum--read is certainly the most important piece, but I guess it makes sense to think about the other functions also for a minute. |
I also thought about that but I think it is better to have them public, they can also be used to adjust |
Makes sense. I wonder more about the selectrum-read-buffer, selectrum-read-library etc functions. Assuming that at some point you may want to rewrite some internals - maybe there wouldn't be the need for selectrum-read-buffer anymore. Why is this needed - I assume to handle this SPC prefix for ephemeral buffers? Maybe given some more adjustments to Selectrum internals the default read-buffer function would just work as is? In Consult I am doing this filtering by adjusting the minibuffer predicate, I wonder how the default read-buffer function handles this. |
Okay, I just checked. There is the variable |
It would be nice if we could remove the custom read buffer function but I just checked and when completing internal buffers with default completion it also bypasses completion styles (probably uses all-completions), so we need to keep our custom version unfortunately. |
|
Thanks for updating the wiki! |
I tried your checko example from above again and it would actually nice if there would be some limited support for completion boundaries in Selectrum. (defun grep-test (string pred action)
(if (eq (car-safe action) 'boundaries)
(cons 'boundaries
(cons
(if-let (pos (seq-position string ?#))
(1+ pos)
(length string)) 0))
(complete-with-action action '(alpha beta gamma) "" pred)))
(completing-read "Grep: " #'grep-test) If you enter |
Okay, I close this issue then! |
I don't think there is an issue yet discussing potential upcoming API changes/deprecations. This is a list of things I stumbled upon. Maybe not all of these suggestions are useful and I probably missed a few changes which you are already planning.
Deprecate and rename(DONE in Private api #446)selectrum-read
toselectrum--read
in favor ofcompleting-read
selectrum-candidate-display-*
, if they are still needed or remove them altogether?selectrum--read
API, currently there seems to be a mix of using setq in a minibuffer setup hook and passing arguments toselectrum--read
.selectrum--dynamic-candidates
which could possibly be removed in favor of using a default completion-table+dynamic-flag or by rewriting the current selectrum functions which make use of this dynamic-candidates feature in other ways (probably this is difficult given the hoops I had to jump through to make Consult narrowing work etc).The text was updated successfully, but these errors were encountered: