-
-
Notifications
You must be signed in to change notification settings - Fork 99
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
Use full affixation-function annotations in consult--multi #565
Comments
As mentioned in #5 (comment) you can specify prefixes and suffixes with
I see. Note that truncating the candidates themselves is not supported or support is at least unclear. In principle the API would allow this but the default completion system doesn't handle this well if I recall correctly. Also I am not sure how well Vertico/Selectrum etc handle this. See also minad/vertico#198 where the candidate truncation issue was discussed for recent files. As of now it is unlikely that I will expose the
Anyway, feel free to investigate this further! Maybe we come up with some functional proposal. But there are implications across multiple of my packages which need to be sorted out first. This is definitely a downside of the approach of relying on existing APIs and trying to find a common denominator. It can happen that you hit the limitations (or under specifications) of the existing APIs and then there is not much we can do. |
I forgot to mention the most important argument why I am against truncating candidates - my reasoning is that the candidate itself is always more important than the annotation. This means if we are out of space it is always better to truncate the annotation. You may disagree with me on that (I think @jdtsmith also disagreed on that in minad/vertico#198), but that's at least my justification to not touch or truncate the candidates, besides the technical issues mentioned before, which may or may not hold. The candidate is the string we are matching against and the candidate is highlighted by the completion style. |
I agree with this in almost all contexts, except one. IMO the long path of a recentf file candidate doesn't deserve that full protection. The path of a buffer file is part of its annotation, and find file visits only a single path at a time. So only for recentf files is the full path considered "part of the candidate". I use this as arg-filter advice to (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 30 (- (window-width) (consult--display-width (nth 2 args)))))
(l (length arg))
((> l w)))
(setcar args (concat "…" (truncate-string-to-width arg l (- l w)))))
args) The fact that the candidate is modified for display only at the last minute means you can still match text which is truncated/not displayed (which is either a feature, or confusing depending on your outlook). But it keeps annotations nicely aligned: I do wish vertico would reformat the candidates for display on frame size changes, since an easy way to see more is to expand the frame. For now I add+remove a character from the search to force reformatting. |
@jdtsmith that's a very elegant solution -- I really like it. I might allow for something similar in my project. |
I think you can always overwrite/modify the candidate with a display/invisble property, e.g., for recent files it should be possible to make the path of the file invisible and only keep the file name. This would allow you to shorten the candidates but of course it wouldn't auto resize depending on the window width. But maybe you could achieve the same with the affixation function by modifying the candidate there (not the string itself), but only propertizing it. Then it would even work dynamically depending on window width since the affixations are recomputed by vertico in the post-command-hook. Maybe then it would be needed to open up the consult--read API to support lists of candidates. |
Btw, I just realized that The issue here is that we break the alignment then. Therefore I reverted this for now. This was probably the reason why I originally didn't support affixations for Any proposals how this could be solved? The answer is probably that the UI should handle this, but this is out of the question due to the weakness and limitations of the affixation API. This issue won't be solved without introducing a better API which pushes the presentation entirely to the UI (the aforementioned hypothetical decorations API). |
My first intuition is that it could be handled similarly to the current relationship between candidates and annotations which appear to their right: by having an alignment string interpolated between them. So EDIT: had a look at this and I can't see how a similar approach to the alignment we use already could work, without either:
Neither is a great approach. To be honest though, in other areas of emacs, alignment like this is left up to the author of the particular function (that is, alignment should be done by making all the annotations the same length). Indeed, it is even up to the author whether they want alignment (sometimes they don't. See the binding annotations in |
Hmm, we could use an affixation function which takes a list and then computes the alignment for all the candidates. This would also work for consult--multi, but then we would have to add full affixation support to consult--read. But I must say I am also not a fan of prefixes anyway. Prefixes seem mostly useful for icons but not for many other things. |
I've heard of people using them for line numbers... 🙄 |
My intention was time-length strings (e.g. |
I would certainly be happy with this as a solution, though I don't know enough (yet!) about consult's internals to know how to implement it. It would work perfectly well though. |
consult-line uses affixation prefixes for line numbers :) |
@minad Damn, you saw my comment before I could delete it. |
Okay, I guess I will bite the bullet and implement alignment directly in |
This would be absolutely amazing. I'm happy to help in any way if I can, but I'm sure you'll do a better job than I could. |
Okay, I tried this in a separate branch 8504f10. The result is not satisfactory at all. It doesn't simplify a bit for the existing Consult |
There is one compromise we could make - we could still support prefixes and suffixes, I mean just pass them through and leaving alignment up to the user (as was suggested in #565 (comment)). But this will potentially lead to an ugly result in the end and hurt composability of sources. I must admit, I don't find the use case in #565 (comment) very convincing. Why not put the time stamp in the suffix? I kind of like that we have suffixes only and the candidates in the front. There are a few special exceptions like icons, line numbers in consult-line etc. Maybe the short time stamp in a music player is a similar special case? |
The only way out I am seeing is via a new API which moves all the alignment work on to the frontend. If someone proposes and implements a patch in Emacs itself (the aforementioned Let me summarize the situation:
All these points hint at that we should move the entire alignment and truncation business to the frontend instead of scattering across backends and middleware. Advanced frontends (e.g. Embark collect tabulated list mode) would in principle even let the user resize columns. I should add, the compromise #565 (comment) is still something I would find at least somewhat acceptable. It leaves the principle intact, that |
But it seems that those types of prefixes should be quite straightforward to format at a constant width? |
This seems eminently sensible. So just pass the display front end a vector of n parts, and some instructions about how to align them (minimum-width, right-/left-/center-align, truncate-from-left/truncate-from-right/no-truncate)? But if only the currently displayed rows are passed to the front-end, there will still be sliding around as you scroll I'd guess. And presumably passing all of them to compute stable alignment up front would be expensive, though you could have a cutoff at 500 or whatever. What if alignment "suggestions" could be encoded as special text properties in the string, for the front end to respect or just ignore? These properties could indicate column breaks, alignment, min/max width, truncation, etc. That way non-compliant front-ends would still display normally. |
Of course. The timestamps are constant width. The issue is that you cannot compose different sources with different prefix width. The solution I tried above was to dynamically compute the maximum width and then align, but this has many disadvantages.
Yes, exactly. That's more or less what I had in mind for the One could start implementing an x-decoration-function extension in Vertico and use it in Marginalia. But at some point this is growing over the top since we would need fallbacks for the annotation-function and the affixation-function. One could also consider implementing a middleware which sits between Vertico and Marginalia/Consult which translates x-decoration-function to the affixation function. |
Do you mean fallbacks in case they attempt their own alignment? I always thought having annotation/affixation try to achieve alignment was a violation of separation of content and presentation. Like an HTML table cell setting its own width. |
No, I mean fallbacks for UIs which don't implement the more advanced API. |
I would like to be able to return a list from the function used for
:annotate
in a call toconsult--multi
, as I currently can withconsult--read
. There are two reasons:First, my use-case for
consult--multi
includes a lot of very long strings. The current annotation mechanism can deliver pretty much everything I need (and does vertical alignment for me, which is great), but vertically aligning the annotations at the end of the longest candidate puts them off-screen to the right. The greater control of affixation-function lets me truncate the candidates themselves too. I know I could build this truncation into the way the list of candidates is generated in the first place, but this seems wrong somehow. I might want to reuse the functions for getting candidate lists elsewhere, and then might need a truncated and non-truncated version for example.Second, I would like to display some metadata as a prefix to each candidate, which as far as I can tell is currently impossible. (well, I might be able to fiddle manually with display properties, but again, this feels like a bit of a hack).
Is this possible/feasible? Or am I just missing some already existing way of doing this?
The text was updated successfully, but these errors were encountered: