greghendershott / racket-mode

Emacs major and minor modes for Racket: edit, REPL, check-syntax, debug, profile, packages, and more.
https://www.racket-mode.com/
GNU General Public License v3.0
681 stars 93 forks source link

Show some documentation when hovering #716

Closed greghendershott closed 1 month ago

greghendershott commented 2 months ago
          @greghendershott Hello, it's been 8 years I know but because I use Racket and Emacs, so here's a few things. I agree with you that `eldoc` on the echo just to see the structure of the s-expression doesn't really have much. But, one can do much more with `eldoc`. Below is a screenshot of a Rust source file where I can get information about anything (keyword or expression) just by hovering it:

pic-selected-240827-0346-37

This is done through eldoc which is getting the necessary stuff from rust-analyzer which is being managed through eglot and then put into a nice hovering box using eldoc-box. I think this can be put to good use alongside the excellent documentation that Racket already holds. Moreover, this also works for one's own local definitions:

pic-selected-240827-0351-26

This works similarly with Haskell using haskell-mode as well. I am not really sure how one might integrate this with racket-mode, but if you can share your thoughts on this and maybe guide a bit on how to make eldoc talk to Racket documentation I could try for implementing this.

Originally posted by @divyaranjan1905 in https://github.com/greghendershott/racket-mode/issues/199#issuecomment-2311517636

greghendershott commented 2 months ago

I can look at this again.

I just realized racket-xp-describe does exactly the same thing in a separate buffer, all that needs tobe done is channel it to the eldoc-box childframe.

Well, racket-xp-describe is rendering the complete HTML page in an Emacs buffer, and positioning you on the item in that page -- just like "normal" Racket help does. Generally, that's best, because:

A good example is match. That's why eventually I decided the separate buffer is the only UX that works well in all cases. (Note also that the company completion framework takes the approach of showing docs in a separate buffer.)

What's more likely to fit in a screen is the "bluebox" summary contract. (So named because they used to be styled blue; these days it's more like a grey box.) However that lacks any of the summary text, like "Subcommand for dealing with peer" in your Haskell doc example.

You can imagine things like, "Well, just include the bluebox plus the first paragraph of text", as a warm bowl of porridge. But there will still be examples where that doesn't work.

So I'm entirely open to improving this -- to showing more than "improted from module" etc. in the tooltip -- I'm just not sure how, yet.

greghendershott commented 2 months ago

I can imagine adding an option that automatically shows the full doc buffer in another window, without stealing the focus from the edit buffer (without changing the active window).

So it would be roughly the same result as if you moved through the .rkt buffer, after some small delay chose racket-xp-describe, and in that other window chose other-window to move back to the .rkt buffer. But of course without the annoyance of manually choosing racket-xp-describe and other-window. You would just move, and after you pause at a certain point long enough, this would happen automatically.

That would not be the child frame UX -- which looks spiffier but has the drawbacks I mentioned above for Racket documentation.

greghendershott commented 1 month ago

Note: Already you can (setq-local eldoc-documentation-function #'racket-xp-eldoc-function) to show "blueboxes". Have you tried this? Does it work OK for you with eldoc-box?

greghendershott commented 1 month ago

I'm getting up to speed on the latest eldoc. (The last I looked at it was when I was using Emacs 25.)

I see now it:

This all sounds great. Especially the last point, because, although getting the "bluebox" signature summaries is fairly fast, it can be slower to fetch full documentation and massage the HTML to render well in an Emacs buffer.

So what I'm exploring right now:

So far this seems to be working well with the vanilla Emacs UX. I plan to try eldoc-box soon, too.

divyaranjan1905 commented 1 month ago

Note: Already you can (setq-local eldoc-documentation-function #'racket-xp-eldoc-function) to show "blueboxes". Have you tried this? Does it work OK for you with eldoc-box?

The setting you prescribed, doesn't seem to do anything for me, I don't see any blue box.

divyaranjan1905 commented 1 month ago
* Default `eldoc-documentation-functions` to just the short bluebox summaries -- but of course a user (like you) could configure for full docs.

So far this seems to be working well with the vanilla Emacs UX. I plan to try eldoc-box soon, too.

@greghendershott Sounds great, anything you need help with? I've done a thing or two with eldoc and did mess around with eldoc-box as well. Since I've been pleased with this package and planning to start contributing, this will be a good opportunity.

greghendershott commented 1 month ago

I spent more time using this for real, and concluded that showing the full documentation is not satisfactory. It can be too slow to parse and walk some of the HTML files. Much of the documentation is too large to fit even in an eldoc-box frame, and that frame doesn't support scrolling with e.g. the mousewheel.

What does work well is the preformatted blueboxes. Those are just function signatures. Maybe someday those could be enhanced to include a "doc string" style summary sentence or paragraph. But I think they need to be preformatted as part of the Racket doc build process that builds blueboxes.

On a more positive note, I've now got up to speed with the new eldoc API, using eldoc-documentation-functions (plural) and eldoc-documentation-strategy. I think I have things working well enough...

I pushed a commit, not merged to the main branch. It looks like there are build errors I need to fix for older Emacs where the new eldoc API isn't available...

divyaranjan1905 commented 1 month ago

Much of the documentation is too large to fit even in an eldoc-box frame, and that frame doesn't support scrolling with e.g. the mousewheel.

Actually @greghendershott , it does. I can scroll through the buffer using whatever keybindings I have (C-n, C-p) or us the mouse.

greghendershott commented 1 month ago

Hmm. For me with eldoc-box-hover-at-point-mode, the keybindings and mousewheel control the edit buffer, not the child frame.

greghendershott commented 1 month ago

In any case I think that commit 085736b on the issue-716 branch might be good enough to merge.

If you're willing/able to try that, and give me feedback, before I merge -- I'd be grateful.

However if it's not convenient for you, no worries, just let me know; I could go ahead and merge, and get your feedback, later.

divyaranjan1905 commented 1 month ago

Hmm. For me with eldoc-box-hover-at-point-mode, the keybindings and mousewheel control the edit buffer, not the child frame.

@greghendershott First click into the child frame while it's open, and then try the mousewheel and keybindings.

divyaranjan1905 commented 1 month ago

@greghendershott I did a checkout of branch issue-716 and I don't think what's implemented is exactly what I was meaning to add. Here's what I see when I hover with eldoc-box-hover-at-point-mode toggled on:

screenshot_2024-09-13_10 37 14

That doesn't really provide any documentation help, it only provides the syntax information regarding how the particular procedure or s-expression is syntactically structured. What I intended with this issue, is to channel the documentation generated by racket-xp-describe to show up, containing the relevant examples and description. To reiterate again, how this works with rust-analyzer in rust files:

screenshot_2024-09-13_10 40 58

I can click into this child frame, and if needed scroll easily and get the relevant information without having another window open up on the side. The documentation rust-analyzer gets is also using the CLI, similar to raco doc.

I understand there's issues of latency, I did notice that at times racket-xp-describe also gets hung up, but that could also be because of the HTML rendering. From what seems like it the eldoc buffer of rust files seems to be markdown with syntax highlighting.

greghendershott commented 1 month ago

I had a function to do this, but I deleted it before committing. I felt the performance was just too slow. Some doc files like "require.html" can take seconds. Although that's acceptable-ish when using racket-describe, it's pretty awful when just navigating around an edit buffer with eldoc. IMHO. But I can add it back in, just not enabled by default, for now. You can try, and maybe we'll have some ideas?

One second...

greghendershott commented 1 month ago

OK I pushed commit f6d68fb to the issue-716 branch. See the commit message for details how to enable. Please let me know what you think?

greghendershott commented 1 month ago

What it looks like on my system (not configured quite as nicely as yours):

image

greghendershott commented 1 month ago

I will also explore some optimizations that occur to me with a fresh brain fueled by coffee.

For example, the "adjusting" step is slowest (where we massage to render better in Emacs). But we need not adjust the entire DOM (as we do when rendering full pages in racket-describe) before extracting one section of interest. We can adjust only that (smaller) section. That should help significantly (?).

After that obvious big optimization, I can also look at micro-optimizing the "adjusting" itself...

greghendershott commented 1 month ago

For example, the "adjusting" step is slowest (where we massage to render better in Emacs). But we need not adjust the entire DOM (as we do when rendering full pages in racket-describe) before extracting one section of interest. We can adjust only that (smaller) section. That should help significantly (?).

Wow. That made a HUGE difference.

Maybe enough to have this enabled by default.

I'll push a new commit, I just want to take a quick break, and come back to verify a few things.

greghendershott commented 1 month ago

OK that's now pushed as commit 3cffba6 if you'd like to try.

greghendershott commented 1 month ago

Pushed commit 32f7305.

I think this is close to being ready to merge?

Would love your feedback, again, when you have a chance -- thanks!

greghendershott commented 1 month ago

Ready to merge.

Here are screenshots for different permutations of racket-xp-eldoc-level and eldoc-documentation-strategy (using eldoc-box-hover-at-point-mode).

racket-xp-eldoc-level: 'summary

Just the bluebox signature.

eldoc-documentation-strategy: #'eldoc-documentation-default

Info about point or sexp app.

image

eldoc-documentation-strategy: #'eldoc-documentation-compose

Info about point and sexp app.

image

racket-xp-eldoc-level: 'complete

Full documentation.

eldoc-documentation-strategy: #'eldoc-documentation-default

Info about point or sexp app.

image

eldoc-documentation-strategy: #'eldoc-documentation-compose

Info about point and sexp app.

image

greghendershott commented 1 month ago

I've continued to make some more commits, to improve this for full documentation and with eldoc-box.

If anyone tried this over the last week, before today, and found it too slow, or the display being not ideal (e.g. some doc lines looking "double spaced")? Then you may want to update both packages (racket-mode and eldoc-box), and try again.

I think you'll find it in good shape. But if you still have problems, feel free to comment here or (even better) open a new issue.