unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
@ 2022-10-11  9:17 João Távora
  2022-10-11 15:38 ` Yuan Fu
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: João Távora @ 2022-10-11  9:17 UTC (permalink / raw)
  To: 58431; +Cc: eliz

Hello,

This request for a "breadcrumb" feature started in Eglot's bug tracker:
   
   https://github.com/joaotavora/eglot/discussions/988

Put it short, a breadcrumb is a summarized indication of the full path
to the current location of point within a source file.  So if I have a
file 'baz.cpp' inside a directory 'bars' of a project directory 'foo'
and that file contains:

    class Baz {
          int quux() {
              return 42; // point here
          }

          // or here
    };

Then the breadcrumb would read:

    foo > bars > baz.cpp > Baz > quux

If I move my point to outside quux(), the breadcrumb should now read:

    foo > bars > baz.cpp > Baz

The preferred location of this breadcrumb readout should be the
headerline.

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.

João

PS: Eli, I'm CCing you to underline this as just an example of a UI
feature that is requested for Eglot, but belongs somewhere else.  In
this case, I believe there is 0 additional integration needed in
eglot.el: it can be realized independently of the backend which feeds
into Imenu (perhaps tree-sitter?) and project.el.














^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-11  9:17 bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services João Távora
@ 2022-10-11 15:38 ` Yuan Fu
  2022-10-11 23:50   ` João Távora
  2023-04-08 19:47 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-04-18 18:10 ` bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, " Adam Porter
  2 siblings, 1 reply; 12+ messages in thread
From: Yuan Fu @ 2022-10-11 15:38 UTC (permalink / raw)
  To: João Távora; +Cc: eliz, 58431


> 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. We could just allow 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 “/“. 

> 
> João
> 
> PS: Eli, I'm CCing you to underline this as just an example of a UI
> feature that is requested for Eglot, but belongs somewhere else.  In
> this case, I believe there is 0 additional integration needed in
> eglot.el: it can be realized independently of the backend which feeds
> into Imenu (perhaps tree-sitter?) and project.el.

I agree, Emacs provides the framework/UI, and tree-sitter/eglot/future magic plug in.

Yuan




^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-11 15:38 ` Yuan Fu
@ 2022-10-11 23:50   ` João Távora
  2022-10-12  6:22     ` Yuan Fu
  2023-05-12 13:09     ` João Távora
  0 siblings, 2 replies; 12+ messages in thread
From: João Távora @ 2022-10-11 23:50 UTC (permalink / raw)
  To: Yuan Fu; +Cc: eliz, 58431

Yuan Fu <casouri@gmail.com> 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





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-11 23:50   ` João Távora
@ 2022-10-12  6:22     ` Yuan Fu
  2022-10-12  8:30       ` João Távora
  2023-05-12 13:09     ` João Távora
  1 sibling, 1 reply; 12+ messages in thread
From: Yuan Fu @ 2022-10-12  6:22 UTC (permalink / raw)
  To: João Távora; +Cc: eliz, 58431



> On Oct 11, 2022, at 4:50 PM, João Távora <joaotavora@gmail.com> wrote:
> 
> Yuan Fu <casouri@gmail.com> 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






^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-12  6:22     ` Yuan Fu
@ 2022-10-12  8:30       ` João Távora
  0 siblings, 0 replies; 12+ messages in thread
From: João Távora @ 2022-10-12  8:30 UTC (permalink / raw)
  To: Yuan Fu; +Cc: eliz, 58431

Yuan Fu <casouri@gmail.com> writes:

> 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.

Yup.

> 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.

Yes, that's exactly it.  It should be reasonably straightforward yes.

Maybe, to make a fancy breadcrumb, with icons like lsp-mode's we will
need some small augmentations to imenu--index-alist, but I don't see
that as a big difficulty.

> 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
> ;-)

Same here.  Drop a line a line if start working on this, so we don't
duplicate each other's work.

João





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-11  9:17 bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services João Távora
  2022-10-11 15:38 ` Yuan Fu
@ 2023-04-08 19:47 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-04-18 18:10 ` bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, " Adam Porter
  2 siblings, 0 replies; 12+ messages in thread
From: Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-04-08 19:47 UTC (permalink / raw)
  To: João Távora; +Cc: eliz, 58431

João Távora <joaotavora@gmail.com> writes:

>
> 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 see this feature as an augmentation of which-func.el.  The purpose is
to show what is the current defun, but the how and where (mode line or
header line) is a configuration option.

In recent versions of IDEs and text editors another header line UI to
show the current function is getting popular, something like our old
Sticky Function mode.  As with this breadcrumb UI, I think its logic
belongs more to which-func-mode.el and shouldn't be coupled to Semantic.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, on imenu.el/project.el services
  2022-10-11  9:17 bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services João Távora
  2022-10-11 15:38 ` Yuan Fu
  2023-04-08 19:47 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-04-18 18:10 ` Adam Porter
  2023-04-18 18:26   ` João Távora
  2 siblings, 1 reply; 12+ messages in thread
From: Adam Porter @ 2023-04-18 18:10 UTC (permalink / raw)
  To: 58431; +Cc: Eli Zaretskii, João Távora, Daniel Martín

Daniel Martín <mardani29 <at> yahoo.es> writes:

>> 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 see this feature as an augmentation of which-func.el.  The purpose is
> to show what is the current defun, but the how and where (mode line or
> header line) is a configuration option.
> 
> In recent versions of IDEs and text editors another header line UI to
> show the current function is getting popular, something like our old
> Sticky Function mode.  As with this breadcrumb UI, I think its logic
> belongs more to which-func-mode.el and shouldn't be coupled to Semantic.

FWIW, this sounds similar to the topsy.el library I published on MELPA a 
couple of years ago.  It aims to provide similar (or better) 
functionality than semantic-stickyfunc-mode without using Semantic.

https://github.com/alphapapa/topsy.el

If any of its code would be helpful, I'd be glad to "donate" it to 
ELPA/Emacs.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, on imenu.el/project.el services
  2023-04-18 18:10 ` bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, " Adam Porter
@ 2023-04-18 18:26   ` João Távora
  2023-04-20  4:27     ` Adam Porter
  0 siblings, 1 reply; 12+ messages in thread
From: João Távora @ 2023-04-18 18:26 UTC (permalink / raw)
  To: Adam Porter; +Cc: Eli Zaretskii, 58431, Daniel Martín

[-- Attachment #1: Type: text/plain, Size: 832 bytes --]

On Tue, Apr 18, 2023 at 7:10 PM Adam Porter <adam@alphapapa.net> wrote:

> FWIW, this sounds similar to the topsy.el library I published on MELPA a
> couple of years ago.  It aims to provide similar (or better)
> functionality than semantic-stickyfunc-mode without using Semantic.

Had a look, but doesn't seem to work with Imenu directly.  That's a goal
here, because it makes this work for Eglot and also any other non-Eglot
client that already defines an imenu.

Also seems to have a slightly different goal.  The goal here, is for
the headerline to show the current position in terms of the intervals
it intersects in the imenu tree, which may be a deep hierarchical
tree in some languages.

Here's what I've come up with: it's fresh out of the oven :-)

(meaning probably buggy, but hopefully hot)

João

[-- Attachment #2: breadcrumb.el --]
[-- Type: text/x-emacs-lisp, Size: 7109 bytes --]

;;; breadcrumb.el --- imenu-based breadcrumb paths   -*- lexical-binding: t; -*-

;; Copyright (C) 2023  João Távora

;; Author: João Távora <joaotavora@gmail.com>
;; Version: 0.0.1alpha
;; Keywords:

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:
;;;
;;; M-x breadcrumb-mode in any buffer where you have imenu capability
;;; (which are a lot of them, though said capability varies)
;;;
;;; Works even better for a recent Eglot (I think Eglot 1.14+),
;;; because it adds extra region info the the traditional imenu
;;; struct, `imenu--index-alist'.  But there should be interesting
;;; stuff in older Eglot too.
;;;
;;; This _should_ be faster than which-func.el due to good caching
;;; strategies.  But I haven't measured.
;;;
;;; This also takes care not to over-call `imenu-make-index-alist',
;;; which could be slow.  The variable `breadcrumb-idle-delay'
;;; controls that.
;;;
;;; Relies a lot on this double-dashed imenu function, but that is
;;; really not a double-dashed function.
;;;

;;; Code:
(require 'cl-lib)
(require 'imenu)

(cl-defun bc-bisect (a x &key (from 0) (to (length a)) key from-end)
  "Compute index to insert X in sequence A, keeping it sorted.
If X already in A, the resulting index is the leftmost such
index, unless FROM-END is t.  KEY is as usual in other CL land."
  (cl-macrolet ((search (from-end key)
                  `(cl-loop while (< from to)
                            for mid = (/ (+ from to) 2)
                            for p1 = (elt a mid)
                            for p2 = ,(if key `(funcall key p1) `p1)
                            if (,(if from-end '< '<=) x p2)
                            do (setq to mid) else do (setq from (1+ mid))
                            finally return from)))
    (if from-end (if key (search t key) (search t nil))
      (if key (search nil key) (search nil nil)))))

(defun bc--path-1 (index-alist pos)
  (cl-labels
      ((search (nodes &optional path)
         (cl-loop
          for n in nodes
          for reg = (get-text-property 0 'breadcrumb-region (car n))
          when (<= (car reg) pos (cdr reg))
          return (search (cdr n) (cons (car n) path))
          finally (cl-return path))))
    (nreverse (search index-alist))))

(defvar-local bc--path-2-cache nil)
(defun bc--path-2 (index-alist pos)
  (cl-labels ((dfs (n &optional path)
                (setq path (cons (car n) path))
                (if (consp (cdr n))
                    (mapc (lambda (n) (dfs n path)) (cdr n))
                  (setq bc--path-2-cache
                        (vconcat bc--path-2-cache
                                 `[,(cons (cdr n) path)])))))
    (unless bc--path-2-cache
      (mapc #'dfs index-alist)
      (setq bc--path-2-cache (cl-sort bc--path-2-cache #'< :key #'car)))
    (unless (< pos (car (aref bc--path-2-cache 0)))
      (let ((res (bc-bisect bc--path-2-cache pos :key #'car :from-end t)))
        (unless (zerop res) (reverse (cdr (elt bc--path-2-cache (1- res)))))))))

(defun bc-path (index-alist pos)
  "Get breadcrumb for position POS given INDEX-ALIST."
  (if (get-text-property 0 'breadcrumb-region (caar index-alist))
      (bc--path-1 index-alist pos)
    (bc--path-2 index-alist pos)))

(defvar-local bc--last-update-tick 0)

(defvar bc--header-line-key [header-line mouse-1])

(defun bc--format-node (p)
  (let ((reg (get-text-property 0 'breadcrumb-region p)))
    (if reg
        (propertize p
                    'mouse-face 'header-line-highlight
                    'help-echo "Go here"
                    'keymap (let ((m (make-sparse-keymap)))
                              (define-key m bc--header-line-key
                                          (lambda (&rest _e)
                                            (interactive)
                                            (push-mark)
                                            (goto-char (car reg))))
                              m))
      p)))

(defvar bc-idle-time 1
  "Control idle time before requesting new breadcrumbs.")

(defvar-local bc--idle-timer nil)

(defun bc--alist ()
  (let ((nochangep (= (buffer-chars-modified-tick) bc--last-update-tick))
        (buf (current-buffer)))
    (cond ((and nochangep imenu--index-alist) imenu--index-alist)
          (t
           (setq bc--last-update-tick (buffer-chars-modified-tick))
           (when bc--idle-timer (cancel-timer bc--idle-timer))
           (setq bc--idle-timer
                 (run-with-idle-timer
                  bc-idle-time nil
                  (lambda ()
                    (when (buffer-live-p buf)
                      (with-current-buffer buf
                        (setq bc--last-update-tick (buffer-chars-modified-tick))
                        (let ((non-essential t)
                              (imenu-auto-rescan t))
                          (imenu--make-index-alist t)
                          (setq bc--path-2-cache nil)
                          (force-mode-line-update t)))))))))))

(defun bc-path-for-header-line ()
  (cl-loop with alist = (bc--alist)
           for (p . more) on (bc-path alist (point))
           collect (bc--format-node p) when more collect " > "))

(defvar bc-header-line-format
  '(:eval (bc-path-for-header-line)))

(define-minor-mode bc-mode
  "Header lines with breadcrumbs."
  :init-value nil
  (if bc-mode (add-to-list 'header-line-format bc-header-line-format)
    (setq header-line-format (delq bc-header-line-format header-line-format))))

(defun bc-jump ()
  "Like M-x `imenu', but breadcrumb-powered."
  (interactive)
  (let (cands choice)
    (cl-labels
        ((fmt (strs)
           (mapconcat #'identity strs " > "))
         (dfs (nodes &optional path)
           (cl-loop
            for n in nodes
            for newpath = (cons (car n) path)
            for pos = (or (car (get-text-property 0 'breadcrumb-region (car n)))
                          (and (number-or-marker-p (cdr n)) (cdr n)))
            when pos do (push (cons (fmt (reverse newpath)) pos)
                              cands)
            do (dfs (cdr n) newpath))))
      (imenu--make-index-alist)
      (dfs imenu--index-alist)
      (unless cands (user-error "Sorry, no breadcrumb items to jump to."))
      (setq choice (cdr (assoc (completing-read "Index item? " cands nil t)
                               cands #'string=)))
      (push-mark)
      (goto-char choice))))

(provide 'breadcrumb)
;;; breadcrumb.el ends here

;; Local Variables:
;; read-symbol-shorthands: (("bc-" . "breadcrumb-"))
;; End:

^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, on imenu.el/project.el services
  2023-04-18 18:26   ` João Távora
@ 2023-04-20  4:27     ` Adam Porter
  2023-04-20  9:22       ` João Távora
  0 siblings, 1 reply; 12+ messages in thread
From: Adam Porter @ 2023-04-20  4:27 UTC (permalink / raw)
  To: João Távora; +Cc: Eli Zaretskii, 58431, Daniel Martín

Hi João,

On 4/18/23 13:26, João Távora wrote:
> On Tue, Apr 18, 2023 at 7:10 PM Adam Porter <adam@alphapapa.net> wrote:
> 
>> FWIW, this sounds similar to the topsy.el library I published on MELPA a
>> couple of years ago.  It aims to provide similar (or better)
>> functionality than semantic-stickyfunc-mode without using Semantic.
> 
> Had a look, but doesn't seem to work with Imenu directly.  That's a goal
> here, because it makes this work for Eglot and also any other non-Eglot
> client that already defines an imenu.

Yes, it doesn't use any Imenu functions currently.  It's an interesting 
idea, though.

> Also seems to have a slightly different goal.  The goal here, is for
> the headerline to show the current position in terms of the intervals
> it intersects in the imenu tree, which may be a deep hierarchical
> tree in some languages.

For most modes, that's true.  For buffers using `magit-section-mode', 
the `topsy--magit-section' function does return a breadcrumbs-style list 
that shows the hierarchy of sections.  Also, my other package that's 
just for Org, org-sticky-header, does show a breadcrumbs-style list of 
ancestor headings.

> Here's what I've come up with: it's fresh out of the oven :-)
> 
> (meaning probably buggy, but hopefully hot)

Thanks.  I tried it, and I'm not sure if it's doing what you intend, but 
it doesn't seem to do what I need; that is, it doesn't show the 
beginning of the top-level form that encloses the line at the top of the 
window.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, on imenu.el/project.el services
  2023-04-20  4:27     ` Adam Porter
@ 2023-04-20  9:22       ` João Távora
  0 siblings, 0 replies; 12+ messages in thread
From: João Távora @ 2023-04-20  9:22 UTC (permalink / raw)
  To: Adam Porter; +Cc: Eli Zaretskii, 58431, Daniel Martín

Adam Porter <adam@alphapapa.net> writes:

> For most modes, that's true.  For buffers using `magit-section-mode',
> the `topsy--magit-section' function does return a breadcrumbs-style
> list that shows the hierarchy of sections.  Also, my other package
> that's just for Org, org-sticky-header, does show a breadcrumbs-style
> list of ancestor headings.

I don't use Magit.  If its buffer support Imenu in any way, then
breadcrumb should do something.

>> Here's what I've come up with: it's fresh out of the oven :-)
>> (meaning probably buggy, but hopefully hot)
>
> Thanks.  I tried it, and I'm not sure if it's doing what you intend,
> but it doesn't seem to do what I need; that is, it doesn't show the
> beginning of the top-level form that encloses the line at the top of
> the window.

Its impossible for me to know what you are trying to do with it doing
with this description.  Is this in a file?  Can you show the file?  If
it's not a file, can you describe how I can test what you're testing?

João





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2022-10-11 23:50   ` João Távora
  2022-10-12  6:22     ` Yuan Fu
@ 2023-05-12 13:09     ` João Távora
  2023-05-17 21:31       ` Yuan Fu
  1 sibling, 1 reply; 12+ messages in thread
From: João Távora @ 2023-05-12 13:09 UTC (permalink / raw)
  To: Yuan Fu, Jeremy Bryant, Daniel Martín, Adam Porter; +Cc: eliz, 58431

On Wed, Oct 12, 2022 at 12:49 AM João Távora <joaotavora@gmail.com> wrote:

> 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)  |
> |  +-------------------+

> \->|...                |
> |  +-------------------+         +--------------+
> |                                |  project.el  |
> |  o-------------------o         +--------------+
> \->|breadcrumb.el      |             /
>    |(proposed addition)|<------------
>    o-------------------o
>

I've now created https://github.com/joaotavora/breadcrumb with
exactly this architecture.  Suggest everyone interested
check it out.  Propose we add it to ELPA.  It is not
Eglot-specific so it needn't depend on Eglot (but I've tested
it with Eglot and it works well).


João





^ permalink raw reply	[flat|nested] 12+ messages in thread

* bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services
  2023-05-12 13:09     ` João Távora
@ 2023-05-17 21:31       ` Yuan Fu
  0 siblings, 0 replies; 12+ messages in thread
From: Yuan Fu @ 2023-05-17 21:31 UTC (permalink / raw)
  To: João Távora
  Cc: Adam Porter, Jeremy Bryant, eliz, 58431, Daniel Martín



> On May 12, 2023, at 6:09 AM, João Távora <joaotavora@gmail.com> wrote:
> 
> On Wed, Oct 12, 2022 at 12:49 AM João Távora <joaotavora@gmail.com> wrote:
> 
>> 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)  |
>> |  +-------------------+
> 
>> \->|...                |
>> |  +-------------------+         +--------------+
>> |                                |  project.el  |
>> |  o-------------------o         +--------------+
>> \->|breadcrumb.el      |             /
>>   |(proposed addition)|<------------
>>   o-------------------o
>> 
> 
> I've now created https://github.com/joaotavora/breadcrumb with
> exactly this architecture.  Suggest everyone interested
> check it out.  Propose we add it to ELPA.  It is not
> Eglot-specific so it needn't depend on Eglot (but I've tested
> it with Eglot and it works well).

Looks good! It doesn’t seem possible for a major mode to give breadcrumb a custom “imenu-alist” that’s different from what it gives to Imenu? It might be useful because it’s common for major modes to add a category layer in the imenu alist, like Function > xxx and Class > xxx instead of xxx along; and there might be other reasons the major mode want the breadcrumb to be different from Imenu.

In general it might be useful for breadcrumb to have it’s own interface, with project and Imenu adapters come with it out-of-the-box.

Yuan




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-05-17 21:31 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-11  9:17 bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based on imenu.el/project.el services João Távora
2022-10-11 15:38 ` Yuan Fu
2022-10-11 23:50   ` João Távora
2022-10-12  6:22     ` Yuan Fu
2022-10-12  8:30       ` João Távora
2023-05-12 13:09     ` João Távora
2023-05-17 21:31       ` Yuan Fu
2023-04-08 19:47 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-04-18 18:10 ` bug#58431: 29.0.50; [Eglot] Add "breadcrumb.el" feature based, " Adam Porter
2023-04-18 18:26   ` João Távora
2023-04-20  4:27     ` Adam Porter
2023-04-20  9:22       ` João Távora

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).