bug#43609: 28.0.50; eldoc-documentation-function

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
When with emacs -Q I put the following snippet into *scratch*

(defun foo ()
   (ignore))

move point to somewhere on "foo" and do

M-: (funcall eldoc-documentation-function)

I get the following backtrace:

Debugger entered--Lisp error: (void-function nil)
   nil(:patient)
   eldoc--make-callback(:patient)
   eldoc-documentation-default()
   funcall(eldoc-documentation-default)
   eval((funcall eldoc-documentation-function) t)
   eval-expression((funcall eldoc-documentation-function) nil nil 127)
   funcall-interactively(eval-expression (funcall eldoc-documentation-function) nil nil 127)
   call-interactively(eval-expression nil nil)
   command-execute(eval-expression)

If I do the same thing with Emacs 27 I get

#("defun: (NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" 0 5 (face font-lock-keyword-face) 8 12 (face eldoc-highlight-function-argument))

The doc-string of 'eldoc-documentation-function' with Emacs 27 was:

   Function to call to return doc string.
   The function of no args should return a one-line string for displaying
   doc about a function etc. appropriate to the context around point.
   It should return nil if there’s no doc appropriate for the context.
   Typically doc is returned if point is on a function-like name or in its
   arg list.

The doc-string with Emacs 28 says

   For backward compatibility to the "old" protocol, this variable
   can also be set to a function that returns nil or a doc string,
   depending whether or not there is documentation to display at
   all.

But it does not tell _how_ to do that in order to get the string
returned by Emacs 27 and I already spent a couple of hours trying.

I am using a package that displays the string produced by that
function in a tooltip near point.  This package now ceased to work
with the backtrace shown above.  Please help me to make that
package work again, either by optionally restoring the old
functionality of (funcall eldoc-documentation-function) or by
providing another function I could call instead.  The present
situation makes it currently impossible for me to use master.

Thank you, martin


In GNU Emacs 28.0.50 (build 1, i686-pc-mingw32)
  of 2020-09-16 built on NOREST
Repository revision: f028a893a552b0c38c35f949addb6a891e8586cc
Repository branch: master
Windowing system distributor 'Microsoft Corp.', version 5.1.2600
System Description: Microsoft Windows XP Service Pack 3 (v5.1.0.2600)

Configured using:
  'configure --prefix=/c/emacs-git/trunk/dbg --with-gnutls=no
  --without-pop --enable-checking=yes --enable-gcc-warnings=warn-only
  --enable-check-lisp-object-type=warn-only 'CFLAGS=-O0 -g3
  -Wno-logical-op -Wno-missing-braces''

Configured features:
XPM JPEG TIFF GIF PNG RSVG SOUND NOTIFY W32NOTIFY ACL LIBXML2 ZLIB
TOOLKIT_SCROLL_BARS MODULES THREADS PDUMPER

Important settings:
   value of $LANG: DEA
   locale-coding-system: cp1252

Major mode: Lisp Interaction

Minor modes in effect:
   tooltip-mode: t
   global-eldoc-mode: t
   eldoc-mode: t
   electric-indent-mode: t
   mouse-wheel-mode: t
   tool-bar-mode: t
   menu-bar-mode: t
   file-name-shadow-mode: t
   global-font-lock-mode: t
   font-lock-mode: t
   blink-cursor-mode: t
   auto-composition-mode: t
   auto-encryption-mode: t
   auto-compression-mode: t
   line-number-mode: t
   transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message rmc puny dired dired-loaddefs
rfc822 mml mml-sec epa derived epg epg-config gnus-util rmail
rmail-loaddefs auth-source cl-seq eieio eieio-core cl-macs
eieio-loaddefs password-cache json map text-property-search time-date
subr-x seq byte-opt gv bytecomp byte-compile cconv mm-decode mm-bodies
mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail
rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils help-fns
radix-tree cl-print debug backtrace help-mode easymenu find-func
cl-loaddefs cl-lib tooltip eldoc electric uniquify ediff-hook vc-hooks
lisp-float-type mwheel dos-w32 ls-lisp disp-table term/w32-win w32-win
w32-vars term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite charscript charprop case-table epa-hook
jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button
loaddefs faces cus-face macroexp files window text-properties overlay
sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads w32notify w32 multi-tty
make-network-process emacs)

Memory information:
((conses 8 57053 5749)
  (symbols 24 7161 1)
  (strings 16 20666 1951)
  (string-bytes 1 643171)
  (vectors 8 12211)
  (vector-slots 4 173280 17378)
  (floats 8 36 47)
  (intervals 28 304 1)
  (buffers 568 13))




Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
 > You might want to read the docstring for
 > eldoc-documentation-functions, in particular the part where "Each hook
 > function is called with at least one argument CALLBACK".

That was the first thing I tried to do.  For beginners, I don't know
what a "Hook of functions" is.  And I completely fail to understand what
a "hook function" in this context is and when and why it gets called.
In short, I completely fail to understand the logic behind this
variable.  All I know is that I do not want to write a hook function and
I do not want to get called by any agent here.

 > I agree that the latest changes make Eldoc gratuitously more complex,
 > though. You can read bug#41531, where they started.

I never read that thread (it started around a time when my mailboxes
were thrashed due to almost simultaneous crashes of two of my mail
receiving machines) and I subsequently had to drop a few thousands of
mails I received earlier.  I've still not recuperated from that state.

I now spent more than an hour reading that thread and am as clever as
before.  The first post in that thread seems to say everything already:

   This enables eldoc.el to exert control over how (and crucially also
   when) to display the docstrings to the user.

In a nutshell: With eldoc-tooltip it's me and only me who decides when
and how to display a doc string.  I do not want to leave this decision
to a package that tries to judge whether and when that Procrustean bed
called echo area is ready to display that doc string, whether and how to
truncate it and when to make it disappear.  Sadly, this doesn't work any
more in Emacs 28.  Maybe there's a simple solution to my problem but
nobody pointed me to it so far ...

Thanks for the response, martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

Dmitry Gutov
On 27.09.2020 11:30, martin rudalics wrote:
>  > You might want to read the docstring for
>  > eldoc-documentation-functions, in particular the part where "Each hook
>  > function is called with at least one argument CALLBACK".
>
> That was the first thing I tried to do.  For beginners, I don't know
> what a "Hook of functions" is.  And I completely fail to understand what
> a "hook function" in this context is and when and why it gets called.

Hooks is a list of functions. They get called to fetch the doc
information. And now there is some logic called "strategies" that
combines the results.

> In short, I completely fail to understand the logic behind this
> variable.  All I know is that I do not want to write a hook function and
> I do not want to get called by any agent here.

No, the hook functions are written already. They are basically a list of
functions that were previously the values of
eldoc-documentation-function. Except it's now a list. *And* they use an
asynchronous convention where the first argument they receive is a callback.

>  > I agree that the latest changes make Eldoc gratuitously more complex,
>  > though. You can read bug#41531, where they started.
>
> I never read that thread (it started around a time when my mailboxes
> were thrashed due to almost simultaneous crashes of two of my mail
> receiving machines) and I subsequently had to drop a few thousands of
> mails I received earlier.  I've still not recuperated from that state.

I see. There is another email I sent to you a few months ago (about
pop-up-mini-mode) that was also without response. I'll resend.

> I now spent more than an hour reading that thread and am as clever as
> before.  The first post in that thread seems to say everything already:
>
>    This enables eldoc.el to exert control over how (and crucially also
>    when) to display the docstrings to the user.
>
> In a nutshell: With eldoc-tooltip it's me and only me who decides when
> and how to display a doc string.  I do not want to leave this decision
> to a package that tries to judge whether and when that Procrustean bed
> called echo area is ready to display that doc string, whether and how to
> truncate it and when to make it disappear.  Sadly, this doesn't work any
> more in Emacs 28.  Maybe there's a simple solution to my problem but
> nobody pointed me to it so far ...

It should work if your package learns to make use of the new
eldoc-documentation-functions hook. Or eldoc-documentation-strategy,
which calls them.

Needless to say, I'm sure the design I advocated in the referenced
discussion would have had better discoverability and would have been
easier to handle in your case as well, especially regarding backward
compatibility.

But since it has received little support, I'll leave this discussion up
to Joao and those others who approved the current state of affairs.



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
 > Hooks is a list of functions. They get called to fetch the doc
 > information. And now there is some logic called "strategies" that
 > combines the results.

So 'eldoc-documentation-functions' just holds a list of functions I
could call in order to get the documentation of the object at point?
How does the notion of a "hook" enter here?

 > No, the hook functions are written already. They are basically a list
 > of functions that were previously the values of
 > eldoc-documentation-function. Except it's now a list. *And* they use
 > an asynchronous convention where the first argument they receive is a
 > callback.

Is there a way to drop that callback?  I just want an immediate answer.

 > It should work if your package learns to make use of the new
 > eldoc-documentation-functions hook. Or eldoc-documentation-strategy,
 > which calls them.

'eldoc-documentation-strategy' is a variable so it's probably the
function that is the value of that variable and it should suffice to use
'eldoc-documentation-default'.  But this failed here before.

martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

Dmitry Gutov
On 29.09.2020 18:09, martin rudalics wrote:
>  > Hooks is a list of functions. They get called to fetch the doc
>  > information. And now there is some logic called "strategies" that
>  > combines the results.
>
> So 'eldoc-documentation-functions' just holds a list of functions I
> could call in order to get the documentation of the object at point?
> How does the notion of a "hook" enter here?

It's a list that is usually manipulated with 'add-hook'. Like it often
done with other variables named '*-functions'.

>  > No, the hook functions are written already. They are basically a list
>  > of functions that were previously the values of
>  > eldoc-documentation-function. Except it's now a list. *And* they use
>  > an asynchronous convention where the first argument they receive is a
>  > callback.
>
> Is there a way to drop that callback?  I just want an immediate answer.

With my proposal, there would have been. See the original discussion.

>  > It should work if your package learns to make use of the new
>  > eldoc-documentation-functions hook. Or eldoc-documentation-strategy,
>  > which calls them.
>
> 'eldoc-documentation-strategy' is a variable so it's probably the
> function that is the value of that variable and it should suffice to use
> 'eldoc-documentation-default'.  But this failed here before.

You should probably honor this variable, if the expectation is to
generally follow ElDoc's behavior but display the documentation in a
different place, e.g. using a popup.



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
 >> So 'eldoc-documentation-functions' just holds a list of functions I
 >> could call in order to get the documentation of the object at point?
 >> How does the notion of a "hook" enter here?
 >
 > It's a list that is usually manipulated with 'add-hook'. Like it often done with other variables named '*-functions'.

Its value is (elisp-eldoc-var-docstring elisp-eldoc-funcall t).  So what
am I supposed to do with that?  I would have to call these functions in
row with some function as callback argument that also handles the :thing
and :face stuff and produces and returns the doc string.

 >>  > No, the hook functions are written already. They are basically a list
 >>  > of functions that were previously the values of
 >>  > eldoc-documentation-function. Except it's now a list. *And* they use
 >>  > an asynchronous convention where the first argument they receive is a
 >>  > callback.
 >>
 >> Is there a way to drop that callback?  I just want an immediate answer.
 >
 > With my proposal, there would have been. See the original discussion.

So there's no way to drop that callback and get an immediate answer.
Bad to know.

 >> 'eldoc-documentation-strategy' is a variable so it's probably the
 >> function that is the value of that variable and it should suffice to use
 >> 'eldoc-documentation-default'.  But this failed here before.
 >
 > You should probably honor this variable, if the expectation is to generally follow ElDoc's behavior but display the documentation in a different place, e.g. using a popup.

Plain (funcall eldoc-documentation-strategy) gets me the already
familiar (void-function nil) error.

martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

João Távora
In reply to this post by martin rudalics
martin rudalics <[hidden email]> writes:

> When with emacs -Q I put the following snippet into *scratch*
>
> (defun foo ()
>   (ignore))
>
> move point to somewhere on "foo" and do
>

Hi Martin, thanks for the bug report, which I only became aware of
today.  I apologize for the delay in answering.

> M-: (funcall eldoc-documentation-function)

You're not supposed to call the that function in your programs and
neither were you in Emacs 27, much in the same way you normally don't
call, say, adaptive-fill-function, add-log-file-name-function or many
others.  That you _could_ do it in your special circumstances was
incidental, though apparently useful for your third-party extension,
which I wasn't aware of.

Furthermore, calling eldoc-documentation-function directly in Emacs 27
simply doesn't work with a lot of major-modes/extensions that use
`eldoc-mode': ElPy, SLIME, SLY, Eldoc, and probably many others. If you
call the function directly in those modes, it will quite likely return
something other than the desired string, which will potentially appear
in the echo area only some time after.

That is becasue these modes (which all work in Emacs 26, 27 and master)
set eldoc-documentation-function to fetch their docstrings from
asynchronous sources.  Therefore, calling the function won't return the
immediate value you expect, since ElDoc in Emacs 27 doesn't have any
concept of "async".  It is true that in Elisp mode (and maybe some other
modes) you get away with it becasue it doesn't have asynchronous sources
(by default, at least, and mostly becasue it doesn't need to).  This is
why your technique worked, under very special conditions.

This is to clarify that the "direct call" protocol of Emacs 27's
eldoc.el was _never_ "a thing".  At any rate it was never something you
could rely on generally.

Anyway, eldoc-documentation-function is consulted by the Eldoc framework
to provide documentation of the thing at point.  The default value of
that variable has changed and it follows the "new" protocol.  The
documentation is telling you how to craft values that you assign to the
varible, not how your application should interpret them.

If you need a direct call, "give me the string" entry point to the
eldoc.el library, one can be added.  However, its semantics depends on
your use case:

- Do you want to have a return value handy for the docstrings that are
  immediately available from the sources that respond synchronously?

- Do you want to wait actively until all sources have reported back and
  then get a return value?  In this case, do you need a timeout?

- Independent of your choice above, or do you want to get the return
  value as list of strings?  Or as a single string, maybe concatenated
  and propertized, exactly the way it is display

But maybe we are putting the cart ahead of ourselves?  Would you mind
explaining exactly what you are trying to do?  I suppose it's:

> I am using a package that displays the string produced by that
> function in a tooltip near point.

Is this supposed to work only for Elisp mode or in general for every
mode that uses Eldoc, such as the ones I listed above?

If the former, you can probably do this (or some variation):

(defun martin ()
  "CAUTION: Only works in default Emacs Lisp mode or modes with all-sync
docstring generating functions.  If some functions calls the
callback afterwards, that result is discarded."
  (let (res)
    (run-hook-with-args 'eldoc-documentation-functions
                        (cl-function
                         (lambda (doc &key thing face &allow-other-keys)
                           (push (format "%s: %s"
                                         (propertize
                                          (format "%s" thing)
                                          'face face)
                                         doc)
                                 res))))
    (mapconcat #'identity res "\n")))

If the latter, I suggest you look at the code I have in the
scratch/eldoc-display-functions branch, which seems to match your
intentions/use case very closely.  The docstring of the new
eldoc-display-functions variable could be of use (let me know if it's
insuficcient).  This means your advanced tooltip-displaying technology
could now work with every Eldoc mode that uses the "new" protocol
(including, of course, Elisp mode).

As a side note, I would take the opinions of your other interlocutor
here so far with a grain of salt or two.  They're not always grounded in
reality.

Finally, I understand the documentation for the new ElDoc framework is
not very good yet: I will update it soon.  Again, I apologize for the
delay in answering this bug report, but I am extremely busy as of late.
Next time, if you can remember, please X-Debbugs-CC: me in your fresh
bug report on this matter, so that the message reaches me immediately.

Sincerely,
João



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
 >> M-: (funcall eldoc-documentation-function)
 >
 > You're not supposed to call the that function in your programs and
 > neither were you in Emacs 27, much in the same way you normally don't
 > call, say, adaptive-fill-function, add-log-file-name-function or many
 > others.  That you _could_ do it in your special circumstances was
 > incidental, though apparently useful for your third-party extension,
 > which I wasn't aware of.
 >
 > Furthermore, calling eldoc-documentation-function directly in Emacs 27
 > simply doesn't work with a lot of major-modes/extensions that use
 > `eldoc-mode': ElPy, SLIME, SLY, Eldoc, and probably many others. If you
 > call the function directly in those modes, it will quite likely return
 > something other than the desired string, which will potentially appear
 > in the echo area only some time after.

Citing again the Emacs 27 doc-string for 'eldoc-documentation-function'

   Function to call to return doc string.
   The function of no args should return a one-line string for displaying
   doc about a function etc.  appropriate to the context around point.
   It should return nil if there’s no doc appropriate for the context.
   Typically doc is returned if point is on a function-like name or in its
   arg list.

   The result is used as is, so the function must explicitly handle
   the variables ‘eldoc-argument-case’ and ‘eldoc-echo-area-use-multiline-p’,
   and the face ‘eldoc-highlight-function-argument’, if they are to have any
   effect.

so if it did not work for the modes you cite, the doc-string should have
warned about that fact earlier.  While this is certainly not your fault,
changing the semantics of that variable for elisp-mode with the argument
that it did not work for other modes was not a user-friendly step.

Personally I use eldoc for two major modes only: 'emacs-lisp-mode' and
'c-mode' (in a crippled way via 'c-eldoc' but here nobody ever bothered
to write an 'eldoc-documentation-function' function for one of the two
major languages used to implement Emacs).  And as far as the former is
concerned, I now cannot use even 'elisp-eldoc-documentation-function'
directly either because you changed its return value too.

 > That is becasue these modes (which all work in Emacs 26, 27 and master)
 > set eldoc-documentation-function to fetch their docstrings from
 > asynchronous sources.  Therefore, calling the function won't return the
 > immediate value you expect, since ElDoc in Emacs 27 doesn't have any
 > concept of "async".  It is true that in Elisp mode (and maybe some other
 > modes) you get away with it becasue it doesn't have asynchronous sources
 > (by default, at least, and mostly becasue it doesn't need to).  This is
 > why your technique worked, under very special conditions.
 >
 > This is to clarify that the "direct call" protocol of Emacs 27's
 > eldoc.el was _never_ "a thing".  At any rate it was never something you
 > could rely on generally.

At the time "el" in eldoc stood for elisp it was.  But many things
changed since then, admittedly.

 > Anyway, eldoc-documentation-function is consulted by the Eldoc framework
 > to provide documentation of the thing at point.  The default value of
 > that variable has changed and it follows the "new" protocol.  The
 > documentation is telling you how to craft values that you assign to the
 > varible, not how your application should interpret them.
 >
 > If you need a direct call, "give me the string" entry point to the
 > eldoc.el library, one can be added.

I think we should do that and provide it as compatibility layer for
people like me who need it.

 > However, its semantics depends on
 > your use case:
 >
 > - Do you want to have a return value handy for the docstrings that are
 >    immediately available from the sources that respond synchronously?

Definitely.

 > - Do you want to wait actively until all sources have reported back and
 >    then get a return value?  In this case, do you need a timeout?

If we can provide an option for that, yes.

 > - Independent of your choice above, or do you want to get the return
 >    value as list of strings?  Or as a single string, maybe concatenated
 >    and propertized, exactly the way it is display

I'd prefer a list of strings.

 > But maybe we are putting the cart ahead of ourselves?  Would you mind
 > explaining exactly what you are trying to do?  I suppose it's:
 >
 >> I am using a package that displays the string produced by that
 >> function in a tooltip near point.
 >
 > Is this supposed to work only for Elisp mode or in general for every
 > mode that uses Eldoc, such as the ones I listed above?

I explained that above.  I attach a copy of eldoc-tooltip.el here (I
have two other packages to display tooltips either in a separate window
or in the header line but I have not used them for years).  As mentioned
above, I use eldoc for elisp and c only.  For the former I currently use

     (cond
      ((fboundp 'eldoc-tooltip-mode)
       (when (fboundp 'global-eldoc-mode)
        (global-eldoc-mode -1))
       (eldoc-tooltip-mode 1))

because eldoc-tooltip-mode was written some time before
'global-eldoc-mode' was added.

 > If the former, you can probably do this (or some variation):
 >
 > (defun martin ()
 >    "CAUTION: Only works in default Emacs Lisp mode or modes with all-sync
 > docstring generating functions.  If some functions calls the
 > callback afterwards, that result is discarded."
 >    (let (res)
 >      (run-hook-with-args 'eldoc-documentation-functions
 >                          (cl-function
 >                           (lambda (doc &key thing face &allow-other-keys)
 >                             (push (format "%s: %s"
 >                                           (propertize
 >                                            (format "%s" thing)
 >                                            'face face)
 >                                           doc)
 >                                   res))))
 >      (mapconcat #'identity res "\n")))
 >

Works without problems for elisp-mode.  Many thanks.

Now for c-mode I use

       (set (make-local-variable 'eldoc-documentation-function)
           'c-eldoc-print-current-symbol-info)

What can I do here? The same?

 > If the latter, I suggest you look at the code I have in the
 > scratch/eldoc-display-functions branch, which seems to match your
 > intentions/use case very closely.  The docstring of the new
 > eldoc-display-functions variable could be of use (let me know if it's
 > insuficcient).  This means your advanced tooltip-displaying technology
 > could now work with every Eldoc mode that uses the "new" protocol
 > (including, of course, Elisp mode).

OK.  I will look into that later.

 > As a side note, I would take the opinions of your other interlocutor
 > here so far with a grain of salt or two.  They're not always grounded in
 > reality.

My other interlocutor here was Dmitry Gutov.  Please refer to him with
his name.  And I highly appreciate the fact that he was the only person
to answer my bug report within a day or two.

 > Finally, I understand the documentation for the new ElDoc framework is
 > not very good yet: I will update it soon.  Again, I apologize for the
 > delay in answering this bug report, but I am extremely busy as of late.
 > Next time, if you can remember, please X-Debbugs-CC: me in your fresh
 > bug report on this matter, so that the message reaches me immediately.

I'll do that.

Many thanks, martin

eldoc-tooltip.el (23K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

martin rudalics
 > Maybe there are examples but I can't find a single example of a user
 > variable ending in "-function" that's supposed to work like you describe
 > or that explicitly advocates for it/against it.  If libraries establish
 > these variable indirections in the first place, it's because they expect
 > to be able to call them in the contexts of their choosing.  So it never
 > crossed my mind, or my eyes that one would be expecting to use it like
 > that, neither did anyone specifically call attention to this and/or
 > provided an example.

We probably should be more defensive when writing doc-strings for such
variables.

 >> And as far as the former is concerned, I now cannot use even
 >> 'elisp-eldoc-documentation-function' directly either because you
 >> changed its return value too.
 >
 > I looked up uses of that function in the Emacs source tree and couldn't
 > find any.  Because of the reasoning explained above, I also expected
 > Elisp mode to be its sole reasonable user.

Agreed if you meant to say that eldoc-mode would be the sole reasonable
user of 'elisp-eldoc-documentation-function'.

 > But if you really insist ,
 > it's a very easy function to bring back I would say (in fact the
 > function I gave you earlier is probably more useful generalization of
 > it).

I won't insist if I have something that substitutes it.  And if you can
provide that something within eldoc.el, a simple cross reference from
the doc-string of 'eldoc-documentation-function(s)' would be enough.

 >>> If you need a direct call, "give me the string" entry point to the
 >>> eldoc.el library, one can be added.
 >>
 >> I think we should do that and provide it as compatibility layer for
 >> people like me who need it.
 >
 > OK.  Do you know very many of those?

No.  Do you know anyone who displays eldoc outside of the echo area?

 >>> - Do you want to have a return value handy for the docstrings that are
 >>>     immediately available from the sources that respond synchronously?
 >>
 >> Definitely.
 >
 > That would be very close to the `martin` function I gave you earlier.

Yes.

 >>> - Do you want to wait actively until all sources have reported back and
 >>>     then get a return value?  In this case, do you need a timeout?
 >>
 >> If we can provide an option for that, yes.
 >
 > It's easy to do (Eldoc's current version has to do it already).

OK.

 >>> - Independent of your choice above, or do you want to get the return
 >>>     value as list of strings?  Or as a single string, maybe concatenated
 >>>     and propertized, exactly the way it is display[ed in the echo area].
 >>
 >> I'd prefer a list of strings.
 >
 > What about a slightly more complex type? (but not much)

No objections.

 > As of now, "enriched" docstrings can be seen as the association of a
 > string with a number of properties, say the "thing" being documented, or
 > the preferred "face" to do it in.  Later on, a piece of documentation
 > can have, for example, other optional meta-hints about it, such as the
 > language or variations on itself for displaying under a very limiting
 > context (such as the echo area), or very permissive context (such as a
 > spacious Help-like buffer).

I certainly would not mind a buffer (like *eldoc-latest*) that I could
consult to obtain the latest information eldoc caught about the symbol
at point of the selected window either.  Maybe together with some status
indicator about how much of that information has been retrieved already.

 > So I think it the return value of such a function should thus be:
 >
 >      ...a list (DOC ...) where DOC looks like (STRING :KEY VALUE :KEY2
 >      VALUE2 ...).  STRING is the a possibly propertized string
 >      containing the documentation's text and the remainder of DOC is
 >      an optional list of keyword-value pairs, described in
 >     `eldoc-documentation-functions'.
 >
 > This will make the return value of the desired function match the values
 > given to eldoc-display-functions, which could come in advantageious.

What, in a nutshell, would these 'eldoc-display-functions' be (sorry but
my master on this system is in an inconsistent state and I don't want to
resolve conflicts when pulling anything into it)?

martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function

João Távora
martin rudalics <[hidden email]> writes:

>> Maybe there are examples but I can't find a single example of a user
>> variable ending in "-function" that's supposed to work like you describe
>> or that explicitly advocates for it/against it.  If libraries establish
> We probably should be more defensive when writing doc-strings for such
> variables.

Maybe, but none of the docstrings of foo-bar-function variables I
consulted explicitly say that you shouldn't call them directly and that
that task is reserved for foo.el.  But that's factually how they work.
When foo.el intends for a function to be called by programs it usually
provides 'foo-bar', the function, not 'foo-bar-function', the variable.

>>> And as far as the former is concerned, I now cannot use even
>>> 'elisp-eldoc-documentation-function' directly either because you
>>> changed its return value too.
>>
>> I looked up uses of that function in the Emacs source tree and couldn't
>> find any.  Because of the reasoning explained above, I also expected
>> Elisp mode to be its sole reasonable user.
>
> Agreed if you meant to say that eldoc-mode would be the sole reasonable
> user of 'elisp-eldoc-documentation-function'.

Yes, that's what I meant.

>> But if you really insist , it's a very easy function to bring back I
>> would say (in fact the function I gave you earlier is probably more
>> useful generalization of it).
>
> I won't insist if I have something that substitutes it.  And if you can
> provide that something within eldoc.el, a simple cross reference from
> the doc-string of 'eldoc-documentation-function(s)' would be enough.

eldoc-documentation-function (singular) is now obsolete.  If we do come
up with such a synchronous, direct-call, get-me-the-docs function, it
makes of course sense to document it somewhere.

>>>> If you need a direct call, "give me the string" entry point to the
>>>> eldoc.el library, one can be added.
>>>
>>> I think we should do that and provide it as compatibility layer for
>>> people like me who need it.
>>
>> OK.  Do you know very many of those?
>
> No.  Do you know anyone who displays eldoc outside of the echo area?

Indeed I do.  Yuan Fu is working on a eldoc-box extension that displays
documentation kind of a tooltip (a child frame I think it's called).

  https://github.com/casouri/eldoc-box/blob/master/eldoc-box.el

Its implementation should also be considerably simplified by the
upcoming eldoc-display-functions.  But currently it uses
eldoc-message-function which is not perfect for the async case.  At any
rate, it's more reliable than calling eldoc-documentation-function as
you used to do.

Additionally, eldoc.el itself can now display in a *eldoc for <thing>*
buffer (much as you suggest below).  In the latest branch, that is
handled by a display function called eldoc-display-in-buffer.

>>>> - Independent of your choice above, or do you want to get the return
>>>>     value as list of strings?  Or as a single string, maybe concatenated
>>>>     and propertized, exactly the way it is display[ed in the echo area].
>>>
>>> I'd prefer a list of strings.
>>
>> What about a slightly more complex type? (but not much)
>
> No objections.
>
>> As of now, "enriched" docstrings can be seen as the association of a
>> string with a number of properties, say the "thing" being documented, or
>> the preferred "face" to do it in.  Later on, a piece of documentation
>> can have, for example, other optional meta-hints about it, such as the
>> language or variations on itself for displaying under a very limiting
>> context (such as the echo area), or very permissive context (such as a
>> spacious Help-like buffer).
>
> I certainly would not mind a buffer (like *eldoc-latest*) that I could
> consult to obtain the latest information eldoc caught about the symbol
> at point of the selected window either.  Maybe together with some status
> indicator about how much of that information has been retrieved
> already.

I think your desired *eldoc-latest* buffer is the return value of the
nullary eldoc-doc-buffer function.  The buffer indeed has the "latest"
documentation, but it, by itself, currently doesn't tell you how many of
the eldoc-documentation-functions (plural) have yet to respond.

That knowledge exists and is held by internal mechanisms of eldoc.el.
We could expose it, but I prefer to avoid doing that unless a clear need
arises (that isn't handled by anything else).

>> So I think it the return value of such a function should thus be:
>>
>>      ...a list (DOC ...) where DOC looks like (STRING :KEY VALUE :KEY2
>>      VALUE2 ...).  STRING is the a possibly propertized string
>>      containing the documentation's text and the remainder of DOC is
>>      an optional list of keyword-value pairs, described in
>>     `eldoc-documentation-functions'.
>>
>> This will make the return value of the desired function match the values
>> given to eldoc-display-functions, which could come in advantageious.
>
> What, in a nutshell, would these 'eldoc-display-functions' be (sorry but
> my master on this system is in an inconsistent state and I don't want to
> resolve conflicts when pulling anything into it)?

No problem, here's the full docstring of the variable:

    (defvar eldoc-display-functions
      '(eldoc-display-in-echo-area eldoc-display-in-buffer)
      "Hook of functions tasked with displaying ElDoc results.
    Each function is passed two arguments: DOCS and INTERACTIVE. DOCS
    is a list (DOC ...) where DOC looks like (STRING :KEY VALUE :KEY2
    VALUE2 ...).  STRING is the a possibly propertized string
    containing the documentation's text and the remainder of DOC is
    an optional list of keyword-value pairs, described in
    `eldoc-documentation-functions'.
     
    INTERACTIVE says if the request to display doc strings came
    directly from the user or from ElDoc's automatic mechanisms'.")

Mind you, this is only a draft.  In particular, I wonder if point (and
mouse position?) at the time when eldoc.el decided to automatically
request documentation should also be passed in somehow.  Maybe we could
reuse the INTERACTIVE argument, which currently is non-nil only if user
specifically pressed M-x eldoc on a thing to document.

Yours sincerely,
João




Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
In reply to this post by martin rudalics
martin rudalics <[hidden email]> writes:

> What, in a nutshell, would these 'eldoc-display-functions' be (sorry but
> my master on this system is in an inconsistent state and I don't want to
> resolve conflicts when pulling anything into it)?

Hi, Martin

I just pushed a cleaned-up improved version of the
eldoc-display-functions branch.

To git.sv.gnu.org:/srv/git/emacs.git
 * [new branch]            scratch/eldoc-display-functions -> scratch/eldoc-display-functions

After a cursory reading of it, I managed to adapt your eldoc-tooltip.el
library to use it.  I didn't make many changes and didn't test it
thoroughly, but I believe the adaptation works nicely.  I attach it as
file eldoc-tooltip-joao.el.  It needs the eldoc-display-functions
branch, obviously, which I will test for a few more than, then push to
master (it's a straightforward planned change and seems pretty stable).

To make it work pre-emacs-28 (where no eldoc-documentation-functions or
eldoc-display-functions exist) shouldn't be extremely hard, but I didn't
make that effort.  Obviously it won't work with asynchronous doc
backends there, but as it didn't before that's not new.

I also include Yuan Fu in this conversation, the author of the
aforementioned eldoc-box.el extension.  It seems both of you are working
in very similar funcionality.  Maybe some of it might make it into emacs
proper as one or more elements that a user can add to
eldoc-display-functions.

João


eldoc-tooltip-joao.el (21K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

martin rudalics
 > I just pushed a cleaned-up improved version of the
 > eldoc-display-functions branch.
 >
 > To git.sv.gnu.org:/srv/git/emacs.git
 >  * [new branch]            scratch/eldoc-display-functions ->
 > scratch/eldoc-display-functions

Thank you.  I had some autoload problems ('ede-add-project-autoload'
had a void function definition) so I had to bootstrap Emacs here which
took some time.

 > After a cursory reading of it, I managed to adapt your eldoc-tooltip.el
 > library to use it.  I didn't make many changes and didn't test it
 > thoroughly, but I believe the adaptation works nicely.  I attach it as
 > file eldoc-tooltip-joao.el.  It needs the eldoc-display-functions
 > branch, obviously, which I will test for a few more than, then push to
 > master (it's a straightforward planned change and seems pretty stable).

I tried that now and it doesn't work here for two reasons:

(1) It behaves like a solution that I worked out before you answered
my original report.  Both omit the function name when point is on that
name: For example, with point on 'setq' in (setq foo 3) I just get

([SYM VAL]...)

and no reference to the function itself as in the expected

setq: ([SYM VAL]...)

Or with point on some 'cons' I only get (CAR CDR).

(2) My pop-up-mini window child frame pops up whenever a tooltip is
immanent and shows the _expected_ full eldoc text in the echo area.

Now one aim of eldoc-tooltip is to show eldoc information in a separate
window near point and the other is to never show eldoc information in
the echo area so to avoid polluting the latter's contents and popping up
my minibuffer frame all the time.

But maybe also my set-up is wrong now - apparently I have to (1) enable
'global-eldoc-mode' in order to produce eldoc text and (2)
'eldoc-tooltip-mode' in order to show the text in a tooltip.  Is that
right?

martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
martin rudalics <[hidden email]> writes:

>> I just pushed a cleaned-up improved version of the
>> eldoc-display-functions branch.
>>
>> To git.sv.gnu.org:/srv/git/emacs.git
>>  * [new branch]            scratch/eldoc-display-functions ->
>> scratch/eldoc-display-functions
>
> Thank you.  I had some autoload problems ('ede-add-project-autoload'
> had a void function definition) so I had to bootstrap Emacs here which
> took some time.

I had the same problem: it appeared in Emacs master recently.

>> After a cursory reading of it, I managed to adapt your eldoc-tooltip.el
>> library to use it.  I didn't make many changes and didn't test it
>> thoroughly, but I believe the adaptation works nicely.  I attach it as
>> file eldoc-tooltip-joao.el.  It needs the eldoc-display-functions
>> branch, obviously, which I will test for a few more than, then push to
>> master (it's a straightforward planned change and seems pretty stable).
>
> I tried that now and it doesn't work here for two reasons:
>
> (1) It behaves like a solution that I worked out before you answered
> my original report.  Both omit the function name when point is on that
> name: For example, with point on 'setq' in (setq foo 3) I just get
>
> ([SYM VAL]...)
>
> and no reference to the function itself as in the expected

Right, as I said, this is to show you how eldoc-display-function works,
not to fix your library definitely.  Anyway, in the
eldoc-tooltip-joao.el file I gave you, I passed the function #'car to
mapconcat, right?  This was just a quick and lazy solution: to get that
augmented information you have to pass it a function that uses more
properties of the list that represent a piece of documentation.  But I
think the previous 'martin' function I gave you should have exactly that
string producing function inside it, right?

> (2) My pop-up-mini window child frame pops up whenever a tooltip is
> immanent and shows the _expected_ full eldoc text in the echo area.
>
> Now one aim of eldoc-tooltip is to show eldoc information in a separate
> window near point and the other is to never show eldoc information in
> the echo area so to avoid polluting the latter's contents and popping up
> my minibuffer frame all the time.

Makes perfect sense I guess.  You should be able to

  (remove-hook 'eldoc-display-functions 'eldoc-display-in-echo-area)

If you're not a fan of the echo area display.

> But maybe also my set-up is wrong now - apparently I have to (1) enable
> 'global-eldoc-mode' in order to produce eldoc text and (2)
> 'eldoc-tooltip-mode' in order to show the text in a tooltip.  Is that
> right?

Yes, it is.  But do you really need a minor mode?  I think activating
your extension could be a matter of:

  (remove-hook 'eldoc-display-functions 'eldoc-display-in-martins-tooltip)

instead of a global minor mode.  Then you would let ElDoc mode _drive_
your extension.



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

martin rudalics
 >> Thank you.  I had some autoload problems ('ede-add-project-autoload'
 >> had a void function definition) so I had to bootstrap Emacs here which
 >> took some time.
 >
 > I had the same problem: it appeared in Emacs master recently.

Good to know.  It's such problems that make me avoid pulling master
unless it's absolutely necessary.

 > Right, as I said, this is to show you how eldoc-display-function works,
 > not to fix your library definitely.

I see.

 > Anyway, in the
 > eldoc-tooltip-joao.el file I gave you, I passed the function #'car to
 > mapconcat, right?  This was just a quick and lazy solution: to get that
 > augmented information you have to pass it a function that uses more
 > properties of the list that represent a piece of documentation.  But I
 > think the previous 'martin' function I gave you should have exactly that
 > string producing function inside it, right?

I tried to do that but wasn't able to get some useful behavior out of
it.  All Emacs tells me is that it was entering the debugger.  Since you
have both, the 'martin' function and the eldoc-tooltip-joao.el file,
could you please just put the former into the latter and send it to me
so I'm not doing anything wrong.

Maybe it's also the 'martin' function itself but I also (1) get an
empty tooltip using that function in my normal eldoc-tooltip.el - so
'martin' apparently does not always "return nil when there’s no doc
appropriate for the context" and (2) window scrolling sometimes stops
here without apparent reason - something which may be completely
unrelated to the eldoc problem, given that I have not pulled master
for months.

 >> (2) My pop-up-mini window child frame pops up whenever a tooltip is
 >> immanent and shows the _expected_ full eldoc text in the echo area.
 >>
 >> Now one aim of eldoc-tooltip is to show eldoc information in a separate
 >> window near point and the other is to never show eldoc information in
 >> the echo area so to avoid polluting the latter's contents and popping up
 >> my minibuffer frame all the time.
 >
 > Makes perfect sense I guess.  You should be able to
 >
 >    (remove-hook 'eldoc-display-functions 'eldoc-display-in-echo-area)

This works indeed.

 > Yes, it is.  But do you really need a minor mode?  I think activating
 > your extension could be a matter of:
 >
 >    (remove-hook 'eldoc-display-functions 'eldoc-display-in-martins-tooltip)
 >
 > instead of a global minor mode.  Then you would let ElDoc mode _drive_
 > your extension.

I'm not yet sure of the consequences of doing that.

Thanks, martin




Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
martin rudalics <[hidden email]> writes:

> I tried to do that but wasn't able to get some useful behavior out of
> it.  All Emacs tells me is that it was entering the debugger.  Since you
> have both, the 'martin' function and the eldoc-tooltip-joao.el file,
> could you please just put the former into the latter and send it to me
> so I'm not doing anything wrong.

OK.  I've done a bit more work on that file, which I attach.  See the
Commentary: section.  You'll notice I removed a eldoc-tooltip--make-2
function and removed the global mode (I don't think it's strictly needed
and sort of stands in the way of this useful functionality, but you can
add it back, if you wish.)

> Maybe it's also the 'martin' function itself but I also (1) get an
> empty tooltip using that function in my normal eldoc-tooltip.el - so
> 'martin' apparently does not always "return nil when there’s no doc
> appropriate for the context" and (2) window scrolling sometimes stops
> here without apparent reason - something which may be completely
> unrelated to the eldoc problem, given that I have not pulled master
> for months.

Right, I fixed these bugs in the eldoc-tooltip-joao.el.  Sorry, but last
time I tested only very briefly, now I spent some more minutes on it.

>> Makes perfect sense I guess.  You should be able to
>>
>>    (remove-hook 'eldoc-display-functions 'eldoc-display-in-echo-area)
>
> This works indeed.

It's good to have some third party testing being done on this.

>> instead of a global minor mode.  Then you would let ElDoc mode _drive_
>> your extension.
>
> I'm not yet sure of the consequences of doing that.

Hopefully, a very useful new feature that works cooperates fully with
the ElDoc framework.

We'll see later how to add backward compatibility to Emacs 27 and
earlier.  Instead of reimplementing ElDoc's idle timers, I think the
best bet is to leverage `eldoc-message` either via
`eldoc-message-function' or with some advice for older version, like
Yuan Fu does.  It won't be as clean as the Emacs 28 implementation, but
should work.

João


eldoc-tooltip-joao.el (16K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

martin rudalics
 > Right, I fixed these bugs in the eldoc-tooltip-joao.el.  Sorry, but last
 > time I tested only very briefly, now I spent some more minutes on it.

Now if I insert in *scratch*

(setq foo 3)

and move point to 'foo', it gets me a tooltip like

nil: (([SYM VAL]...) :thing setq :face font-lock-keyword-face)

while the echo area gives the expected

setq: ([SYM VAL]...)

Naively spoken: Can't we use the contents of the *eldoc for setq*
buffer here?

Thanks, martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
I must have given you the wrong version of the file,
sorry, I had that problem too at some point.  Probably
forgot to save before attaching.  If only there was some
way to control versioning of source files...

Anyway, your technique is perfectly valid too, in fact that's
the approach that `eldoc-display-in-echo-area` uses. But it's
slightly more correct to read the information for docs directly
because the buffer might eventually be rendered in ways that
don't make sense for tooltips.

João



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
In reply to this post by martin rudalics
martin rudalics <[hidden email]> writes:

>> Right, I fixed these bugs in the eldoc-tooltip-joao.el.  Sorry, but last
>> time I tested only very briefly, now I spent some more minutes on it.
>
> Now if I insert in *scratch*

Here's the updated version of the file (let's hope I got it right, still
stubbornly avoiding Git for this...)

I left some comments in the code about commenting out these lines, which
interfered witht he echo-area display in my testing.

;; (add-hook 'window-configuration-change-hook 'eldoc-tooltip--hide-tip)
;; (add-hook 'window-size-change-functions 'eldoc-tooltip--hide-tip)

João


eldoc-tooltip-joao.el (16K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

martin rudalics
 > Here's the updated version of the file (let's hope I got it right, still
 > stubbornly avoiding Git for this...)

Thanks.  It works now as expected.

 > I left some comments in the code about commenting out these lines, which
 > interfered witht he echo-area display in my testing.
 >
 > ;; (add-hook 'window-configuration-change-hook 'eldoc-tooltip--hide-tip)
 > ;; (add-hook 'window-size-change-functions 'eldoc-tooltip--hide-tip)

Nowadays, I wouldn't add these anyway.  In my experience, tooltips hide
quicker than I'm able to change anything in the windows setup.  OTOH in
my regular flow of work, I'd never want the mini window to expand or
otherwise grab my attention just because I moved point.  Hence, in my
personal use, I'd always keep echo area display disabled.

martin



Reply | Threaded
Open this post in threaded view
|

bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]

João Távora
On Thu, Oct 8, 2020 at 9:22 AM martin rudalics <[hidden email]> wrote:
>
>  > Here's the updated version of the file (let's hope I got it right, still
>  > stubbornly avoiding Git for this...)
>
> Thanks.  It works now as expected.

Happy to register that.

>  > I left some comments in the code about commenting out these lines, which
>  > interfered witht he echo-area display in my testing.
>  >
>  > ;; (add-hook 'window-configuration-change-hook 'eldoc-tooltip--hide-tip)
>  > ;; (add-hook 'window-size-change-functions 'eldoc-tooltip--hide-tip)
>
> Nowadays, I wouldn't add these anyway.  In my experience, tooltips hide
> quicker than I'm able to change anything in the windows setup.  OTOH in
> my regular flow of work, I'd never want the mini window to expand or
> otherwise grab my attention just because I moved point.  Hence, in my
> personal use, I'd always keep echo area display disabled.

That makes perfect sense, too, but elements in eldoc-display-functions
must coexist peacefully with other elements there.  Currently, the
implementation is oblivious to the order of functions in
eldoc-display-funcions.  Maybe that could be changed, and
as such we'd have the eldoc-display-in-tooltip function happen
before in the list and say "no more functions after me".

Anyway, this is only relevant if you're thinking of integrating
your tooltip display in Emacs proper, eldoc or thereabouts.
Are you?

João



12