* Need help with eldoc:
@ 2022-03-24 14:21 T.V Raman
2022-03-24 23:28 ` João Távora
0 siblings, 1 reply; 9+ messages in thread
From: T.V Raman @ 2022-03-24 14:21 UTC (permalink / raw)
To: emacs-devel
Hi,
this is with Emacs compiled from the Git repo @HEAD.
Eldoc stopped working for me a few months (perhaps over a year)ago,
and I finally got some time to investigate.
Running with emacs -q and just emacspeak loaded, I did the following:
1. Open an elisp file, in my case I opened the source to Emacs
built-in function next-line
2. Evaluate (eldoc-documentation-default) which is the value in
eldoc-documentation-function
Could the current maintainer of eldoc give some pointers on what might
be breaking?
Here is the backtrace:
Debugger entered--Lisp error: (void-function nil)
nil(:patient)
eldoc--make-callback(:patient)
eldoc-documentation-default()
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-24 14:21 Need help with eldoc: T.V Raman
@ 2022-03-24 23:28 ` João Távora
2022-03-24 23:39 ` T.V Raman
0 siblings, 1 reply; 9+ messages in thread
From: João Távora @ 2022-03-24 23:28 UTC (permalink / raw)
To: T.V Raman; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 831 bytes --]
>
> Could the current maintainer of eldoc give some pointers on what might
> be breaking?
>
Hello Raman,
I'm not formally the maintainer of Eldoc (I think) but I have worked on it
recently (read more than one year ago). The changes I introduced make it
so that the documentation-generating functions in
eldoc-documentation-functions
(plural!) can now be asynchronous (i.e. not return doc results immediately).
eldoc-documentation-default should not be called directly from elisp
libraries other
than eldoc.el itself, which handles this possible asynchronicity. It is a
function value to
be put into eldoc-documentation-function which is then called by the
eldoc.el machinery
(such as M-x eldoc) that gives it context.
So can you tell me what are you trying to accomplish? Maybe I can help.
João
[-- Attachment #2: Type: text/html, Size: 1256 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-24 23:28 ` João Távora
@ 2022-03-24 23:39 ` T.V Raman
2022-03-25 0:16 ` João Távora
0 siblings, 1 reply; 9+ messages in thread
From: T.V Raman @ 2022-03-24 23:39 UTC (permalink / raw)
To: joaotavora; +Cc: raman, emacs-devel
thanks for reaching out and replying!
So let me step back and explain what I want and I'm sure you'll know
the answer.
I use and maintain emacspeak (https://emacspeak.sf.net --- code is on
github under https://github.com/tvraman/emacspeak
Eldoc is extremely useful to the blind software engineer, perhaps even
more so than to someone who can glance at the docs in another
window. But eldoc spopping up and speaking based on an idel timer is
suboptimal.
So what I had implemented a few years ago was:
1. Turn off global eldoc mode.
2. Advice the eldoc-message machinery to cache the displayed
message somewhre
3. Added an interactive command that spoke that cached value
Result: a blind user could avoid the constant interruption
from eldoc but ask for the documentation when needed with a
single keystroke.
Your explanation around how async updates works now explains
my older solution broke, and I was naively trying to call
what seemed to the closest equivalent which was clearly
wrong.
So to cut to the chase; could you provide me a simple
mechanism that I could call from emacspeak (via a keybinding
bound to an interactive command I write) where that command
calls into the eldoc machinery and gets back the help that
eldoc displays?
João Távora writes:
> >
> > Could the current maintainer of eldoc give some pointers on what might
> > be breaking?
> >
>
> Hello Raman,
>
> I'm not formally the maintainer of Eldoc (I think) but I have worked on it
> recently (read more than one year ago). The changes I introduced make it
> so that the documentation-generating functions in
> eldoc-documentation-functions
> (plural!) can now be asynchronous (i.e. not return doc results immediately).
>
> eldoc-documentation-default should not be called directly from elisp
> libraries other
> than eldoc.el itself, which handles this possible asynchronicity. It is a
> function value to
> be put into eldoc-documentation-function which is then called by the
> eldoc.el machinery
> (such as M-x eldoc) that gives it context.
>
> So can you tell me what are you trying to accomplish? Maybe I can help.
>
> João
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-24 23:39 ` T.V Raman
@ 2022-03-25 0:16 ` João Távora
2022-03-25 2:21 ` T.V Raman
2022-03-25 14:27 ` T.V Raman
0 siblings, 2 replies; 9+ messages in thread
From: João Távora @ 2022-03-25 0:16 UTC (permalink / raw)
To: T.V Raman; +Cc: emacs-devel
"T.V Raman" <raman@google.com> writes:
> So to cut to the chase; could you provide me a simple
> mechanism that I could call from emacspeak (via a keybinding
> bound to an interactive command I write) where that command
> calls into the eldoc machinery and gets back the help that
> eldoc displays?
Hello Raman,
Yes, I think I have the solution for you. There is a new variable
called eldoc-display-functions as well. My advice is that you attempt
to write a member function for it. Call it, say
emacsspeak-speak-out-docs and then add it to eldoc-display-functions via
add-hook.
Your new function emacsspeak-speak-out-docs will then receive two
arguments: DOCS and INTERACTIVE. The first contains the pieces of
documentation that have been gathered by the
eldoc-documentation-functions (plural) and the second INTERACTIVE
argument says if the request to "display" documentation came directly
from the user or from ElDoc's automatic mechanisms (the timer that you
are keen on turning off).
The docstring has more details.
Once that is done you need only call M-x eldoc and your problem, as you
presented it, should be solved. And yes, it's fine to turn off
global-eldoc-mode.
Let me know if you need more help.
João
PS: I guess it should be called eldoc-presentation-functions instead of
eldoc-display-functions since in this case it's not really "displaying"
anything, but presenting it with sound. Also congratulations for
Emacsspeak! I realize it's a very important project, and it's amazing
that someone like you is making Emacs work for the visually impaired.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-25 0:16 ` João Távora
@ 2022-03-25 2:21 ` T.V Raman
2022-03-25 10:03 ` João Távora
2022-03-25 14:27 ` T.V Raman
1 sibling, 1 reply; 9+ messages in thread
From: T.V Raman @ 2022-03-25 2:21 UTC (permalink / raw)
To: joaotavora; +Cc: raman, emacs-devel
So this was very easy to get working, I'd like you to take a look.
I discovered custom option
'(eldoc-echo-area-prefer-doc-buffer t)
--- this i good for the emacspeak user who can see a little since
they can look at the buffer -- and it doesn't disturb or distract the
totally blind user.
I then went ahead and implemented the function as you suggested -- see
https://github.com/tvraman/emacspeak/blob/master/lisp/emacspeak-advice.el
-- search for "eldoc" to jump to the relevant portion.
I'd like some feedback for the following:
0. I cloned your display in a buffer function
1. changed it to use with-temp-buffer
3. rendered the doc there and asked it to speak it.
4. if called non-interactively I just play a short sound to say
something is available
5. And then bound eldoc to a key
This all works, but it could well be simpler now that the above
works.
If I could be ensured of the eldoc always being in a buffer I could
eliminate most of the above, but I am also afraid that that will
recreate the earlier async problem which is why I didn't go there.
So modulo not yet having figured out the empty doc-string case, this
works well for me for now.
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-25 2:21 ` T.V Raman
@ 2022-03-25 10:03 ` João Távora
2022-03-25 14:03 ` T.V Raman
0 siblings, 1 reply; 9+ messages in thread
From: João Távora @ 2022-03-25 10:03 UTC (permalink / raw)
To: T.V Raman; +Cc: emacs-devel
"T.V Raman" <raman@google.com> writes:
> If I could be ensured of the eldoc always being in a buffer I could
> eliminate most of the above, but I am also afraid that that will
> recreate the earlier async problem which is why I didn't go there.
Raman,
You are completely on the right track, and I'm very glad it was
reasonably straightforward. And yes, "ensuring eldoc always being in a
buffer" is useful and possible -- if very slightly hacky, but read on.
Anyway, if you read the eldoc code and search for
eldoc--format-doc-buffer, you'll notice that the two members of
eldoc-display-functions by default already share "the eldoc doc buffer".
This avoids them repeating common needed work between themselves. In
Emacsspeak, you have the same problem.
So you have two options:
1. Make use of the internal function eldoc--format-doc-buffer. This has
"ensure" semantics and returns the desired buffer. Then your
function will become:
(defun emacspeak-speak-eldoc (docs interactive)
"Speak eldoc."
(emacspeak-auditory-icon 'help)
(when interactive
(with-current-buffer (eldoc--format-doc-buffer docs)
(dtk-speak (buffer-string)))))
2. Make sure that the function eldoc-display-in-buffer is always present
in eldoc-display-functions. It will undertake to call
eldoc--format-doc-buffer and place that work in the buffer that you
can access with eldoc--doc-buffer. Your function becomes:
(defun emacspeak-speak-eldoc (docs interactive)
"Speak eldoc."
(emacspeak-auditory-icon 'help)
(when interactive
(with-current-buffer eldoc--doc-buffer
(dtk-speak (buffer-string)))))
The reason I said before these solutions are slightly hacky is because
of the usage of "internal --" symbols. But I guess it's reasonable to
make one of these symbols "external". Or better yet, reuse the existing
external function eldoc-doc-buffer and re-purpose it for non-interactive
use. This is done in a patch to eldoc.el added in PS, which I think is
reasonable.
Then your function would become more idiomatic:
(defun emacspeak-speak-eldoc (docs interactive)
"Speak eldoc."
(emacspeak-auditory-icon 'help)
(when interactive
(with-current-buffer (eldoc-doc-buffer)
(dtk-speak (buffer-string)))))
Let me know what you think,
João
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 74ffeb166d..2d0656fb41 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -464,19 +464,21 @@ eldoc--doc-buffer
(defvar eldoc--doc-buffer-docs nil "Documentation items in `eldoc--doc-buffer'.")
-(defun eldoc-doc-buffer ()
+(defun eldoc-doc-buffer (&optional interactive)
"Display ElDoc documentation buffer.
This holds the results of the last documentation request."
- (interactive)
+ (interactive (list t))
(unless (buffer-live-p eldoc--doc-buffer)
(user-error (format
"ElDoc buffer doesn't exist, maybe `%s' to produce one."
(substitute-command-keys "\\[eldoc]"))))
(with-current-buffer eldoc--doc-buffer
- (rename-buffer (replace-regexp-in-string "^ *" ""
- (buffer-name)))
- (display-buffer (current-buffer))))
+ (cond (interactive
+ (rename-buffer (replace-regexp-in-string "^ *" ""
+ (buffer-name)))
+ (display-buffer (current-buffer)))
+ (t (current-buffer)))))
(defun eldoc--format-doc-buffer (docs)
"Ensure DOCS are displayed in an *eldoc* buffer."
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-25 10:03 ` João Távora
@ 2022-03-25 14:03 ` T.V Raman
2022-03-25 22:52 ` João Távora
0 siblings, 1 reply; 9+ messages in thread
From: T.V Raman @ 2022-03-25 14:03 UTC (permalink / raw)
To: joaotavora; +Cc: raman, emacs-devel
This is awesome!
Q: what is "patch in PS"?
Once you push the patch to emacs git I'll implement what you suggest
as the final solution.
One more question -- Once I have this working well for myself, I then
need to build a solution that works when Emacs 28 releases --- since I
cant depend on all emacspeak users running emacs from @HEAD, but I'd
like to first get the *final* solution right, then worry about
backwards compat.
João Távora writes:
> "T.V Raman" <raman@google.com> writes:
>
> > If I could be ensured of the eldoc always being in a buffer I could
> > eliminate most of the above, but I am also afraid that that will
> > recreate the earlier async problem which is why I didn't go there.
>
> Raman,
>
> You are completely on the right track, and I'm very glad it was
> reasonably straightforward. And yes, "ensuring eldoc always being in a
> buffer" is useful and possible -- if very slightly hacky, but read on.
>
> Anyway, if you read the eldoc code and search for
> eldoc--format-doc-buffer, you'll notice that the two members of
> eldoc-display-functions by default already share "the eldoc doc buffer".
> This avoids them repeating common needed work between themselves. In
> Emacsspeak, you have the same problem.
>
> So you have two options:
>
> 1. Make use of the internal function eldoc--format-doc-buffer. This has
> "ensure" semantics and returns the desired buffer. Then your
> function will become:
>
> (defun emacspeak-speak-eldoc (docs interactive)
> "Speak eldoc."
> (emacspeak-auditory-icon 'help)
> (when interactive
> (with-current-buffer (eldoc--format-doc-buffer docs)
> (dtk-speak (buffer-string)))))
>
> 2. Make sure that the function eldoc-display-in-buffer is always present
> in eldoc-display-functions. It will undertake to call
> eldoc--format-doc-buffer and place that work in the buffer that you
> can access with eldoc--doc-buffer. Your function becomes:
>
> (defun emacspeak-speak-eldoc (docs interactive)
> "Speak eldoc."
> (emacspeak-auditory-icon 'help)
> (when interactive
> (with-current-buffer eldoc--doc-buffer
> (dtk-speak (buffer-string)))))
>
> The reason I said before these solutions are slightly hacky is because
> of the usage of "internal --" symbols. But I guess it's reasonable to
> make one of these symbols "external". Or better yet, reuse the existing
> external function eldoc-doc-buffer and re-purpose it for non-interactive
> use. This is done in a patch to eldoc.el added in PS, which I think is
> reasonable.
>
> Then your function would become more idiomatic:
>
> (defun emacspeak-speak-eldoc (docs interactive)
> "Speak eldoc."
> (emacspeak-auditory-icon 'help)
> (when interactive
> (with-current-buffer (eldoc-doc-buffer)
> (dtk-speak (buffer-string)))))
>
> Let me know what you think,
> João
>
>
> diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
> index 74ffeb166d..2d0656fb41 100644
> --- a/lisp/emacs-lisp/eldoc.el
> +++ b/lisp/emacs-lisp/eldoc.el
> @@ -464,19 +464,21 @@ eldoc--doc-buffer
>
> (defvar eldoc--doc-buffer-docs nil "Documentation items in `eldoc--doc-buffer'.")
>
> -(defun eldoc-doc-buffer ()
> +(defun eldoc-doc-buffer (&optional interactive)
> "Display ElDoc documentation buffer.
>
> This holds the results of the last documentation request."
> - (interactive)
> + (interactive (list t))
> (unless (buffer-live-p eldoc--doc-buffer)
> (user-error (format
> "ElDoc buffer doesn't exist, maybe `%s' to produce one."
> (substitute-command-keys "\\[eldoc]"))))
> (with-current-buffer eldoc--doc-buffer
> - (rename-buffer (replace-regexp-in-string "^ *" ""
> - (buffer-name)))
> - (display-buffer (current-buffer))))
> + (cond (interactive
> + (rename-buffer (replace-regexp-in-string "^ *" ""
> + (buffer-name)))
> + (display-buffer (current-buffer)))
> + (t (current-buffer)))))
>
> (defun eldoc--format-doc-buffer (docs)
> "Ensure DOCS are displayed in an *eldoc* buffer."
>
>
>
>
>
>
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-25 14:03 ` T.V Raman
@ 2022-03-25 22:52 ` João Távora
0 siblings, 0 replies; 9+ messages in thread
From: João Távora @ 2022-03-25 22:52 UTC (permalink / raw)
To: T.V Raman; +Cc: emacs-devel
"T.V Raman" <raman@google.com> writes:
> This is awesome!
>
> Q: what is "patch in PS"?
"patch in Post Scriptum" means I attached a small diff at the end of the
email, after my signature. This will repurpose the eldoc-doc-buffer
function for non-interactive use, as we discussed.
> Once you push the patch to emacs git I'll implement what you suggest
> as the final solution.
OK. Perfect. For now you can use one of the solutions using internal
symbols. I believe they are unlikely to change in the near future.
> One more question -- Once I have this working well for myself, I then
> need to build a solution that works when Emacs 28 releases --- since I
> cant depend on all emacspeak users running emacs from @HEAD, but I'd
> like to first get the *final* solution right, then worry about
> backwards compat.
Actually, this _might_ be a non-problem. You see, eldoc.el is a GNU
ELPA "core package" that works in older versions of Emacs as long as
they're >= 26.3. You can see this in the header of the eldoc.el file:
;; Package-Requires: ((emacs "26.3"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
;; compatible with the version of Emacs recorded above.
So if you can arrange for emacsspeak to either use package.el ELPA
packages or simply for emacsspeak to load the Emacs's
lisp/emacs-lisp/eldoc.el file, then "you're golden", as they say.
João
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Need help with eldoc:
2022-03-25 0:16 ` João Távora
2022-03-25 2:21 ` T.V Raman
@ 2022-03-25 14:27 ` T.V Raman
1 sibling, 0 replies; 9+ messages in thread
From: T.V Raman @ 2022-03-25 14:27 UTC (permalink / raw)
To: joaotavora; +Cc: raman, emacs-devel
Works like a charm!
https://github.com/tvraman/emacspeak/blob/master/lisp/emacspeak-advice.el#L794
This is still using the internal eldoc variable for the buffer; will
update to using your public function once that is pushed.
We can next worry about Emacs 28 vs Emacs@HEAD:-)
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
--
Thanks,
--Raman(I Search, I Find, I Misplace, I Research)
♉ Id: kg:/m/0285kf1 🦮
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-03-25 22:52 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-24 14:21 Need help with eldoc: T.V Raman
2022-03-24 23:28 ` João Távora
2022-03-24 23:39 ` T.V Raman
2022-03-25 0:16 ` João Távora
2022-03-25 2:21 ` T.V Raman
2022-03-25 10:03 ` João Távora
2022-03-25 14:03 ` T.V Raman
2022-03-25 22:52 ` João Távora
2022-03-25 14:27 ` T.V Raman
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).