unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#43609: 28.0.50; eldoc-documentation-function
@ 2020-09-25  8:46 martin rudalics
  2020-09-26 18:34 ` Dmitry Gutov
  2020-09-30 14:37 ` João Távora
  0 siblings, 2 replies; 41+ messages in thread
From: martin rudalics @ 2020-09-25  8:46 UTC (permalink / raw)
  To: 43609

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






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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-25  8:46 bug#43609: 28.0.50; eldoc-documentation-function martin rudalics
@ 2020-09-26 18:34 ` Dmitry Gutov
  2020-09-27  8:30   ` martin rudalics
  2020-09-30 14:37 ` João Távora
  1 sibling, 1 reply; 41+ messages in thread
From: Dmitry Gutov @ 2020-09-26 18:34 UTC (permalink / raw)
  To: martin rudalics, 43609

Hi Martin,

On 25.09.2020 11:46, martin rudalics wrote:
> 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))

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

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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-26 18:34 ` Dmitry Gutov
@ 2020-09-27  8:30   ` martin rudalics
  2020-09-29 11:20     ` Dmitry Gutov
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-09-27  8:30 UTC (permalink / raw)
  To: Dmitry Gutov, 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-27  8:30   ` martin rudalics
@ 2020-09-29 11:20     ` Dmitry Gutov
  2020-09-29 15:09       ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: Dmitry Gutov @ 2020-09-29 11:20 UTC (permalink / raw)
  To: martin rudalics, 43609

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.





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-29 11:20     ` Dmitry Gutov
@ 2020-09-29 15:09       ` martin rudalics
  2020-09-29 15:23         ` Dmitry Gutov
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-09-29 15:09 UTC (permalink / raw)
  To: Dmitry Gutov, 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-29 15:09       ` martin rudalics
@ 2020-09-29 15:23         ` Dmitry Gutov
  2020-09-30  8:14           ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: Dmitry Gutov @ 2020-09-29 15:23 UTC (permalink / raw)
  To: martin rudalics, 43609

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.





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-29 15:23         ` Dmitry Gutov
@ 2020-09-30  8:14           ` martin rudalics
  2020-09-30  8:50             ` Dmitry Gutov
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-09-30  8:14 UTC (permalink / raw)
  To: Dmitry Gutov, 43609

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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-30  8:14           ` martin rudalics
@ 2020-09-30  8:50             ` Dmitry Gutov
  0 siblings, 0 replies; 41+ messages in thread
From: Dmitry Gutov @ 2020-09-30  8:50 UTC (permalink / raw)
  To: martin rudalics, 43609; +Cc: João Távora, Stefan Monnier

On 30.09.2020 11:14, martin rudalics wrote:
>  >> 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.

...that receives the :thing, and :face, and the doc string, and prints 
it out appropriately.

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

Le sigh.

This is the point where I'm bowing out.





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-25  8:46 bug#43609: 28.0.50; eldoc-documentation-function martin rudalics
  2020-09-26 18:34 ` Dmitry Gutov
@ 2020-09-30 14:37 ` João Távora
  2020-09-30 17:33   ` martin rudalics
  1 sibling, 1 reply; 41+ messages in thread
From: João Távora @ 2020-09-30 14:37 UTC (permalink / raw)
  To: martin rudalics; +Cc: 43609

martin rudalics <rudalics@gmx.at> 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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-30 14:37 ` João Távora
@ 2020-09-30 17:33   ` martin rudalics
  2020-09-30 18:22     ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-09-30 17:33 UTC (permalink / raw)
  To: João Távora; +Cc: 43609

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

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

[-- Attachment #2: eldoc-tooltip.el --]
[-- Type: text/x-emacs-lisp, Size: 23083 bytes --]

;;; eldoc-tooltip.el --- show ElDoc as tooltips  -*- lexical-binding:t -*-

;; Copyright (C) 2015  Free Software Foundation, Inc.

;; Time-stamp: "2016-01-11 08:55:41 martin"
;; Author: Martin Rudalics <rudalics@gmx.at>
;; Keywords: ElDoc, tooltips
;; Version: 1.0

;; eldoc-tooltip.el 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, or (at
;; your option) any later version.

;; eldoc-tooltip.el 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 <http://www.gnu.org/licenses/>.

;;; Commentary:

;; ElDoc tooltip mode is a minor mode to show the function arglist or
;; variable docstring provided by `eldoc-documentation-function' in a
;; tooltip window.

;; To turn on this mode automatically (and simultaneously turn off
;; showing tooltips in the echo area) put
;;
;;      (eldoc-tooltip-mode 1)
;;	(global-eldoc-mode -1)
;;
;; into your .emacs.

;; Eldoc tooltip mode requires Emacs 25 or higher for its handling of
;; toolbar window positioning.  It requires `eldoc' only to (1) get
;; access to `eldoc-documentation-function' and (2) override the option
;; `eldoc-echo-area-use-multiline-p' in invocations of the former.

;;; Code:
(defgroup eldoc-tooltip nil
  "Show ElDoc in tooltips."
  :version "25.1"
  :group 'extensions)

;;;###autoload
(define-minor-mode eldoc-tooltip-mode
  "Toggle ElDoc tooltip mode on or off."
  :group 'eldoc-tooltip
  (if eldoc-tooltip-mode
      (progn
	(set-frame-parameter nil 'eldoc-focus t)
	(add-hook 'focus-in-hook 'eldoc-tooltip--focus-in)
	(add-hook 'focus-out-hook 'eldoc-tooltip--focus-out)
	(add-hook 'window-configuration-change-hook 'eldoc-tooltip--hide-tip)
	(add-hook 'window-size-change-functions 'eldoc-tooltip--hide-tip)
	(unless (memq eldoc-tooltip-idle-timer timer-idle-list)
	  (setq eldoc-tooltip-idle-timer
		(run-with-idle-timer
		 eldoc-tooltip-delay t
		 (if (fboundp 'window-absolute-body-pixel-edges)
		     'eldoc-tooltip--make-2
		 'eldoc-tooltip--make)))))
    (when eldoc-tooltip-idle-timer
      (cancel-timer eldoc-tooltip-idle-timer)
      (setq eldoc-tooltip-idle-timer nil))
    (remove-hook 'focus-in-hook 'eldoc-tooltip--focus-in)
    (remove-hook 'focus-out-hook 'eldoc-tooltip--focus-out)
    (remove-hook 'window-configuration-change-hook 'eldoc-tooltip--hide-tip)
    (remove-hook 'window-size-change-functions 'eldoc-tooltip--hide-tip)))

(defgroup eldoc-tooltip nil
  "Show function arglist or variable docstring in tooltip."
  :group 'eldoc)

(defcustom eldoc-tooltip-delay 1.0
  "Number of seconds of idle time to wait before showing eldoc tooltip.
If user input arrives before this interval of time has elapsed after the
last input, no documentation will be shown.

If this variable is set to 0, no idle time is required."
  :type 'number
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-duration 60
  "Number of seconds to show eldoc tooltip.
If user input arrives before this time has elapsed, the tooltip will be
hidden."
  :type 'number
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-location 'eols
  "Where to show ElDoc tooltip.
Options are:

`above' - over text on line above point

`below' - over text on line below point

`eols' - at ends of lines near point

`top' on top of selected window

`bottom' - on bottom of selected window"
  :type '(choice (const :tag "on line above point" above)
                 (const :tag "on line below point" below)
                 (const :tag "at line ends near point" eols)
                 (const :tag "on top of selected window" top)
                 (const :tag "on bottom of selected window" bottom))
  :group 'eldoc-tooltip)


(defcustom eldoc-tooltip-x-offset-alist
  '((above . 2) (current . 2) (below . 2) (top . 2) (bottom . 2))
  "Offsets to adjust x-position of tooltips.
These pixel offsets are added to the x-position of tooltips that
respectively appear on the line above the current line (`above'),
the current line (`current'), the line below the current
line (`below'), the top edge of the window (`top') and the bottom
edge of the window (`bottom')."
  :type '(alist :key-type (symbol :tag "Location")
		:value-type integer)
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-indent-above-below t
  "Non-nil means to show tooltips at indent of current line.
This options takes affect only when tooltips shown at the
beginning of a line, that is when `eldoc-tooltip-location' equals
`above' or `below'.  When this option is nil, such tooltips start
at the visual beginning of the respective line."
  :type 'boolean
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-current-eol-extra-x-offset t
  "Extra offset for tooltip at end of current line.
If non-nil this adds an extra offset of one character's width to
avoid that the tooltip window overlays a block cursor at the end
of the current line.  If nil the offset is entirely determined by
the value of `eldoc-tooltip-x-offsets'.  Tooltips appearing
above or below the current line are not affected by this option."
  :type 'boolean
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-y-offset-alist
  '((above . 0) (current . -2) (below . -2) (top . 2) (bottom . -2))
  "Alist of offsets to adjust y-position of tooltips.
These pixel offsets are added to the y-position of tooltips that
respectively appear on the line above the current line (`above'),
the current line (`current'), the line below the current
line (`below'), the top edge of the window (`top') and the bottom
edge of the window (`bottom')."
  :type '(alist :key-type (symbol :tag "Location")
		:value-type integer)
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-max-size '(120 . 1)
  "Maximimum size of ElDoc tooltips.
A cons of rows and columns."
  :type '(cons (integer :tag "Columns")
	       (integer :tag "Lines"))
  :group 'eldoc-tooltip)

(defcustom eldoc-tooltip-frame-parameters
  '((background-color . "honeydew")
    (alpha . 60))
  "Frame parameter alist used for ElDoc tooltips.
The list of frame parameters passed to `x-show-tip' is built by
appending to this a list built from the `left' and `top'/`bottom'
parameters as produced by `eldoc-tooltip-make' and the value of
`tooltip-frame-parameters'."
  :type '(alist :key-type symbol
		:value-type sexp)
  :group 'tooltip)

(defvar eldoc-tooltip-idle-timer nil
  "ElDoc tooltip timer.")

(defvar eldoc-tooltip-debug nil
  "Non-nil means display message about position of tooltip window.")

(defun eldoc-tooltip--focus-in ()
  "ElDoc tooltip mode function when selected frame gains focus."
  (set-frame-parameter nil 'eldoc-focus t))

;; In the following two we should check that we own the tooltip.
(defun eldoc-tooltip--focus-out ()
  "ElDoc tooltip mode function when selected frame loses focus."
  (set-frame-parameter nil 'eldoc-focus nil)
  (x-hide-tip))

(defun eldoc-tooltip--hide-tip (&optional _ignore)
  "Hide ElDoc tooltip."
  (x-hide-tip))

(defun eldoc-tooltip--text ()
  "Return text string for ElDoc tooltip, nil if there's none."
  (save-excursion
    (goto-char (window-point))
    (when (boundp 'eldoc-documentation-function)
      ;; Alwasy try to get full string.
      (let ((eldoc-echo-area-use-multiline-p t))
	(funcall eldoc-documentation-function)))))

(defun eldoc-tooltip--current-line-wrapped-p ()
  "Return non-nil when current line is wrapped."
  (save-excursion
    (< (progn
	 (beginning-of-line)
	 (vertical-motion 1)
	 (point))
       (progn
	 (forward-line)
	 (point)))))

(defun eldoc-tooltip--make ()
  "Make ElDoc tooltip."
  (let* ((pos-point (pos-visible-in-window-p (point) nil t))
	 ;; We make a tooltip iff `point' is visible in the selected
	 ;; window, the frame has focus and we get a suitable text from
	 ;; the corresponding eldoc function.  Remember that
	 ;; `pos-visible-in-window-p' may return non-nil even when POS
	 ;; is scrolled off horizontally.
	 (text (and eldoc-tooltip-mode pos-point
		    (frame-parameter nil 'eldoc-focus)
		    (eldoc-tooltip--text))))
    (when text
      (let* ((edges (window-inside-pixel-edges))
	     (frame-geometry (frame-geometry))
	     ;; 	     (x-frame-geometry)
	     (frame-left-position
	      (or (cadr (assq 'frame-position frame-geometry))
		  (cadr (assq 'outer-position frame-geometry))
		  (nth 1 (assq 'outer-edges frame-geometry))))
	     (frame-top-position
	      (or (cddr (assq 'frame-position frame-geometry))
		  (cddr (assq 'outer-position frame-geometry))
		  (nth 2 (assq 'outer-edges frame-geometry))))
	     (frame-left
	      (let ((edge (frame-parameter nil 'left)))
		(if (numberp edge) edge 0)))
	     (left (+ frame-left
		      ;; Count left border iff frame's left edge is on
		      ;; screen (this should catch frame maximation by
		      ;; moving the border off-display tricks).
		      (if (< frame-left-position 0)
			  0
			(cadr (assq 'external-border-size frame-geometry)))
		      (nth 0 edges)
		      ;; Count tool bar when it's on the left.
		      (or (and (cdr (assq 'tool-bar-external frame-geometry))
			       (eq (cdr (assq 'tool-bar-position frame-geometry))
				   'left)
			       (cddr (assq 'tool-bar-size frame-geometry)))
			  0)
		      ;; Count vertical scroll bar when it's on the
		      ;; left.  Don't care about fringes or margins yet.
		      (if (eq (car (window-current-scroll-bars)) 'left)
			  (window-scroll-bar-width)
			0)))
	     (frame-top
	      (let ((edge (frame-parameter nil 'top)))
		(if (numberp edge) edge 0)))
	     (top
	      (+ frame-top
		 ;; Count top border iff frame's top edge is on screen
		 ;; (to catch frame maximation by moving the border
		 ;; off-display tricks).  Also, apparently ns counts the
		 ;; top border in the title height already.
		 (if (or (< frame-top-position 0)
			 (eq (window-system) 'ns))
		     0
		   (cddr (assq 'external-border-size frame-geometry)))
		 ;; Add heights of title, menu and tool bar but only if
		 ;; they are external (an "internal" tool or menu bar is
		 ;; already counted by `window-pixel-edges').
		 (or (cdr (assq 'title-height frame-geometry))
		     (cddr (assq 'title-bar-size frame-geometry))
		     0)
		 (or (and (cdr (assq 'menu-bar-external frame-geometry))
			  (cddr (assq 'menu-bar-size frame-geometry)))
		     0)
		 (or (and (cdr (assq 'tool-bar-external frame-geometry))
			  (eq (cdr (assq 'tool-bar-position frame-geometry))
			      'top)
			  (cddr (assq 'tool-bar-size frame-geometry)))
		     0)
		 (if (eq eldoc-tooltip-location 'bottom)
		     ;; Don't obscure mode line.
		     (- (nth 3 edges)
			(window-mode-line-height)
			(window-bottom-divider-width))
		   (nth 1 edges))))
	     (x-max-tooltip-size eldoc-tooltip-max-size)
	     parameters)
	(pcase eldoc-tooltip-location
	  ((or `above `below)
	   (let ((x-adjust (or (cdr (assq eldoc-tooltip-location
					  eldoc-tooltip-x-offset-alist))
			       0))
		 (y-adjust (or (cdr (assq eldoc-tooltip-location
					  eldoc-tooltip-y-offset-alist))
			       0))
		 (pos-x
		  (if eldoc-tooltip-indent-above-below
		      (save-excursion
			(beginning-of-line)
			(skip-chars-forward " \t")
			(nth 0 (pos-visible-in-window-p (point) nil t)))
		    0))
		 (pos-y (+ (nth 1 pos-point)
			   (if (eq eldoc-tooltip-location 'above)
			       0
			     ;; `window-line-height' returns nil when
			     ;; display is not up-to-date.
			     (or (car (window-line-height))
				 (frame-char-height))))))
	     (when eldoc-tooltip-debug
	       (message "%s %s %s %s [x: %s %s %s] [y: %s %s %s] -> %s"

			(if (or (< frame-top 0) (eq (window-system) 'ns))
			    0
			  (cddr (assq 'external-border-size frame-geometry)))
			(or (cdr (assq 'title-height frame-geometry))
			    (cddr (assq 'title-bar-size frame-geometry))
			    0)
			(or (and (cdr (assq 'menu-bar-external frame-geometry))
				 (cddr (assq 'menu-bar-size frame-geometry)))
			    0)
			(or (and (cdr (assq 'tool-bar-external frame-geometry))
				 (eq (cdr (assq 'tool-bar-position frame-geometry))
				     'top)
				 (cddr (assq 'tool-bar-size frame-geometry)))
			    0)

			left pos-x x-adjust top pos-y y-adjust
			(cons (+ left 0 x-adjust)
			      (+ top pos-y y-adjust))))
	     (setq parameters
		   (list
		    (cons 'left (+ left pos-x x-adjust))
		    (if (eq eldoc-tooltip-location 'above)
			(cons 'bottom (+ top pos-y y-adjust))
		      (cons 'top (+ top pos-y y-adjust)))))))
	  (`eols
	   (let (where pos-above pos-this pos-below pos-x pos-y x-adjust y-adjust)
	     (setq pos-this (pos-visible-in-window-p (line-end-position) nil t))

	     ;; Try current line first.
	     (when pos-this
	       (setq where 'current)
	       (setq pos-x (nth 0 pos-this))
	       (setq pos-y (nth 1 pos-this)))

	     ;; Try line above next.
	     (when (and (setq pos-above
			      (and (/= (line-beginning-position) (point-min))
				   (pos-visible-in-window-p
				    (line-end-position 0) nil t)))
			(or (not pos-x) (< (nth 0 pos-above) pos-x)))
	       (setq where 'above)
	       (setq pos-x (nth 0 pos-above))
	       (setq pos-y (if truncate-lines
			       ;; When lines are truncated use top
			       ;; of the current line.
			       (nth 1 pos-point)
			     ;; Otherwise use top of beginning of
			     ;; current line.
			     (or (nth 1 (pos-visible-in-window-p
					 (line-beginning-position) nil t))
				 0))))

	     ;; Try line below last.
	     (when (and (/= (line-end-position) (point-max))
			(or truncate-lines
			    (save-excursion
			      (forward-line)
			      (not (eldoc-tooltip--current-line-wrapped-p))))
			(setq pos-below (pos-visible-in-window-p
					 (line-end-position 2) nil t))
			(or (not pos-x) (< (nth 0 pos-below) pos-x)))
		 (setq where 'below)
		 (setq pos-x (nth 0 pos-below))
		 (setq pos-y (nth 1 pos-below)))

	     ;; If we didn't get a result till now simulate `above'.
	     (unless pos-x
	       (setq where 'above)
	       (setq pos-x 0)
	       (setq pos-y (nth 1 pos-point)))

	     ;; If the window is scrolled horizontally, make sure the
	     ;; tooltip doesn't start on the left of it.
	     (setq pos-x (max 0 pos-x))

	     ;; Adjust offsets now.
	     (setq x-adjust
		   (or (cdr (assq where eldoc-tooltip-x-offset-alist)) 0))
	     (setq y-adjust
		   (or (cdr (assq where eldoc-tooltip-y-offset-alist)) 0))

	     (when (and eldoc-tooltip-current-eol-extra-x-offset
			(or (= (point) (point-max)) (looking-at "\n")))
	       ;; Don't obscure block pointer at EOL.
	       (setq x-adjust (+ x-adjust (frame-char-width))))

	     (when eldoc-tooltip-debug
	       (message "%s %s %s %s - %s / %s / %s / %s -> %s [x: %s %s %s] [y: %s %s %s] -> %s"

			(if (or (< frame-top 0) (eq (window-system) 'ns))
			    0
			  (cddr (assq 'external-border-size frame-geometry)))
			(or (cdr (assq 'title-height frame-geometry))
			    (cddr (assq 'title-bar-size frame-geometry))
			    0)
			(or (and (cdr (assq 'menu-bar-external frame-geometry))
				 (cddr (assq 'menu-bar-size frame-geometry)))
			    0)
			(or (and (cdr (assq 'tool-bar-external frame-geometry))
				 (eq (cdr (assq 'tool-bar-position frame-geometry))
				     'top)
				 (cddr (assq 'tool-bar-size frame-geometry)))
			    0)

			pos-above pos-point pos-this pos-below where
			left pos-x x-adjust top pos-y y-adjust
			(cons (+ left pos-x x-adjust)
			      (+ top pos-y y-adjust))))

	     (setq parameters
		   (list
		    (cons 'left (+ left pos-x x-adjust))
		    (if (eq where 'above)
			(cons 'bottom (+ top pos-y y-adjust))
		      (cons 'top (+ top pos-y y-adjust)))))))
	  (`top
	   (let* ((x-adjust (cdr (assq 'top eldoc-tooltip-x-offset-alist)))
		  (y-adjust (cdr (assq 'top eldoc-tooltip-y-offset-alist))))
	     (when eldoc-tooltip-debug
	       (message "[x: %s %s] [y: %s %s] -> %s"
			left x-adjust top y-adjust
			(cons (+ left x-adjust) (+ top y-adjust))))
	     (setq parameters
		   (list
		    (cons 'left (+ left x-adjust))
		    (cons 'bottom (+ top y-adjust))))))
	  (`bottom
	   (let* ((x-adjust (cdr (assq 'top eldoc-tooltip-x-offset-alist)))
		  (y-adjust (cdr (assq 'top eldoc-tooltip-y-offset-alist))))
	     (when eldoc-tooltip-debug
	       (message "[x: %s %s] [y: %s %s] -> %s"
			left x-adjust top y-adjust
			(cons (+ left x-adjust) (+ top y-adjust))))
	     (setq parameters
		   (list
		    (cons 'left (+ left x-adjust))
		    (cons 'bottom (+ top y-adjust)))))))
	;; Show tip.
	(when parameters
	  (x-show-tip
	   text (selected-frame)
	   (append
	    eldoc-tooltip-frame-parameters parameters tooltip-frame-parameters)
	   eldoc-tooltip-duration 0 0))))))

(defun eldoc-tooltip--make-2 ()
  "Make ElDoc tooltip.
`window-absolute-body-pixel-edges' is needed for this."
  (let* ((pos-point (pos-visible-in-window-p (point) nil t))
	 ;; We make a tooltip iff `point' is visible in the selected
	 ;; window, the frame has focus and we get a suitable text from
	 ;; the corresponding eldoc function.  Remember that
	 ;; `pos-visible-in-window-p' may return non-nil even when POS
	 ;; is scrolled off horizontally.
	 (text (and eldoc-tooltip-mode pos-point
		    (frame-parameter nil 'eldoc-focus)
		    (eldoc-tooltip--text)))
	 old-consed)
    ;; Optional.
    (when (boundp 'mode-line-operation-consed)
      (setq old-consed cons-cells-consed))
    (when text
      (let* ((edges (and (fboundp 'window-absolute-body-pixel-edges)
			 (window-absolute-body-pixel-edges)))
	     (left (nth 0 edges))
	     (top (nth 1 edges))
	     (x-max-tooltip-size eldoc-tooltip-max-size)
	     parameters)
	(pcase eldoc-tooltip-location
	  ((or `above `below)
	   (let ((x-adjust (or (cdr (assq eldoc-tooltip-location
					  eldoc-tooltip-x-offset-alist))
			       0))
		 (y-adjust (or (cdr (assq eldoc-tooltip-location
					  eldoc-tooltip-y-offset-alist))
			       0))
		 (pos-x
		  (if eldoc-tooltip-indent-above-below
		      (save-excursion
			(beginning-of-line)
			(skip-chars-forward " \t")
			(nth 0 (pos-visible-in-window-p (point) nil t)))
		    0))
		 (pos-y (+ (nth 1 pos-point)
			   (if (eq eldoc-tooltip-location 'above)
			       0
			     ;; `window-line-height' returns nil when
			     ;; display is not up-to-date.
			     (or (car (window-line-height))
				 (frame-char-height))))))
	     (setq parameters
		   (list
		    (cons 'left (+ left pos-x x-adjust))
		    (if (eq eldoc-tooltip-location 'above)
			(cons 'bottom (+ top pos-y y-adjust))
		      (cons 'top (+ top pos-y y-adjust)))))))
	  (`eols
	   (let (where pos-above pos-this pos-below pos-x pos-y x-adjust y-adjust)
	     (setq pos-this (pos-visible-in-window-p (line-end-position) nil t))

	     ;; Try current line first.
	     (when pos-this
	       (setq where 'current)
	       (setq pos-x (nth 0 pos-this))
	       (setq pos-y (nth 1 pos-this)))

	     ;; Try line above next.
	     (when (and (setq pos-above
			      (and (/= (line-beginning-position) (point-min))
				   (pos-visible-in-window-p
				    (line-end-position 0) nil t)))
			(or (not pos-x) (< (nth 0 pos-above) pos-x)))
	       (setq where 'above)
	       (setq pos-x (nth 0 pos-above))
	       (setq pos-y (if truncate-lines
			       ;; When lines are truncated use top
			       ;; of the current line.
			       (nth 1 pos-point)
			     ;; Otherwise use top of beginning of
			     ;; current line.
			     (or (nth 1 (pos-visible-in-window-p
					 (line-beginning-position) nil t))
				 0))))

	     ;; Try line below last.
	     (when (and (/= (line-end-position) (point-max))
			(or truncate-lines
			    (save-excursion
			      (forward-line)
			      (not (eldoc-tooltip--current-line-wrapped-p))))
			(setq pos-below (pos-visible-in-window-p
					 (line-end-position 2) nil t))
			(or (not pos-x) (< (nth 0 pos-below) pos-x)))
	       (setq where 'below)
	       (setq pos-x (nth 0 pos-below))
	       (setq pos-y (nth 1 pos-below)))

	     ;; If we didn't get a result till now simulate `above'.
	     (unless pos-x
	       (setq where 'above)
	       (setq pos-x 0)
	       (setq pos-y (nth 1 pos-point)))

	     ;; If the window is scrolled horizontally, make sure the
	     ;; tooltip doesn't start on the left of it.
	     (setq pos-x (max 0 pos-x))

	     ;; Adjust offsets now.
	     (setq x-adjust
		   (or (cdr (assq where eldoc-tooltip-x-offset-alist)) 0))
	     (setq y-adjust
		   (or (cdr (assq where eldoc-tooltip-y-offset-alist)) 0))

	     (when (and eldoc-tooltip-current-eol-extra-x-offset
			(eq where 'current)
			(or (= (point) (point-max)) (looking-at "\n")))
	       ;; Don't obscure block pointer at EOL.
	       (setq x-adjust (+ x-adjust (frame-char-width))))

	     (setq parameters
		   (list
		    (cons 'left (+ left pos-x x-adjust))
		    (if (eq where 'above)
			(cons 'bottom (+ top pos-y y-adjust))
		      (cons 'top (+ top pos-y y-adjust)))))))
	  (`top
	   (let* ((x-adjust (cdr (assq 'top eldoc-tooltip-x-offset-alist)))
		  (y-adjust (cdr (assq 'top eldoc-tooltip-y-offset-alist))))
	     (setq parameters
		   (list
		    (cons 'left (+ left x-adjust))
		    (cons 'top (+ top y-adjust))))))
	  (`bottom
	   (let* ((x-adjust (cdr (assq 'bottom eldoc-tooltip-x-offset-alist)))
		  (y-adjust (cdr (assq 'bottom eldoc-tooltip-y-offset-alist))))
	     (setq parameters
		   (list
		    (cons 'left (+ left x-adjust))
		    (cons 'bottom (+ (nth 3 edges) y-adjust)))))))
	(when parameters
	  ;; Show tip first.
	  (x-show-tip
	   text (selected-frame)
	   (append
	    eldoc-tooltip-frame-parameters parameters tooltip-frame-parameters)
	   eldoc-tooltip-duration 0 0)
	  ;; If necessary, move mouse pointer away afterwards.
	  (let* ((buffer (get-buffer " *tip*"))
		 (window (and buffer (get-buffer-window buffer t)))
		 (frame (and window (window-frame window)))
		 (tip-edges (and frame (frame-edges frame 'outer)))
		 (tip-left (nth 0 tip-edges))
		 (tip-top (nth 1 tip-edges))
		 (tip-right (nth 2 tip-edges))
		 (tip-bottom (nth 3 tip-edges))
		 (mouse-position (mouse-absolute-pixel-position))
		 (mouse-x (car mouse-position))
		 (mouse-y (cdr mouse-position)))
	    (when (and tip-left tip-right mouse-x (<= tip-left mouse-x) (<= mouse-x tip-right)
		       tip-top tip-bottom mouse-y (<= tip-top mouse-y) (<= mouse-y tip-bottom))
	      (let* ((window-edges (window-edges nil t t t))
		     (window-top (nth 1 window-edges)))
;; 		(message "frame: %s  tip-left: %s  tip-top: %s  tip-right: %s  tip-bottom: %s"
;; 			 frame tip-left tip-top tip-right tip-bottom)
		(set-mouse-absolute-pixel-position
		 mouse-x
		 ;; If there's enough space within the seelcted window,
		 ;; move mouse pointer two pixels above top of tooltip,
		 ;; otherwise move it one pixel below bottom of tooltip.
		 (if (< (+ window-top 2) tip-top)
		     (- tip-top 2)
		   (1+ tip-bottom)))))))))
    ;; Optional.
    (when (boundp 'mode-line-operation-consed)
      (setq mode-line-operation-consed (- cons-cells-consed old-consed)))
    ))

(provide 'eldoc-tooltip)
;;; eldoc-tooltip.el ends here

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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-30 17:33   ` martin rudalics
@ 2020-09-30 18:22     ` João Távora
  2020-10-01  8:40       ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-09-30 18:22 UTC (permalink / raw)
  To: martin rudalics; +Cc: 43609

martin rudalics <rudalics@gmx.at> writes:

> so if it did not work for the modes you cite, the doc-string should have
> warned about that fact earlier.

IME when these docstrings are built, they don't foresee all possible
uses.  It didn't foresee the async use just like it didn't foresee your
direct call use.

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

I don't really believe I changed the semantics, Martin.  I don't read
anywhere in the docstring that you are to funcall the value stored in
the variable eldoc-documentation-function, merely a description of the
protocol of that the function that you store there should do.  I do
understand that it might be seen as ambiguous by a newcomer, but you're
not exactly a newcomer, right?  :-)

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.

That said I am aware that in Emacs/Lisp _anything_ can happen :-) 

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

If you use the Eglot (or the lsp-mode) extension, you will see there are
increasingly nice solutions for that.

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

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

I agree.  Eldoc is now, and has been for a while, Emacs's de facto (and
only) framework for displaying documentation of things at point.  This
is why it's a piece very much worth improving.

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

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

That would be very close to the `martin` function I gave you earlier.

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

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

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

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.

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

You're welcome.

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

In this case you just call c-eldoc-print-current-symbol-info, right?  Of
course you can _also_ do the former, if you wish, it's just like it
looks like you're not using the ElDoc framework anyway (though I haven't
read your attached tooltip.el code).

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

I'll look at your tooltip.el code and try to make a member function of
eldoc-display-function for it.

> My other interlocutor here was Dmitry Gutov.  Please refer to him with
> his name.

I fully understand that, and normally I would, but this is a special
case of very toxic communication.  So, for the moment, please permit me
to keep my distance, so we can make real progress on this bug.

> And I highly appreciate the fact that he was the only person to answer
> my bug report within a day or two.

Pity the answer didn't help you much.  I don't have time to browse
bug-gnu-emacs daily, sorry.  As I said, next time try to include me
directly.  You also can usually find active maintainers of specific
files (and even regions) with M-x vc-print-log or M-x vc-region-history.

Yours sincerely,
João





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-09-30 18:22     ` João Távora
@ 2020-10-01  8:40       ` martin rudalics
  2020-10-01  9:23         ` João Távora
  2020-10-03 19:15         ` bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions] João Távora
  0 siblings, 2 replies; 41+ messages in thread
From: martin rudalics @ 2020-10-01  8:40 UTC (permalink / raw)
  To: João Távora; +Cc: 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function
  2020-10-01  8:40       ` martin rudalics
@ 2020-10-01  9:23         ` João Távora
  2020-10-03 19:15         ` bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions] João Távora
  1 sibling, 0 replies; 41+ messages in thread
From: João Távora @ 2020-10-01  9:23 UTC (permalink / raw)
  To: martin rudalics; +Cc: 43609

martin rudalics <rudalics@gmx.at> 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






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-01  8:40       ` martin rudalics
  2020-10-01  9:23         ` João Távora
@ 2020-10-03 19:15         ` João Távora
  2020-10-05  8:35           ` martin rudalics
  2020-10-23  2:37           ` Yuan Fu
  1 sibling, 2 replies; 41+ messages in thread
From: João Távora @ 2020-10-03 19:15 UTC (permalink / raw)
  To: martin rudalics; +Cc: casouri, 43609

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

martin rudalics <rudalics@gmx.at> 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


[-- Attachment #2: eldoc-tooltip-joao.el --]
[-- Type: application/emacs-lisp, Size: 22106 bytes --]

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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-03 19:15         ` bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions] João Távora
@ 2020-10-05  8:35           ` martin rudalics
  2020-10-05  9:29             ` João Távora
  2020-10-23  2:37           ` Yuan Fu
  1 sibling, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-05  8:35 UTC (permalink / raw)
  To: João Távora; +Cc: casouri, 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-05  8:35           ` martin rudalics
@ 2020-10-05  9:29             ` João Távora
  2020-10-06  8:23               ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-05  9:29 UTC (permalink / raw)
  To: martin rudalics; +Cc: casouri, 43609

martin rudalics <rudalics@gmx.at> 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.





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-05  9:29             ` João Távora
@ 2020-10-06  8:23               ` martin rudalics
  2020-10-06  9:29                 ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-06  8:23 UTC (permalink / raw)
  To: João Távora; +Cc: casouri, 43609

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






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-06  8:23               ` martin rudalics
@ 2020-10-06  9:29                 ` João Távora
  2020-10-07  8:36                   ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-06  9:29 UTC (permalink / raw)
  To: martin rudalics; +Cc: casouri, 43609

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

martin rudalics <rudalics@gmx.at> 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


[-- Attachment #2: eldoc-tooltip-joao.el --]
[-- Type: application/emacs-lisp, Size: 16386 bytes --]

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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-06  9:29                 ` João Távora
@ 2020-10-07  8:36                   ` martin rudalics
  2020-10-07  8:40                     ` João Távora
  2020-10-07  9:36                     ` João Távora
  0 siblings, 2 replies; 41+ messages in thread
From: martin rudalics @ 2020-10-07  8:36 UTC (permalink / raw)
  To: João Távora; +Cc: casouri, 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-07  8:36                   ` martin rudalics
@ 2020-10-07  8:40                     ` João Távora
  2020-10-07  9:36                     ` João Távora
  1 sibling, 0 replies; 41+ messages in thread
From: João Távora @ 2020-10-07  8:40 UTC (permalink / raw)
  To: martin rudalics; +Cc: Yuan Fu, 43609

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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-07  8:36                   ` martin rudalics
  2020-10-07  8:40                     ` João Távora
@ 2020-10-07  9:36                     ` João Távora
  2020-10-08  8:22                       ` martin rudalics
  1 sibling, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-07  9:36 UTC (permalink / raw)
  To: martin rudalics; +Cc: casouri, 43609

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

martin rudalics <rudalics@gmx.at> 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


[-- Attachment #2: eldoc-tooltip-joao.el --]
[-- Type: application/emacs-lisp, Size: 16971 bytes --]

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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-07  9:36                     ` João Távora
@ 2020-10-08  8:22                       ` martin rudalics
  2020-10-08  8:27                         ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-08  8:22 UTC (permalink / raw)
  To: João Távora; +Cc: casouri, 43609

 > 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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-08  8:22                       ` martin rudalics
@ 2020-10-08  8:27                         ` João Távora
  2020-10-09  8:03                           ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-08  8:27 UTC (permalink / raw)
  To: martin rudalics; +Cc: Yuan Fu, 43609

On Thu, Oct 8, 2020 at 9:22 AM martin rudalics <rudalics@gmx.at> 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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-08  8:27                         ` João Távora
@ 2020-10-09  8:03                           ` martin rudalics
  2020-10-24 15:18                             ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-09  8:03 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

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

I have to use it in practice before I can tell whether it works.  Back
then, it took me some time to make the code do what I meant - put the
tooltip in the right place of the window, move away the mouse cursor if
necessary ...

Meanwhile, please provide the compatibility layer you earlier promised
with

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

so we can close this bug.

Ideally, this would render your earlier changes backward-compatible and
make the obsoletion declaration for 'eldoc-documentation-function' clean
and follow our usual practice.

The downside of this approach is obviously that we would have to keep
the old definitions of 'elisp-eldoc-documentation-function' and its
colleagues around for a while.  So if you think that removing these old
definitions immediately is crucial for future development, please
provide some substitute function and mention it in the doc-string of
'eldoc-documentation-function(s)'.

Thanks in advance, martin





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-03 19:15         ` bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions] João Távora
  2020-10-05  8:35           ` martin rudalics
@ 2020-10-23  2:37           ` Yuan Fu
  2020-10-24 17:09             ` João Távora
  1 sibling, 1 reply; 41+ messages in thread
From: Yuan Fu @ 2020-10-23  2:37 UTC (permalink / raw)
  To: João Távora; +Cc: 43609

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

Hi Joao,

If there are multiple display functions, how does Emacs decide which one to use? Do you have ideas now about what :thing should be?

Yuan

Some typo I spotted:


[-- Attachment #2: eldoc.patch --]
[-- Type: application/octet-stream, Size: 2050 bytes --]

diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 4c8d8222ea..356092d670 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -110,7 +110,7 @@ eldoc-echo-area-use-multiline-p
 If value is nil, a doc string is always truncated to fit in a
 single line of display in the echo area.
 
-Any resizing of the echo area aditionally respects
+Any resizing of the echo area additionally respects
 `max-mini-window-height'."
   :type '(radio (const   :tag "Always" t)
                 (float   :tag "Fraction of frame height" 0.25)
@@ -426,12 +426,12 @@ eldoc-documentation-functions
 (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 a string containing the documentation's
-text and the remainder of DOC is an optional list of
-keyword-value pairs denoting additional properties of that
-documention.  For commonly recognized properties, see
+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 a string containing the
+documentation's text and the remainder of DOC is an optional list
+of keyword-value pairs denoting additional properties of that
+documentation.  For commonly recognized properties, see
 `eldoc-documentation-functions'.
 
 INTERACTIVE says if the request to display doc strings came
@@ -442,9 +442,9 @@ eldoc--doc-buffer
 (defvar eldoc--doc-buffer-docs nil "Documentation items in `eldoc--doc-buffer'.")
 
 (defun eldoc-doc-buffer (&optional interactive)
-  (interactive (list t))
   "Display ElDoc documentation buffer.
 This holds the results of the last documentation request."
+  (interactive (list t))
   (unless (buffer-live-p eldoc--doc-buffer)
     (setq eldoc--doc-buffer (get-buffer-create "*eldoc*")))
   (when interactive

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





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-09  8:03                           ` martin rudalics
@ 2020-10-24 15:18                             ` João Távora
  2020-10-26 14:12                               ` João Távora
  2020-10-27  9:58                               ` martin rudalics
  0 siblings, 2 replies; 41+ messages in thread
From: João Távora @ 2020-10-24 15:18 UTC (permalink / raw)
  To: martin rudalics; +Cc: Yuan Fu, 43609

Hi martin,

Sorry for taking so long to reply.  I've been busy.

martin rudalics <rudalics@gmx.at> writes:

> Meanwhile, please provide the compatibility layer you earlier promised
> with
>
>   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).
>
> so we can close this bug.
>
> Ideally, this would render your earlier changes backward-compatible and
> make the obsoletion declaration for 'eldoc-documentation-function' clean
> and follow our usual practice.

As I explained, this is impossible. Let's recap:

* eldoc-documentation-function is a variable exposed by eldoc.el meant
  to be set, not called, by libraries.  Many libraries set it in a way
  that, when called without the proper context from within eldoc.el's
  internals, it doesn't make any sense.  Such libaries are long-standing
  such as SLIME, Elpy, etc, and have existed for a long time.  So,
  because your use case wasn't ever a valid use of that variable to
  begin with, I don't see the case for any backward-iccompatibility
  claim.

* As I said, it's possible to write a eldoc-get-me-the-string function
  (not a variable) with the semantics that you want.  This is what I
  meant by "if you insist".  By that I meant there would have to be good
  reason for it.  But is there?  The use case you gave me was cleanly
  solved by relying on eldoc-display-functions, a feature which I'll
  push very shortly to master.  So, while this _can_ be done, I don't
  think it's a priority, because there's no clear use case for it.

> The downside of this approach is obviously that we would have to keep
> the old definitions of 'elisp-eldoc-documentation-function' and its
> colleagues around for a while.  So if you think that removing these old
> definitions immediately is crucial for future development, please
> provide some substitute function and mention it in the doc-string of
> 'eldoc-documentation-function(s)'.

Let's say eldoc-get-me-the-string function is written: then there is no
need to bring back these definitions.  Your library calls
eldoc-get-me-the-string if it finds it (which it presumably will in
Emacs 28), and (brokenly) calls eldoc-documentation-function in other
Emacs versions.  In Emacs 28 your library will work OK will all
documentation producers and in Emacs <= 27 it will not, but it will work
with Elisp and C++ which appear to be your priorities.

But, again, is the previous exercise really needed?  I very much doubt
it. You asked, and I provided, a modificaiton of your library so that it
works in Emacs 28 _without_ this hypothetical eldoc-get-me-the-string.
I showed you that all that is needed is a new element in
eldoc-display-functions.  If you want to make that library (again,
brokenly) compatible to Emacs <= 27, you must merely check the version
and use the previous technique.  Surely you can make that happen
yourself, it's a simple "if" statement.

But a much better alternative, in my opinion, is to use the code I gave
you and create a robust package that works correctly in Emacs >= 26.3.
How?  You make use of the fact the latest ElDoc in master is now _also_
available in GNU ELPA and you install that..  This means that even in
Emacs 26.3 you can use your tooltip thing for Elisp and C++ and so would
other people, for those modes and many others.

As to the implementation of this solution, it's a simple case of adding
this line:

;; Package-Requires: ((emacs "26.3") (eldoc "1.xx.0"))

to the martin-tooltip.el file I gave you earlier, and then using the
package.el system to package it.  Alternatively, if you don't want to
make a package, just 'M-x package-install eldoc' in Emacs >= 26.3 should
bring in the latest eldoc.

xx is the version of eldoc that will contain the new
eldoc-display-functions development.

Best regards,
João






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-23  2:37           ` Yuan Fu
@ 2020-10-24 17:09             ` João Távora
  2020-10-31 13:07               ` Basil L. Contovounesios
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-24 17:09 UTC (permalink / raw)
  To: Yuan Fu; +Cc: 43609

Yuan Fu <casouri@gmail.com> writes:

> Hi Joao,

Hi Yuan, I've now pushed the branch with eldoc-display-functions to
master.  It is version 1.11.0 of the ElDoc library and should be in GNU
ELPA soon.

>
> If there are multiple display functions, how does Emacs decide which
> one to use?

It uses all of them after calculating the documentation that should be
displayed.  The default value of eldoc-display-functions has two
elements:

- eldoc-display-in-echo-area which displays the documentation in the echo
  area, as is usual in Emacs.

- eldoc-display-in-doc-buffer which puts the documentation in a dedicated
  buffer.  However it does not display that buffer, unless 'M-x eldoc'
  is being called interactively (which normally it isn't, but now you
  can do that).

> Do you have ideas now about what :thing should be?

I've improved the documentation (after applying your typos patch:
thanks!).  If should be clear from the docstring.  Tell me if it's not.
Anyway, you don't _have_ to provide :thing when writing new members for
eldoc-documentation-functions and you don't _have_ to interpret it when
writing members for eldoc-display-functions.

João





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-24 15:18                             ` João Távora
@ 2020-10-26 14:12                               ` João Távora
  2020-10-27  9:59                                 ` martin rudalics
  2020-10-27  9:58                               ` martin rudalics
  1 sibling, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-26 14:12 UTC (permalink / raw)
  To: martin rudalics; +Cc: Yuan Fu, 43609

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

Hi Martin,

On Sat, Oct 24, 2020 at 4:19 PM João Távora <joaotavora@gmail.com> wrote:

> xx is the version of eldoc that will contain the new
> eldoc-display-functions development.

1.11.0 is the version of the ElDoc library that contains the new
development.
It's been in GNU ELPA for a couple of days now.

Also, there's something else where I might have useful information
to add. When you were talking about the version of eldoc-tooltip.el
that I adapted to the new ElDoc:

> I have to use it in practice before I can tell whether it works.  Back
> then, it took me some time to make the code do what I meant - put the
> tooltip in the right place of the window, move away the mouse cursor if
> necessary ...

As far as I know, I didn't change any of this tooltip behaviour.
All I changed is the when and with what information the tooltip is
displayed to the user.  So there's a relatively low chance of
those characteristics having been affected severely.

João

[-- Attachment #2: Type: text/html, Size: 1338 bytes --]

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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-24 15:18                             ` João Távora
  2020-10-26 14:12                               ` João Távora
@ 2020-10-27  9:58                               ` martin rudalics
  2020-10-27 15:11                                 ` João Távora
  1 sibling, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-27  9:58 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

 > * eldoc-documentation-function is a variable exposed by eldoc.el meant
 >    to be set, not called, by libraries.  Many libraries set it in a way
 >    that, when called without the proper context from within eldoc.el's
 >    internals, it doesn't make any sense.  Such libaries are long-standing
 >    such as SLIME, Elpy, etc, and have existed for a long time.  So,
 >    because your use case wasn't ever a valid use of that variable to
 >    begin with, I don't see the case for any backward-iccompatibility
 >    claim.
 >
 > * As I said, it's possible to write a eldoc-get-me-the-string function
 >    (not a variable) with the semantics that you want.  This is what I
 >    meant by "if you insist".  By that I meant there would have to be good
 >    reason for it.  But is there?  The use case you gave me was cleanly
 >    solved by relying on eldoc-display-functions, a feature which I'll
 >    push very shortly to master.  So, while this _can_ be done, I don't
 >    think it's a priority, because there's no clear use case for it.

Let's disagree on the backward incompatibility issue.  As a rule, Emacs
changes have always tried to not alter the signatures of functions in a
way that makes previously written calls invalid but I'm not very eager
to argue about that.

For me the sad fact remains that I will now have to change all these
calls on my 50-some Winchester and USB partitions where I have Emacs
installed, whenever I plug in or reactivate any of them and the
respective error message pops up rendering the actual session invalid.

Something you could have avoided by keeping a clean separation of the
old behavior of 'eldoc-documentation-function' on the one side and the
new behavior of 'eldoc-documentation-functions' on the other.  Please
everybody keep in mind for future changes to avoid introducing such
incompatible behavior.  If there is a function definition and that
function is not clearly marked as internal (via the usual two slashes),
please keep the signature and the semantics intact so users can rely on
it behaving as intended until that function has been declared obsolete
for a sufficient long time.

 > Let's say eldoc-get-me-the-string function is written: then there is no
 > need to bring back these definitions.  Your library calls
 > eldoc-get-me-the-string if it finds it (which it presumably will in
 > Emacs 28), and (brokenly) calls eldoc-documentation-function in other
 > Emacs versions.  In Emacs 28 your library will work OK will all
 > documentation producers and in Emacs <= 27 it will not, but it will work
 > with Elisp and C++ which appear to be your priorities.

I still have to make the change in all copies of my library I intend to
run.  While this may look like a minor issue to you, it would make Emacs
in the long term unusable for me, if such changes were introduced on a
regular basis.

 > But, again, is the previous exercise really needed?  I very much doubt
 > it. You asked, and I provided, a modificaiton of your library so that it
 > works in Emacs 28 _without_ this hypothetical eldoc-get-me-the-string.
 > I showed you that all that is needed is a new element in
 > eldoc-display-functions.  If you want to make that library (again,
 > brokenly) compatible to Emacs <= 27, you must merely check the version
 > and use the previous technique.  Surely you can make that happen
 > yourself, it's a simple "if" statement.
 >
 > But a much better alternative, in my opinion, is to use the code I gave
 > you and create a robust package that works correctly in Emacs >= 26.3.
 > How?  You make use of the fact the latest ElDoc in master is now _also_
 > available in GNU ELPA

Since I don't use any package archives and do not require them, this is
not a practical option for me.

 > and you install that..  This means that even in
 > Emacs 26.3 you can use your tooltip thing for Elisp and C++ and so would
 > other people, for those modes and many others.
 >
 > As to the implementation of this solution, it's a simple case of adding
 > this line:
 >
 > ;; Package-Requires: ((emacs "26.3") (eldoc "1.xx.0"))
 >
 > to the martin-tooltip.el file I gave you earlier, and then using the
 > package.el system to package it.  Alternatively, if you don't want to
 > make a package, just 'M-x package-install eldoc' in Emacs >= 26.3 should
 > bring in the latest eldoc.
 >
 > xx is the version of eldoc that will contain the new
 > eldoc-display-functions development.

Thanks, martin





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-26 14:12                               ` João Távora
@ 2020-10-27  9:59                                 ` martin rudalics
  0 siblings, 0 replies; 41+ messages in thread
From: martin rudalics @ 2020-10-27  9:59 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

 >> I have to use it in practice before I can tell whether it works.  Back
 >> then, it took me some time to make the code do what I meant - put the
 >> tooltip in the right place of the window, move away the mouse cursor if
 >> necessary ...
 >
 > As far as I know, I didn't change any of this tooltip behaviour.
 > All I changed is the when and with what information the tooltip is
 > displayed to the user.  So there's a relatively low chance of
 > those characteristics having been affected severely.

Both, the "when" and the "what" may affect the underlying behavior in
various ways.  I use eldoc tooltips for quite some time now but only in
the restricted environment of my private editing.  Many external changes
have never interested me.

For example, I recently noticed that the tab bar line introduced last
year can affect the positioning of the tooltip and I still have not
found out whether the problem is in 'pos-visible-in-window-p' or in my
code.  So before I can put that code into eldoc.el, I may also have to
resolve problems not or only tangentially related to your changes.

martin





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-27  9:58                               ` martin rudalics
@ 2020-10-27 15:11                                 ` João Távora
  2020-10-27 18:05                                   ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-27 15:11 UTC (permalink / raw)
  To: martin rudalics; +Cc: Yuan Fu, 43609

> Let's disagree on the backward incompatibility issue.  As a rule, Emacs
> changes have always tried to not alter the signatures of functions in a
> way that makes previously written calls invalid but I'm not very eager
> to argue about that.

I don't think this is a detail we can paper over, it's quite central of
what happened to you. eldoc-documentation-function has a name that ends
in "function", but it is _not_ a function.  It is a variable.  The fact
is that you were are funcalling _a variable_, not a _function_.  The
instructions in the docstring for that variable teach you, as they have
always, how to create values to assign to that variable.

There are very many variable variables in Emacs core alone ending in
"function" (just M-x apropos-variable for them).  They are called by the
libraries that define them, in potentially special contexts (say, with
special variables or unwind-protect around them).  If you create code
that funcalls the values without reconstructing these conditions
perfectly (a futile exercise IMO) you run the same risks of breakage
that you run when relying on implementation details.

Also, even before my changes, there was a better way to do what you
wanted (and there still is, afaik), which was (is) to hook onto
eldoc-message-function (Yuan Fu's code does this, though it doesn't use
a tooltip, it uses a so-called "child-frame").

Now, after my changes, your options to do your library correctly have
only increased.

> For me the sad fact remains that I will now have to change all these
> calls on my 50-some Winchester and USB partitions where I have Emacs
> installed, whenever I plug in or reactivate any of them and the
> respective error message pops up rendering the actual session invalid.

I'd like to help you, but I don't understand: are you updating Emacs to
master in all 50 of those drives?  Do you do this 50 times?  By hand?
Why can't you update your eldoc-tooltip.el in the process?

> Something you could have avoided by keeping a clean separation of the
> old behavior of 'eldoc-documentation-function' on the one side and the
> new behavior of 'eldoc-documentation-functions' on the other.

I don't understand how this can work: it's essential that ElDoc calls
eldoc-documentation-functions _through_ eldoc-documentation-function:
that's the only way it can deal with both old-style libraries that set
the latter and new-style library that set the former.  That's the key to
backward compatibility, and it's working correctly for many old and new
packages.  Furthermore, this link between the two variables _precedes_
my code (see SHA c0fcbd2c119b8418855f0931aceefbef717c5e53): I just added
the async support.

> Please everybody keep in minnd for future changes to avoid introducing
> such incompatible behavior.  If there is a function definition and
> that function is not clearly marked as internal (via the usual two
> slashes), please keep the signature and the semantics intact so users
> can rely on it behaving as intended until that function has been
> declared obsolete for a sufficient long time.

If "function definitions" were at stake, I would certainly agree with
you.  But they're not.  This is a _variable_ definition, that the
library gives users to exert control by assigning to it, _not_
funcalling it.  The semantics pertain to what values users are allowed
to assign to it.  Those semantics have been kept intact.  When libraries
mean for users to _call_ something, they expose functions, not
variables.

> I still have to make the change in all copies of my library I intend to
> run.  While this may look like a minor issue to you, it would make Emacs
> in the long term unusable for me, if such changes were introduced on a
> regular basis.

I have no idea if it's minor or major: I don't mean to belittle your
troubles, I'm trying to help you.  But I also don't understand this. As
I recall I've given you two modified version of your library:

- The one uses a martin() function and makes it work with all Emacsen
  but disregards asynchronous backends.  It seems to be enough for your
  use case anyway.
 
- The other uses the new protocol properly, removed much of your ElDoc
  reinvention, and works with the latest Emacs.  If you find a way to
  load the latest eldoc.el, it works with Emacs >= 26.3

If you are going to update Emacs to master in N servers, you might as
well update your library in those N servers. If you're updating it by
hand, then this doesn't seem like a tremendous extra effort to expend.
If you're using a script, just put the library update in that script.  I
personally use Git to good effect for this: push once, pull many times.

Alternatively, and perhaps even better, you're invited to contribute
your library to Emacs (or GNU ELPA).  Then you'll just have to update
Emacs, using your preferred method.

>> But a much better alternative, in my opinion, is to use the code I gave
>> you and create a robust package that works correctly in Emacs >= 26.3.
>> How?  You make use of the fact the latest ElDoc in master is now _also_
>> available in GNU ELPA
> Since I don't use any package archives and do not require them, this is
> not a practical option for me.

If you don't like packages, then just arrange some way for the latest
eldoc.el to be loaded along with martin-tooltip.el.  Eldoc.el has no
other dependencies other than Emacs 26.3.

João





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-27 15:11                                 ` João Távora
@ 2020-10-27 18:05                                   ` martin rudalics
  2020-10-27 19:56                                     ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-27 18:05 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

 > I'd like to help you, but I don't understand: are you updating Emacs to
 > master in all 50 of those drives?  Do you do this 50 times?  By hand?
 > Why can't you update your eldoc-tooltip.el in the process?

Every year I experience around two or three crashes among my machines
which run various operating systems ranging from Windows XP to Windows
10 and old stable to unstable Debian.  When a HD drive crashes, I try
to recreate the prior state by plugging in an older disk or copy the
contents of that older disk into a new one.  Thereafter, I usually
update my Emacs repositories reusing my older libraries.  If I also have
to update my libraries, I'm ending up in Augean stables.

 > I don't understand how this can work: it's essential that ElDoc calls
 > eldoc-documentation-functions _through_ eldoc-documentation-function:
 > that's the only way it can deal with both old-style libraries that set
 > the latter and new-style library that set the former.  That's the key to
 > backward compatibility, and it's working correctly for many old and new
 > packages.  Furthermore, this link between the two variables _precedes_
 > my code (see SHA c0fcbd2c119b8418855f0931aceefbef717c5e53): I just added
 > the async support.

Then I fail to understand why my old code stopped working after your
changes.  On the version of master I'm currently using here it's even
documented in the Elisp manual as

‘eldoc-documentation-function’
      This variable holds the function which is used to retrieve
      documentation for the item at point from the functions in the hook
      ‘eldoc-documentation-functions’.  By default,
      ‘eldoc-documentation-function’ returns the first documentation
      string produced by the ‘eldoc-documentation-functions’ hook.

 > If "function definitions" were at stake, I would certainly agree with
 > you.  But they're not.

Here 'elisp-eldoc-documentation-function' is a function defined in
elisp-mode.el.  IIUC this function has gone now.

 > If you are going to update Emacs to master in N servers, you might as
 > well update your library in those N servers. If you're updating it by
 > hand, then this doesn't seem like a tremendous extra effort to expend.
 > If you're using a script, just put the library update in that script.  I
 > personally use Git to good effect for this: push once, pull many times.

This is not something I do once to be done for ever.  It's something
that I usually have to do in a troublesome situation where I have to
recover from a previous crash and I'm trying to make some system run
again.  I can't afford to plug in all sorts of hard disk drives in order
to make them future-proof.

 > Alternatively, and perhaps even better, you're invited to contribute
 > your library to Emacs (or GNU ELPA).  Then you'll just have to update
 > Emacs, using your preferred method.

I'd still have to update each of my .emacs and install the respective
calls for each version of Emacs I might use there.

martin






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-27 18:05                                   ` martin rudalics
@ 2020-10-27 19:56                                     ` João Távora
  2020-10-28  8:39                                       ` martin rudalics
  2020-10-28  9:17                                       ` Lars Ingebrigtsen
  0 siblings, 2 replies; 41+ messages in thread
From: João Távora @ 2020-10-27 19:56 UTC (permalink / raw)
  To: martin rudalics; +Cc: larsi, Yuan Fu, 43609

[Lars, I'm CC'ing you specifcally since there's a patch to review at the
end.]

martin rudalics <rudalics@gmx.at> writes:

>> I'd like to help you, but I don't understand: are you updating Emacs to
>> master in all 50 of those drives?  Do you do this 50 times?  By hand?
>> Why can't you update your eldoc-tooltip.el in the process?
>
> Every year I experience around two or three crashes among my machines
> which run various operating systems ranging from Windows XP to Windows
> 10 and old stable to unstable Debian.  When a HD drive crashes, I try
> to recreate the prior state by plugging in an older disk or copy the
> contents of that older disk into a new one.  Thereafter, I usually
> update my Emacs repositories reusing my older libraries.  If I also have
> to update my libraries, I'm ending up in Augean stables.

I'm not sure I follow 100%, I'm just thinking that whatever process you
use to update Emacs in those machines you can also use to update
eldoc-tooltip.el.

> Then I fail to understand why my old code stopped working after your
> changes.  On the version of master I'm currently using here it's even
> documented in the Elisp manual as
>
> ‘eldoc-documentation-function’
>      This variable holds the function which is used to retrieve
>      documentation for the item at point from the functions in the hook
>      ‘eldoc-documentation-functions’.  By default,
>      ‘eldoc-documentation-function’ returns the first documentation
>      string produced by the ‘eldoc-documentation-functions’ hook.

And these things are true, still today, as far as I know. What I meant
is that the link between eldoc-documentation-function and
eldoc-documentation-functions was already established.  You were arguing
for some conceptual separation between these two variables and I noted
that they were already interconnected.

>> If "function definitions" were at stake, I would certainly agree with
>> you.  But they're not.
>
> Here 'elisp-eldoc-documentation-function' is a function defined in
> elisp-mode.el.  IIUC this function has gone now.

Ah right, then I misunderstood: you're talking about _that_ function.
That is indeed a function.  I thought you were talking about
eldoc-documentation-function, the variable, since that seems~ to have
been the original problem.  But what you're requesting seems to be the
functionally the martin() function I gave you earlier, right?

   (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."
   ...)

So you'd like it to be called elisp-eldoc-documentation-function, and
put in elisp-mode.el, right?  That _could_ be done, I guess, and I've
attached a patch at the end of this message.

But there's still something I don't understand: in your original
martin-tooltip.el library you didn't call this e-e-d-f function, did
you?  AFAIU, you did:

   (funcall eldoc-documentation-function)

or am I mistaken?  So you'd have to change your code anyway to now call
elisp-eldoc-documentation-function, right?  So, if you're going to
change it, why not change it to the new, better alternatives I have
presented?

Regardless, here's my take on '--': The presence of '--' clearly
specifies something to be an internal implementation detail. But that's
not the same as taking the absence of '--' as a sign that something is
an "external" function.  The '--' convention is relatively recent, and
programmers had been using internal details before the convention
existed.  This was one of them.

>> If you are going to update Emacs to master in N servers, you might as
>> well update your library in those N servers. If you're updating it by
>> hand, then this doesn't seem like a tremendous extra effort to expend.
>> If you're using a script, just put the library update in that script.  I
>> personally use Git to good effect for this: push once, pull many times.
>
> This is not something I do once to be done for ever.  It's something
> that I usually have to do in a troublesome situation where I have to
> recover from a previous crash and I'm trying to make some system run
> again.  I can't afford to plug in all sorts of hard disk drives in order
> to make them future-proof.

But isn't the problem that you've somehow built or placed a new version
of Emacs in those drives/servers/hosts where an incompatible
martin-tooltip.el lives?  I just don't understand why updating an Emacs
executable is somehow feasible in that setup but updating an Elisp
library that it depends on isn't.

>> Alternatively, and perhaps even better, you're invited to contribute
>> your library to Emacs (or GNU ELPA).  Then you'll just have to update
>> Emacs, using your preferred method.
>
> I'd still have to update each of my .emacs and install the respective
> calls for each version of Emacs I might use there.

I'm again confused: If you contribute your code to Emacs, then whenever
you update Emacs (which seems to be what you're concerned about) the
facilities you need will just be there.

João

As promised, a patch for you to review (and maybe Lars as well?)

diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index eed73f5791..f133635ec1 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1411,6 +1411,30 @@ elisp--eldoc-last-data
       or argument string for functions.
   2 - `function' if function args, `variable' if variable documentation.")
 
+(defun elisp--documentation-one-liner ()
+  (let* (str
+         (callback (lambda (doc &rest plist)
+                     (setq str
+                           (format "%s: %s"
+                                   (propertize (prin1-to-string
+                                                (plist-get plist :thing))
+                                               'face (plist-get plist :face))
+                                   doc)))))
+    (or (progn (elisp-eldoc-var-docstring callback) str)
+        (progn (elisp-eldoc-funcall callback) str))))
+
+(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner
+  "Return Elisp documentation for the thing at point as one-line string.
+This is meant as a backward compatibility aid to the \"old\"
+Elisp eldoc behaviour.  Consider variable docstrings and function
+signatures only, in this order.  If none applies, returns nil.
+Changes to `eldoc-documentation-functions' and
+`eldoc-documentation-strategy' are _not_ reflected here.  As such
+it is preferrable to use ElDoc's interfaces directly.")
+
+(make-obsolete 'elisp-eldoc-documentation-function
+               "use ElDoc's interfaces instead." "28.1")
+
 (defun elisp-eldoc-funcall (callback &rest _ignored)
   "Document function call at point.
 Intended for `eldoc-documentation-functions' (which see)."






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-27 19:56                                     ` João Távora
@ 2020-10-28  8:39                                       ` martin rudalics
  2020-10-28  9:38                                         ` João Távora
  2020-10-28  9:17                                       ` Lars Ingebrigtsen
  1 sibling, 1 reply; 41+ messages in thread
From: martin rudalics @ 2020-10-28  8:39 UTC (permalink / raw)
  To: João Távora; +Cc: larsi, Yuan Fu, 43609

 > I'm not sure I follow 100%, I'm just thinking that whatever process you
 > use to update Emacs in those machines

It's git pull nowadays and used to be some cvs or bzr command in the old
days.

 > you can also use to update
 > eldoc-tooltip.el.

You're right that I probably should write some sort of script but the
process is highly individual depending on the state of the machine that
crashed, the state of the disk I'm recovering from and the state of the
machine I'm moving too.  Restoring a crashed XP partition, for example,
is a pain these days since I cannot connect to XP from newer Debians via
the network.

 >> ‘eldoc-documentation-function’
 >>       This variable holds the function which is used to retrieve
 >>       documentation for the item at point from the functions in the hook
 >>       ‘eldoc-documentation-functions’.  By default,
 >>       ‘eldoc-documentation-function’ returns the first documentation
 >>       string produced by the ‘eldoc-documentation-functions’ hook.
 >
 > And these things are true, still today, as far as I know. What I meant
 > is that the link between eldoc-documentation-function and
 > eldoc-documentation-functions was already established.  You were arguing
 > for some conceptual separation between these two variables and I noted
 > that they were already interconnected.

But how can I get that default mentioned in "By default,
‘eldoc-documentation-function’ returns the first documentation string
produced by the ‘eldoc-documentation-functions’ hook."?

 > But there's still something I don't understand: in your original
 > martin-tooltip.el library you didn't call this e-e-d-f function, did
 > you?  AFAIU, you did:
 >
 >     (funcall eldoc-documentation-function)
 >
 > or am I mistaken?

You're not mistaken.  My expectation was and would be that in elisp mode
'eldoc-documentation-function' returned the value produced by
'elisp-eldoc-documentation-function' and IIUC that can't be done any
more because it would break you compatibility code for that variable.

 > So you'd have to change your code anyway to now call
 > elisp-eldoc-documentation-function, right?  So, if you're going to
 > change it, why not change it to the new, better alternatives I have
 > presented?

Because at the time I'm there I have other concerns than remember how I
did that.

 > Regardless, here's my take on '--': The presence of '--' clearly
 > specifies something to be an internal implementation detail. But that's
 > not the same as taking the absence of '--' as a sign that something is
 > an "external" function.  The '--' convention is relatively recent, and
 > programmers had been using internal details before the convention
 > existed.  This was one of them.

The absence of "--" is a sign that neither semantics nor signature of
that function, primitive, variable or macro should ever change unless
explicitly marked as obsoleted (for some time) or as an incompatible
change (which inherently means that there was some force majeure that
caused us to do that).

For example, in the fix of Bug#44080 Clemens preserved the old behavior
of 'fit-frame-to-buffer' and provided the now desired behavior by
introducing a new function 'fit-frame-to-buffer-1' that now becomes the
default value called by 'resize-mini-frames'.  While this is clumsy and
changes the default behavior of Emacs by calling another function when
the size of the minibuffer changes, it both (1) guarantees that
'fit-frame-to-buffer' behaves right as before and (2) allows to get the
previous, now undesired, behavior triggered by minibuffer size changes
by customizing 'resize-mini-frames' to 'fit-frame-to-buffer'.

With your changes, I cannot simply customize a variable to get the old
behavior back.  I have to do some extra coding somewhere.

 > But isn't the problem that you've somehow built or placed a new version
 > of Emacs in those drives/servers/hosts where an incompatible
 > martin-tooltip.el lives?  I just don't understand why updating an Emacs
 > executable is somehow feasible in that setup but updating an Elisp
 > library that it depends on isn't.

Because I expect Emacs to be backward-compatible (.elc included).

 > I'm again confused: If you contribute your code to Emacs, then whenever
 > you update Emacs (which seems to be what you're concerned about) the
 > facilities you need will just be there.

But my .emacs won't know.

 > As promised, a patch for you to review (and maybe Lars as well?)

Thank you.  If it also provided an option so the only thing I'd have to
do is to customize that, things would become for me as simple as the
present situation permits, I think.

martin






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-27 19:56                                     ` João Távora
  2020-10-28  8:39                                       ` martin rudalics
@ 2020-10-28  9:17                                       ` Lars Ingebrigtsen
  2020-10-28  9:54                                         ` João Távora
  1 sibling, 1 reply; 41+ messages in thread
From: Lars Ingebrigtsen @ 2020-10-28  9:17 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

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

> [Lars, I'm CC'ing you specifcally since there's a patch to review at the
> end.]

I don't really know much about eldoc, so I don't have much to say here...

[...]

> +(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner

[...]

> +(make-obsolete 'elisp-eldoc-documentation-function
> +               "use ElDoc's interfaces instead." "28.1")
> +

But this seems like the correct approach -- we should never remove
non-internal functions without going through the obsoletion process.
(And "--" functions are the only ones that are clearly marked as
internal; for internalish functions prior to that convention we have to
do this for all of them, whether we consider them internal or not.)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-28  8:39                                       ` martin rudalics
@ 2020-10-28  9:38                                         ` João Távora
  2020-10-31  8:01                                           ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-28  9:38 UTC (permalink / raw)
  To: martin rudalics; +Cc: larsi, Yuan Fu, 43609

martin rudalics <rudalics@gmx.at> writes:

> But how can I get that default mentioned in "By default,
> ‘eldoc-documentation-function’ returns the first documentation string
> produced by the ‘eldoc-documentation-functions’ hook."?

It's still the default.  But I see your confusion.  Instead of:

   "returns the first documentation string produced ..."

It should say:

   "computes the first documentation string produced"

Or even:

   "arranges for the first documentation string produced ... to be
   displayed to the user"

These things are, of course, equivalent from the POV of the user as long
as you're not calling eldoc-documentation-function, the variable.

This is also shows what async does: If doc string are to be produced
asynchronously, then by definition eldoc-documentation-function cannot
return it as a Lisp return value.

>> But there's still something I don't understand: in your original
>> martin-tooltip.el library you didn't call this e-e-d-f function, did
>> you?  AFAIU, you did:
>>
>>     (funcall eldoc-documentation-function)
>>
>> or am I mistaken?
>
> You're not mistaken.  My expectation was and would be that in elisp mode
> 'eldoc-documentation-function' returned the value produced by
> 'elisp-eldoc-documentation-function' and IIUC that can't be done any
> more because it would break you compatibility code for that variable.

Yes but now _you're_ mistaken.  You _can_ still set `e-d-f` to `e-e-d-f`
and that still works.  But the default in Elisp mode is to make use of
`e-d-f`'s (also known as eldoc-documentation-strategy) superior
capabilities that allow it to report more than one type of doc per
symbol, for example.

>> So you'd have to change your code anyway to now call
>> elisp-eldoc-documentation-function, right?  So, if you're going to
>> change it, why not change it to the new, better alternatives I have
>> presented?
>
> Because at the time I'm there I have other concerns than remember how I
> did that.

I didn't follow this at all, but it seems highly personal and related to
how your mental memory works, so I'm not going to insist.  I just think
a code change is a code change and I've given you the code.

> With your changes, I cannot simply customize a variable to get the old
> behavior back.  I have to do some extra coding somewhere.

I'd say customize a variable and do some extra (trivial) coding are
comparable in effort, especially when someone else is handing you that
code.

>> of Emacs in those drives/servers/hosts where an incompatible
>> martin-tooltip.el lives?  I just don't understand why updating an Emacs
>> executable is somehow feasible in that setup but updating an Elisp
>> library that it depends on isn't.
> Because I expect Emacs to be backward-compatible (.elc included).

We've gone through that, and I've noted that your library was calling a
variable (not a functino) meant to be called by a library.  That's
relying on an implementation detail, and Emacs's implementation changes
over time.

>> I'm again confused: If you contribute your code to Emacs, then whenever
>> you update Emacs (which seems to be what you're concerned about) the
>> facilities you need will just be there.
>
> But my .emacs won't know.

But your .emacs has to know about "custom-set-variables" too right?  Why
are you OK with that?

>> As promised, a patch for you to review (and maybe Lars as well?)
>
> Thank you.  If it also provided an option so the only thing I'd have to
> do is to customize that, things would become for me as simple as the
> present situation permits, I think.

You can:

 (add-hook 'emacs-lisp-mode-hook
           (lambda () (setq-local eldoc-documentation-function
                                  'elisp-eldoc-documentation-function)))

Somewhere in your .emacs.  Or in your martin-tooltip.el library.

Frankly, I think a customization variable for this type of obsoleted
behaviour is too much.  I get that deleting
elisp-eldoc-documentation-function was getting rid of a non '--'
function that, even though:

- it's quite questionable that third parties should be relying on it,
- noone in the core Emacs relied upon it,
- and noone in GNU Elpa relied upon it,
- and not even your private martin-tooltip.el code relied upon it,

So we bring that e-e-d-f back, OK seems it _could_ help you make the
adaptation of martin-tooltip.el, even though I've given you already
multiple better adaptations of that same file that you reject for some
reason that I can't comprehend.

But changing the _value_ of eldoc-documentation-function (the variable)
was _not_ a backward incompatible change (I've explained at length why,
I think).  So a confusing user option here to save you those three lines
of trivial code seems too much.

João






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-28  9:17                                       ` Lars Ingebrigtsen
@ 2020-10-28  9:54                                         ` João Távora
  2020-10-30 22:51                                           ` João Távora
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-28  9:54 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Yuan Fu, 43609

Lars Ingebrigtsen <larsi@gnus.org> writes:

> João Távora <joaotavora@gmail.com> writes:
>
>> [Lars, I'm CC'ing you specifcally since there's a patch to review at the
>> end.]
>
> I don't really know much about eldoc, so I don't have much to say here...
>
> [...]
>
>> +(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner
>
> [...]
>
>> +(make-obsolete 'elisp-eldoc-documentation-function
>> +               "use ElDoc's interfaces instead." "28.1")
>> +
>
> But this seems like the correct approach -- we should never remove
> non-internal functions without going through the obsoletion process.
> (And "--" functions are the only ones that are clearly marked as
> internal; for internalish functions prior to that convention we have to
> do this for all of them, whether we consider them internal or not.)

OK, I'm pushing that.

João





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-28  9:54                                         ` João Távora
@ 2020-10-30 22:51                                           ` João Távora
  2020-10-31  8:02                                             ` martin rudalics
  0 siblings, 1 reply; 41+ messages in thread
From: João Távora @ 2020-10-30 22:51 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Yuan Fu, 43609-done

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

> Lars Ingebrigtsen <larsi@gnus.org> writes:
>
>> João Távora <joaotavora@gmail.com> writes:
>>
>>> [Lars, I'm CC'ing you specifcally since there's a patch to review at the
>>> end.]
>>
>> I don't really know much about eldoc, so I don't have much to say here...
>>
>> [...]
>>
>>> +(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner
>>
>> [...]
>>
>>> +(make-obsolete 'elisp-eldoc-documentation-function
>>> +               "use ElDoc's interfaces instead." "28.1")
>>> +
>>
>> But this seems like the correct approach -- we should never remove
>> non-internal functions without going through the obsoletion process.
>> (And "--" functions are the only ones that are clearly marked as
>> internal; for internalish functions prior to that convention we have to
>> do this for all of them, whether we consider them internal or not.)
>
> OK, I'm pushing that.

I just did this.  elisp-eldoc-documentation-function is now in master
again.  Martin, from what I understand of this bug, fixing your problem
is now this short snippet away in your .emacs or in your
martin-tooltip.el library:

   (add-hook 'emacs-lisp-mode-hook
      (lambda () (setq-local eldoc-documentation-function
                             #'elisp-eldoc-documentation-function)))

The byte-compiler should warn you that
elisp-eldoc-documentation-function is obsoleted, but that's fine.

I'm also closing this bug, I will of course re-open if you don't agree.

João







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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-28  9:38                                         ` João Távora
@ 2020-10-31  8:01                                           ` martin rudalics
  0 siblings, 0 replies; 41+ messages in thread
From: martin rudalics @ 2020-10-31  8:01 UTC (permalink / raw)
  To: João Távora; +Cc: larsi, Yuan Fu, 43609

 > But changing the _value_ of eldoc-documentation-function (the variable)
 > was _not_ a backward incompatible change

And I disagree.

(1) Fifteen years ago we had

(defvar eldoc-documentation-function nil
   "If non-nil, 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.

This variable is expected to be made buffer-local by modes (other than
Emacs Lisp mode) that support Eldoc.")

(2) Five years ago, that is, at the time I wrote 'eldoc-tooltip-mode' we
had

(defvar eldoc-documentation-function #'ignore
   "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.

Major modes should modify this variable using `add-function', for example:
   (add-function :before-until (local 'eldoc-documentation-function)
                 #'foo-mode-eldoc-function)
so that the global documentation function (i.e. the default value of the
variable) is taken into account if the major mode specific function does not
return any documentation.")

(3) With

commit c0fcbd2c119b8418855f0931aceefbef717c5e53
Author: Mark Oteiza <mvoteiza@udel.edu>
Date:   Tue Feb 25 17:53:04 2020 -0500

     Expose ElDoc functions in a hook (Bug#28257)

the definition became

(defcustom eldoc-documentation-function #'eldoc-documentation-default
   "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."

(4) With current master 'eldoc-documentation-function' is not defined
any more but has become an alias in a way I can't fathom.  C-h v gets
me:

eldoc-documentation-function is a variable defined in ‘eldoc.el’.
Its value is ‘eldoc-documentation-default’

   This variable is an alias for ‘eldoc-documentation-strategy’.
   You can customize this variable.
   Probably introduced at or before Emacs version 22.1.

Documentation:
How to collect and organize results of ‘eldoc-documentation-functions’.

This variable controls how ‘eldoc-documentation-functions’, which
specifies the sources of documentation, is queried and how its
results are organized before being displayed to the user.  The
following values are allowed:

- ‘eldoc-documentation-default’: calls functions in the special
   hook in order until one is found that produces a doc string
   value.  Display only that value;

- ‘eldoc-documentation-compose’: calls all functions in the
   special hook and displays all of the resulting doc strings
   together.  Wait for all strings to be ready, and preserve their
   relative as specified by the order of functions in the hook;

- ‘eldoc-documentation-compose-eagerly’: calls all functions in
   the special hook and display as many of the resulting doc
   strings as possible, as soon as possibl.  Preserving the
   relative order of doc strings;

- ‘eldoc-documentation-enthusiast’: calls all functions in the
   special hook and displays only the most important resulting
   docstring one at any given time.  A function appearing first in
   the special hook is considered more important.

This variable can also be set to a function of no args that
returns something other than a string or nil and allows for some
or all of the special hook ‘eldoc-documentation-functions’ to be
run.  In that case, the strategy function should follow that
other variable’s protocol closely and endeavor to display the
resulting doc strings itself.

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.

Note here the "can also be set to a function of no args that returns
something other than a string or nil" and "For backward compatibility to
the \"old\" protocol, this variable can also be set to a function that
returns nil or a doc string": The former implies that returning a string
or nil is the expected behavior.  The latter implies that returning a
string or nil is the exception.

What makes (4) backward incompatible is that "should return a one-line
string" is no more mentioned in the doc-string.  Consequently, modes
defining their support functions do not have to support this part of the
original specification any more.  In the sequel changes were installed
that, for example, have the corresponding function in elisp-mode.el
return a value that no more obeys the doc-strings of (1), (2) and (3).

It's also possible that the incompatible change is a combination of (3)
and (4): (3) changed the implementation in a way that already violated
the semantics of 'eldoc-documentation-function' by silently accepting
return values that at the time (3) was installed were invalid according
to its doc-string.  (4) then sanctioned that violation by aliasing the
variable and amending the doc-string.

 > (I've explained at length why, I think)

So let's continue to disagree.

martin






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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-30 22:51                                           ` João Távora
@ 2020-10-31  8:02                                             ` martin rudalics
  0 siblings, 0 replies; 41+ messages in thread
From: martin rudalics @ 2020-10-31  8:02 UTC (permalink / raw)
  To: João Távora, Lars Ingebrigtsen; +Cc: Yuan Fu, 43609-done

 > elisp-eldoc-documentation-function is now in master
 > again.  Martin, from what I understand of this bug, fixing your problem
 > is now this short snippet away in your .emacs or in your
 > martin-tooltip.el library:
 >
 >     (add-hook 'emacs-lisp-mode-hook
 >        (lambda () (setq-local eldoc-documentation-function
 >                               #'elisp-eldoc-documentation-function)))
 >
 > The byte-compiler should warn you that
 > elisp-eldoc-documentation-function is obsoleted, but that's fine.

I'll try it out as soon as I'm pulling from master again.

 > I'm also closing this bug, I will of course re-open if you don't agree.

Fine.

Many thanks, martin





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

* bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions]
  2020-10-24 17:09             ` João Távora
@ 2020-10-31 13:07               ` Basil L. Contovounesios
  0 siblings, 0 replies; 41+ messages in thread
From: Basil L. Contovounesios @ 2020-10-31 13:07 UTC (permalink / raw)
  To: João Távora; +Cc: Yuan Fu, 43609

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

> Hi Yuan, I've now pushed the branch with eldoc-display-functions to
> master.  It is version 1.11.0 of the ElDoc library and should be in GNU
> ELPA soon.

Thanks.  Just one minor question: why does eldoc--format-doc-buffer have
an interactive spec?

-- 
Basil





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

end of thread, other threads:[~2020-10-31 13:07 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25  8:46 bug#43609: 28.0.50; eldoc-documentation-function martin rudalics
2020-09-26 18:34 ` Dmitry Gutov
2020-09-27  8:30   ` martin rudalics
2020-09-29 11:20     ` Dmitry Gutov
2020-09-29 15:09       ` martin rudalics
2020-09-29 15:23         ` Dmitry Gutov
2020-09-30  8:14           ` martin rudalics
2020-09-30  8:50             ` Dmitry Gutov
2020-09-30 14:37 ` João Távora
2020-09-30 17:33   ` martin rudalics
2020-09-30 18:22     ` João Távora
2020-10-01  8:40       ` martin rudalics
2020-10-01  9:23         ` João Távora
2020-10-03 19:15         ` bug#43609: 28.0.50; eldoc-documentation-function [vs new eldoc-display-functions] João Távora
2020-10-05  8:35           ` martin rudalics
2020-10-05  9:29             ` João Távora
2020-10-06  8:23               ` martin rudalics
2020-10-06  9:29                 ` João Távora
2020-10-07  8:36                   ` martin rudalics
2020-10-07  8:40                     ` João Távora
2020-10-07  9:36                     ` João Távora
2020-10-08  8:22                       ` martin rudalics
2020-10-08  8:27                         ` João Távora
2020-10-09  8:03                           ` martin rudalics
2020-10-24 15:18                             ` João Távora
2020-10-26 14:12                               ` João Távora
2020-10-27  9:59                                 ` martin rudalics
2020-10-27  9:58                               ` martin rudalics
2020-10-27 15:11                                 ` João Távora
2020-10-27 18:05                                   ` martin rudalics
2020-10-27 19:56                                     ` João Távora
2020-10-28  8:39                                       ` martin rudalics
2020-10-28  9:38                                         ` João Távora
2020-10-31  8:01                                           ` martin rudalics
2020-10-28  9:17                                       ` Lars Ingebrigtsen
2020-10-28  9:54                                         ` João Távora
2020-10-30 22:51                                           ` João Távora
2020-10-31  8:02                                             ` martin rudalics
2020-10-23  2:37           ` Yuan Fu
2020-10-24 17:09             ` João Távora
2020-10-31 13:07               ` Basil L. Contovounesios

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