joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.27k stars 200 forks source link

more expansive help? #507

Closed mohkale closed 6 months ago

mohkale commented 4 years ago

Is there any way to get more help about an identifier or type from eglot. For example, say I've got the following rust code.

use std::fs::File;

fn main() {
    let f = File::open("hello.txt");
    println!("{:?}", f);
}

If I hover over the open method eglot shows some type assistance in the minibuffer.

20200624-49-33

If I run eglot-help-at-point eglot will pop open a buffer with some more documentation about the open method, but what if I wan't to get the docstring or information about the return type, or one of the argument types. What I've been doing so far is manually typing out the type of what I want to know more about just to then call eglot-help-at-point on it.

I'd prefer a function like eglot-query-identifier which displays all known types, values or anything for which we have documentation and lets me select one of them to view the doc of. Is this possible or is there another way to get at this information.

Also is it possible to associate eglot help buffers with the underlying lsp server. Then I can hover over types in the documentation and run eglot-help-at-point on them, saving me the need to type them out. Such as here I have to return to my file buffer just to get back to finding more documentation.

20200624-01-41

joaotavora commented 4 years ago

First of all, let me say what an exquisitely beautiful Emacs.

I am working on significant enhancements for the documentation capabilities of Emacs eldoc.el that Eldoc can take advantage of. They are near completion.

Unfortunately, there doesn't seem to be such a thing in the language server protocol (LSP) itself as "get me the documentation for this arbitrary identifier that I provide". It is very much the same with the "find definition" scenario, works very much like "find me that thing at point". There is no such thing at the present (unless I'm mistaken and they added it to the spec).

mohkale commented 4 years ago

Why thank you very much :grinning:.

Hmmm... that's a shame, well I don't really need a list of all symbols. Is there some way to use completion instead here with ivy? ivy has support for using a dynamic-collection where the user enters some text and the collection function returns a list of candidates. This is used with, for example, counsel-rg so that the ripgrep command is rerun every time the user enters something. So I was thinking I can use a collection function which just passes the input to the language-server, returns completion candidates. Whatever candidate the user chooses I then ask eglot to show me the help for.

For example, if I run ivy-eglot-query-identifier and enter std:: I can choose from:

    IoSliceMut
    Read
    Bytes
    _eprint(…)
    Error
    set_print(…)
    Repeat
    StdoutLock
-- TRIMMED --

I choose Error and then ask eglot to get me the help for it.

Does that seam more reasonable? I'm slightly concerned that the std::io:: prefix isn't in the completion candidates, but I presume lsp is context aware enough to know what Error type I mean if I exit with error here.

S.N. seriously... eldocs gonna get even better :astonished:. Looking forward to that :+1:.

joaotavora commented 4 years ago

ivy-eglot-query-identifier

can you point me to the definition of this function? I doubt it's using much more than a hack , though.

joaotavora commented 4 years ago

Also read #506 for a very similar discussion, but based on finding definitions.

mohkale commented 4 years ago

can you point me to the definition of this function? I doubt it's using much more than a hack , though.

Sorry that was all just hypothetical. I'll try implementing it to see if it's possible.

joaotavora commented 4 years ago

I think you'll bump into 2 distinct problems in the LSP protocol (this is all in a "as far as I remember" basis, I haven't looked over the spec in some time, unfortunately).

  1. There is no practical way to get all symbols in a project;

  2. There is no way to get the documentation for a specific symbol without having point be on that symbol;

mohkale commented 4 years ago

well that second point clinches it, that's a shame. I don't really see any workaround for that. :sob:.

joaotavora commented 4 years ago

well that second point clinches it, that's a shame. I don't really see any workaround for that. sob.

You should go into the LSP repo and complain or suggest alternatives. I was looking at https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol, but it doesn't really do waht you want. Eglot uses it to feed Imenu, which isn't bad.

Explore the repo it here, https://github.com/microsoft/language-server-protocol, particularly its issues. If there's no issue yet requesting this feature, open one yourself.

mohkale commented 4 years ago

Looks like another emacs user raised an issue about querying identifiers (like 5 hours ago, this is starting to get spooky :fearful:).

There doesn't appear to be an issue for just asking for the help of an identifier, 634 seems to be hinting at it, but no dice there. I'll make a new issue.

joaotavora commented 4 years ago

Looks like another emacs user raised an issue about querying identifiers (like 5 hours ago, this is starting to get spooky fearful).

Dang! spooky :ghost: , that makes it 3

I'll make a new issue.

Good idea. THough you could also add to that very issue, IMO

joaotavora commented 4 years ago

Make a new issue. I see they added something recently that could be seen as a decisive fix to the find definition problem. Maybe there's something for the doc too.

apiraino commented 2 years ago

I landed here while searching for a solution to this.

I think the current solution is to run M-x eldoc or M-x eldoc-doc-buffer(as explained in the README) to get that popup detailing the documentation. The old eglot-help-at-point command has long been deprecated. maybe close this issue?

mohkale commented 2 years ago

I think the current solution is to run M-x eldoc or M-x eldoc-doc-buffer(as explained in the README) to get that popup detailing the documentation. The old eglot-help-at-point command has long been deprecated. maybe close this issue?

@apiraino I think you might be misinterpreting what this issue was asking for. We already had a doc-buffer (before eglot specific, now through eldoc) when I raised this issue. The intention was to have a sort of search engine for lsp symbols that could bring up documentation on demand. Something like workspace/symbols but instead of jump to definition it gives you the documentation buffer for that symbol.

I also mention wanting to support eldoc in doc-buffers so you could do M-x eldoc-doc-buffer and then move point to part of the signature and eldoc would show documentation for it as well in the minibuffer. I've since concluded that isn't very practical, if for no other reason, then because there's not very much consistency in what an LSP server could give back for a documentation request. It's either markdown or plain-text (the latter which we render as the underlying buffers major-mode (including documentation, not just the signature)).

yveszoundi commented 2 years ago

I've also noticed recently the disappearance of eglot-help-at-point. It was rather convenient for me, as I always disable eldoc by default (too distracting). With rust, both eldoc and eldoc-doc-buffer are rather useless for my use-cases, often displaying either nothing or simply function information (rather than help for the symbol at the point).

I'm currently the function below, in case it could be useful to others (/cc @mohkale @apiraino ):

(defun ers/eglot-help-at-point ()
        (interactive)
        (let* ((response (jsonrpc-request
                          (eglot--current-server-or-lose)
                          :textDocument/hover (eglot--TextDocumentPositionParams)))
               (doc-details (eglot--format-markup (plist-get response :contents))))
          (set-buffer (get-buffer-create "*EGLOT_HELP*"))
          (let ((inhibit-read-only t))
            (erase-buffer)
            (insert doc-details)
            (goto-char (point-min)))
          (view-mode 1) ;; good enough for now...
          (display-buffer "*EGLOT_HELP*"
                          '(display-buffer-in-side-window . ((side . bottom) (window-height . 5))))))

(define-key eglot-mode-map (kbd "C-c l .") #'ers/eglot-help-at-point)

Often I'm just reading the signature, so I'm immediately invoking C-x 1, but I do have keybinds to move to the window below (windmove-down) or scroll down from the current buffer (scroll-other-window).

joaotavora commented 2 years ago

Write commands that rely on Eglot internals at your own risk. If I'm reading your judgement of eldoc correctly, I find it odd that this ers/eglot-help-at-point command presents information that M-x eldoc doesn't, as the latter should invoke textDocument/hover documentation (at least if eglot-hover-eldoc-function is still in your eldoc-documentation-functions, which it is by default).

Note that you can use M-x eldoc and M-x eldoc-doc-buffer and not have ElDoc constantly bothering you in the echo area. You do this by simply turning off eldoc-mode.

yveszoundi commented 2 years ago

I did read briefly those eldoc-documentation-functions settings, I'm using the defaults and my eglot customization is very limited overall. I'd rather not use internal eglot functions, but I literally have no options: per previous comment, eldoc and eldoc-doc-buffer are literally completely useless here (emacs 27.2 on Mac OS).

Screenshot of eldoc-doc-buffer

M-x eldoc and then M-x eldoc-doc-buffer

Screen Shot 2022-07-19 at 7 51 28 PM

Screenshot of custom function

M-x ers/eglot-help-at-point invoked at the cursor location

Screen Shot 2022-07-19 at 7 54 39 PM
joaotavora commented 2 years ago

Seems like your language server is returning a useless () very quickly. This prevents other more interesting sources from being tried. Try setting eldoc-documentation-strategy to eldoc-documentation-compose in eglot-connected-hook. Alternatively, add :signatureHelpProvider to eglot-ignored-server-capabilities.

yveszoundi commented 2 years ago

I did also previously tried eldoc-documentation-compose without success prior posting here.

Indeed, it could be an issue with the language server itself (rust-analyzer 17afa2e77 2022-01-24 stable). I'll see if there's an upgrade and retest with the latest version available.

joaotavora commented 2 years ago

I did also previously tried eldoc-documentation-compose without success prior posting here.

That doesn't make sense to me. Can you confirm that eglot-documentation-strategy is set to what you think it is by checking C-h v eglot-documentation-strategy RET in the buffer? Can you post the parts of the Eglot events buffer around the time of the M-x eldoc manual request?

yveszoundi commented 2 years ago

I did verify, I wasn't even aware about eglot-documentation-strategy -> I don't update that often.

On an other note (positive/constructive one), I'm glad to report that your assumptions about the LSP server were correct.

joaotavora commented 2 years ago

I'm still intrigued about the previous problem, but I guess it doesn't matter now that the problem is solved :+1: M-x eldoc should also work without eldoc-doc-buffer, but that's a bug in eldoc.el that I've just fixed and will only become available tomorrow or so in GNU ELPA.

DamienCassou commented 6 months ago

Should this issue be closed?

joaotavora commented 6 months ago

probably. Let's close it