Subject: bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services

From: Yuan Fu <[email-masked]>
Date: Tue, 11 Oct 2022 23:22:48 -0700

> On Oct 11, 2022, at 4:50 PM, João Távora <[email-masked]> wrote:
> 
> Yuan Fu <[email-masked]> writes:
> 
>>> In the original Eglot request, users are requesting this UI feature for
>>> the Eglot LSP client.  But this doesn't have any LSP-specific
>>> interactions.  It can and should be done entirely by using the services
>>> provided by imenu.el and project.el.
>>> 
>>> Eglot already integrates with Imenu, so as soon as this hypothetical
>>> breadcrumb.el is in place, then Eglot users can take advantage of it.
>>> 
>>> This is similar to which-func.el, which displays the trailing element of
>>> the breadcrumb in the headerline.  Perhaps the breadcrumb feature can be
>>> thought of as an augmentation of which-func.el's functionality.  I don't
>>> have a strong opinion there.
>> 
>> I think which-func is closer to breadcrumb conceptually and api-wise:
>> Both which-func and breadcrumb are about the current function, while
>> imenu is about a list of _all_ functions/sections.
> 
> I think there is a slight misunderstanding here.
> 
> The information stored in imenu is what which-func.el uses by default.
> See this comment in which-func.el
> 
>   ;; This package prints name of function where your current point is
>   ;; located in mode line.  It assumes that you work with the imenu
>   ;; package and `imenu--index-alist' is up to date.
> 
> Moreover, imenu--index-alist is not a list, but a tree (of which a flat
> list is a particular case).
> 
> M-x which-function-mode works for any Eglot-managed buffer, but Eglot
> doesn't have any code specific to which-func.el.  How can this be?
> Well, Eglot stores the tree information is gets from LSP in Imenu's
> imenu--index-alist and that information serves many Imenu frontends --
> which-func.el being just one of them.
> 
> Moreover, the breadcrumb that the Eglot user is requesting -- and which
> I am describing in detail -- also needs information that is owned by
> project.el, namely the project root.
> 
> Let's use some M-x artist-mode magic to explain what is in place
> and what I am proposing.
> 
> +---+----+   +---------+     +----------+
> |eglot.el|   |python.el|     | ruby.el  |
> +---+----+   +---+-----+     +----+-----+
>    |            |                |
>    |            |                |
>    |            v                |
>    |        +----------+         |
>    +------->| imenu.el |<--------+
>             +-+--------+
>               |
> +--------------+
> |
> |  +-------------------+
> \->|which-func.el      |
> |  |(already working)  |
> |  +-------------------+
> |
> |  +-------------------+
> \->|speedbar.el        |
> |  |(also working)     |
> |  +-------------------+
> |
> |  +-------------------+
> \->|...                |
> |  +-------------------+         +--------------+
> |                                |  project.el  |
> |  o-------------------o         +--------------+
> \->|breadcrumb.el      |             /
>   |(proposed addition)|<------------ 
>   o-------------------o
> 
> So, Eglot already stores its LSP-gathered information "inside" imenu's
> data structures using imenu-create-index-function.  As does the current
> python.el, ruby.el, antlr-mode.el, cc-mode and many others when they are
> used without Eglot.
> 
> which-func.el get this information from imenu and uses it for the limited
> purpose of showing only the leaf of the tree where the point is at.
> 
> breadcrumb.el would function similarly, but instead use it to show the
> _full path_ of that tree up until the leaf of the tree where the point
> is at.  It would then prepend the path to the file by getting it from
> project.el.
> 
>> which-func-function to accept a list of function names. In fact, the
>> which-func function of tree-sitter powered python.el already generates
>> a breadcrumb, I just joined all the function names along the path with
>> “/“.
> 
> You can use that strategy in your new Python mode, but it seems
> misguided to me.  You'll be supporting which-func.el directly instead of
> indirectly, thus missing out on other imenu-using client frontends like
> speedbar, "treemacs", M-x imenu or others.  They will not work
> out-of-the-box with your new mode.
> 
> Therefore, my advice is that you keep the tree structure you get from
> tree-sitter intact and stored in imenu--index-alist via
> imenu-create-index-function -- see the docstring imenu--index-alist --
> then let the imenu clients compose a breadcrumb iff they so desire.
> 
> breadcrumb.el would be such a client, that would work in your
> tree-sitter powered python mode and in many other contexts.
> 
> João

Thanks for your explanation! I didn’t know which-func can just use imenu--index-alist. I already have support for imenu, just need to let which-func do its thing. 

What you said for breakcumb.el makes total sense. It sounds pretty straightforward, just get file path from project.el and function path from imenu and put them together. I can work on it later if no one come around and adopt it, I’ve got a lot of stuff on my plate already ;-)

Yuan