From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Mark Oteiza Newsgroups: gmane.emacs.bugs Subject: bug#28257: 26.0.50; [PATCH] expose eldoc functions in a hook Date: Sun, 26 Jan 2020 18:47:31 -0500 Message-ID: <20200126234731.GA12794@holos.localdomain> References: <87ziakwifi.fsf@holos> <87val88l0d.fsf@users.sourceforge.net> <20170828031104.GA15524@holos.localdomain> <87shgb89q1.fsf@users.sourceforge.net> <20170830015017.GA28668@holos.localdomain> <87wohasikq.fsf@gmail.com> <20190626140303.quhh4psgvd3aneyr@logos.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="15216"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Lars Ingebrigtsen , 28257@debbugs.gnu.org, npostavs@users.sourceforge.net To: Noam Postavsky Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Jan 27 00:48:15 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ivrdW-0003uW-3N for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 27 Jan 2020 00:48:14 +0100 Original-Received: from localhost ([::1]:38448 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ivrdU-000687-TY for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 26 Jan 2020 18:48:12 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:42646) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ivrdM-00067x-A3 for bug-gnu-emacs@gnu.org; Sun, 26 Jan 2020 18:48:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ivrdK-00046V-4h for bug-gnu-emacs@gnu.org; Sun, 26 Jan 2020 18:48:04 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:51693) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ivrdJ-00044r-N8 for bug-gnu-emacs@gnu.org; Sun, 26 Jan 2020 18:48:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ivrdJ-00024J-Km for bug-gnu-emacs@gnu.org; Sun, 26 Jan 2020 18:48:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Mark Oteiza Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 26 Jan 2020 23:48:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28257 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 28257-submit@debbugs.gnu.org id=B28257.15800824617926 (code B ref 28257); Sun, 26 Jan 2020 23:48:01 +0000 Original-Received: (at 28257) by debbugs.gnu.org; 26 Jan 2020 23:47:41 +0000 Original-Received: from localhost ([127.0.0.1]:57666 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ivrcy-00023l-UE for submit@debbugs.gnu.org; Sun, 26 Jan 2020 18:47:41 -0500 Original-Received: from mail-qv1-f66.google.com ([209.85.219.66]:46223) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ivrcx-00023Z-E0 for 28257@debbugs.gnu.org; Sun, 26 Jan 2020 18:47:40 -0500 Original-Received: by mail-qv1-f66.google.com with SMTP id u1so3683625qvk.13 for <28257@debbugs.gnu.org>; Sun, 26 Jan 2020 15:47:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=udel-edu.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=LnfZ1pJLoraMnrC+BRen6PFtfXfqkt3tRgx+D46+FKQ=; b=HQ7gJZqykDo1iBITbbb2nlVWTlnRffd9CdnLdJmqf3pTTwTTWhsEUy7Rk/WmdFdP+n 0IyOg9TILPaJfmcBB9eK8yFSP/lXAXMMXHh1TldiLza1hj9XfUpKYLtf9pFg9d12MWgP QeN1W7iN2D0bd6VIj5u8CSbrOqok+cJPi+Gi8Mc+fBurnTmlWjpGPpRNBTmSy46X33Jx XXFpkG28kaMnXv6z6EykAnyi4eVvyZe44c12/oHpdgvQUHnLapxYWvi6lsAnUrKppE5w H6v3/w3k83Yz82jSGMJq9PEwmmBX4bRaSIm4ThFER1nKRS8pb0DL9ZIoxo2OmUBo9cgt 2zuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=LnfZ1pJLoraMnrC+BRen6PFtfXfqkt3tRgx+D46+FKQ=; b=TH1UBeAhC5iw2mrpZoeSLMGsCbj0ioIjmu8plwV9lorpZKx4L93O3UNLgZ/chdVxva P5Z0zfPwJo2SCEswwwx3PbVqXWf/267vZeO1FRCt3dbI4BqOMNTBOl/Yxag1L28yGy/V yGrp+9y5CNjnjUlNLibNTyl+6g+zNoeBOOjRKKJRRpMxM2uJKXPsiKePC1M8OmKhgOnz cqntditg71r1Mcg77domprIctZ6NKnv0S3TKTbooiTCDcrLdWCfG5BmjdeDJ2U8HFOf8 TzmG33JB2BAaV/3mDt7PnkwHvphRnLt1fVQqmmjg4PYst/Wg4BigfT7SGfF2/LTGmtl9 kdfA== X-Gm-Message-State: APjAAAWW/bQ1+RpqpvC8h21mMLikfzdNZXuDbRDADGShq1WlwRfAY1Hu jDvXt453K205ZNONOtJsET+HJg== X-Google-Smtp-Source: APXvYqxShbB2IGtQlqpXYHVrtMAqLAxOPaWMKPH5ZW7JojhxwdoAiYaoxzWTHWEsVO51g7rFMSNryA== X-Received: by 2002:a0c:f412:: with SMTP id h18mr14618737qvl.124.1580082453495; Sun, 26 Jan 2020 15:47:33 -0800 (PST) Original-Received: from holos.localdomain (c-69-251-143-253.hsd1.md.comcast.net. [69.251.143.253]) by smtp.gmail.com with ESMTPSA id f4sm8381143qka.89.2020.01.26.15.47.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Jan 2020 15:47:32 -0800 (PST) Content-Disposition: inline In-Reply-To: <20190626140303.quhh4psgvd3aneyr@logos.localdomain> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:175323 Archived-At: On 26/06/19 at 10:03am, Mark Oteiza wrote: > On 24/06/19 at 06:51pm, Noam Postavsky wrote: > > Lars Ingebrigtsen writes: > > > > > Mark Oteiza writes: > > > > > >>> Could be a worthwhile tradeoff (especially > > >>>since there currently aren't any individual mode eldoc functions using > > >>>anything apart from :before-until, afaik); I'm on the fence about this. > > >> > > >> Not in emacs, at least. In elpa, ggtags uses :after-until. The only > > >> 3rd party packages--that I can think of right now--that implement eldoc > > >> functions just use setq-local (elpy and geiser). > > > > > > Noam, still on the fence? > > > > I haven't really thought about this much, maybe bring it up on > > emacs-devel? > > I happily rolled with this patch until some changes to eldoc broke it. > Will post a new patch when I get around to it. New patch below. Lightly tested, at first sight it seems to work (setting eldoc-documentation-function to eldoc-documentation-compose) diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi index 683374c615..8e2a22b2ff 100644 --- a/doc/emacs/programs.texi +++ b/doc/emacs/programs.texi @@ -1269,9 +1269,27 @@ Lisp Doc for a function, it shows the argument list, and for a variable it shows the first line of the variable's documentation string. To toggle Eldoc mode, type @kbd{M-x eldoc-mode}. There's also a Global -Eldoc mode, which is turned on by default, and affects buffers, such -as @samp{*scratch*}, whose major mode is Emacs Lisp or Lisp -Interaction (@w{@kbd{M-x global-eldoc-mode}} to turn it off globally). +Eldoc mode, which is turned on by default, and affects buffers whose +major mode sets the variables described below. Use @w{@kbd{M-x +global-eldoc-mode}} to turn it off globally. + +@vindex eldoc-documentation-function +@vindex eldoc-documentation-functions + These variables can be used to configure ElDoc mode: + +@table @code +@item 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 +@code{eldoc-documentation-functions}. By default, +@code{eldoc-documentation-function} returns the first documentation +string produced by the @code{eldoc-documentation-functions} hook. + +@item eldoc-documentation-functions +This abnormal hook holds documentation functions. It acts as a +collection of backends for ElDoc. This is what modes should use to +register their documentation functions with ElDoc. +@end table @node Hideshow @section Hideshow minor mode diff --git a/etc/NEWS b/etc/NEWS index 276b8f46e8..8396afc277 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -103,6 +103,16 @@ To revert to the previous behaviour, unconditionally aborts the current edebug instrumentation with the supplied error message. ++++ +** ElDoc + +*** New hook 'eldoc-documentation-functions' to be used for registering +doc string functions. This makes the results of all doc string +functions accessible to the user through the existing single function hook +'eldoc-documentation-function'. + +*** 'eldoc-documentation-function' is now a custom variable. + ** Tramp +++ diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 7a7b8ec164..0a17e7e2ea 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -40,9 +40,9 @@ ;; (add-hook 'ielm-mode-hook 'eldoc-mode) ;; (add-hook 'eval-expression-minibuffer-setup-hook 'eldoc-mode) -;; Major modes for other languages may use ElDoc by defining an -;; appropriate function as the buffer-local value of -;; `eldoc-documentation-function'. +;; Major modes for other languages may use ElDoc by adding an +;; appropriate function to the buffer-local value of +;; `eldoc-documentation-functions'. ;;; Code: @@ -222,8 +222,8 @@ global-eldoc-mode (defun eldoc--eval-expression-setup () ;; Setup `eldoc', similar to `emacs-lisp-mode'. FIXME: Call ;; `emacs-lisp-mode' itself? - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (eldoc-mode +1)) ;;;###autoload @@ -235,7 +235,11 @@ turn-on-eldoc-mode (defun eldoc--supported-p () "Non-nil if an ElDoc function is set for this buffer." - (not (memq eldoc-documentation-function '(nil ignore)))) + (let ((hook 'eldoc-documentation-functions)) + (and eldoc-documentation-function + (or (and (local-variable-p hook) + (buffer-local-value hook (current-buffer))) + (default-value hook))))) (defun eldoc-schedule-timer () @@ -348,7 +352,47 @@ eldoc-display-message-no-interference-p ;;;###autoload -(defvar eldoc-documentation-function #'ignore +(defvar eldoc-documentation-functions nil + "Hook for functions to call to return doc string. +Each function should accept no arguments and 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. + +Major modes should modify this hook locally, for example: + (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t) +so that the global value (i.e. the default value of the hook) is +taken into account if the major mode specific function does not +return any documentation.") + +(defun eldoc-documentation-default () + "Show doc string for item at point. +Default value for `eldoc-documentation-function'." + (let ((res (run-hook-with-args-until-success 'eldoc-documentation-functions))) + (when res + (if eldoc-echo-area-use-multiline-p res + (truncate-string-to-width + res (1- (window-width (minibuffer-window)))))))) + +(defun eldoc-documentation-compose () + "Show multiple doc string results at once. +Meant as a value for `eldoc-documentation-function'." + (let (res) + (run-hook-wrapped + 'eldoc-documentation-functions + (lambda (f) + (let ((str (funcall f))) + (when str (push str res)) + nil))) + (when res + (setq res (mapconcat #'identity (nreverse res) ", ")) + (if eldoc-echo-area-use-multiline-p res + (truncate-string-to-width + res (1- (window-width (minibuffer-window)))))))) + +;;;###autoload +(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. @@ -359,14 +403,12 @@ eldoc-documentation-function 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.") +effect." + :link '(info-link "(emacs) Lisp Doc") + :type '(radio (function-item eldoc-documentation-default) + (function-item eldoc-documentation-compose) + (function :tag "Other function")) + :group 'eldoc) (defun eldoc-print-current-symbol-info () "Print the text produced by `eldoc-documentation-function'." @@ -381,7 +423,8 @@ eldoc-print-current-symbol-info ;; Only keep looking for the info as long as the user hasn't ;; requested our attention. This also locally disables inhibit-quit. (while-no-input - (eldoc-message (funcall eldoc-documentation-function))))))) + (let ((fun eldoc-documentation-function)) + (when fun (eldoc-message (funcall fun))))))))) ;; If the entire line cannot fit in the echo area, the symbol name may be ;; truncated or eliminated entirely from the output to make room for the diff --git a/lisp/hexl.el b/lisp/hexl.el index 58518e7416..cf7118f208 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -367,8 +367,8 @@ hexl-mode (add-hook 'change-major-mode-hook #'hexl-maybe-dehexlify-buffer nil t) ;; Set a callback function for eldoc. - (add-function :before-until (local 'eldoc-documentation-function) - #'hexl-print-current-point-info) + (add-hook 'eldoc-documentation-functions + #'hexl-print-current-point-info nil t) (eldoc-add-command-completions "hexl-") (eldoc-remove-command "hexl-save-buffer" "hexl-current-address") @@ -455,6 +455,8 @@ hexl-revert-buffer-function ;; 2. reset change-major-mode-hook in case that `hexl-mode' ;; previously added hexl-maybe-dehexlify-buffer to it. (remove-hook 'change-major-mode-hook #'hexl-maybe-dehexlify-buffer t) + (remove-hook 'eldoc-documentation-functions + #'hexl-print-current-point-info t) (setq major-mode 'fundamental-mode) (hexl-mode))) diff --git a/lisp/ielm.el b/lisp/ielm.el index 41675c011d..fc06ebfa2d 100644 --- a/lisp/ielm.el +++ b/lisp/ielm.el @@ -541,8 +541,8 @@ inferior-emacs-lisp-mode (set (make-local-variable 'completion-at-point-functions) '(comint-replace-by-expanded-history ielm-complete-filename elisp-completion-at-point)) - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (set (make-local-variable 'ielm-prompt-internal) ielm-prompt) (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only) (setq comint-get-old-input 'ielm-get-old-input) diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el index 9ddb2ab2bb..af02f5fea8 100644 --- a/lisp/progmodes/cfengine.el +++ b/lisp/progmodes/cfengine.el @@ -1390,12 +1390,15 @@ cfengine3-mode (when buffer-file-name (shell-quote-argument buffer-file-name))))) - ;; For emacs < 25.1 where `eldoc-documentation-function' defaults to - ;; nil. - (or eldoc-documentation-function - (setq-local eldoc-documentation-function #'ignore)) - (add-function :before-until (local 'eldoc-documentation-function) - #'cfengine3-documentation-function) + (if (> emacs-major-version 25) + (add-hook 'eldoc-documentation-functions + #'cfengine3-documentation-function nil t) + ;; For emacs < 25.1 where `eldoc-documentation-function' defaults + ;; to nil. + (or eldoc-documentation-function + (setq-local eldoc-documentation-function #'ignore)) + (add-function :before-until (local 'eldoc-documentation-function) + #'cfengine3-documentation-function)) (add-hook 'completion-at-point-functions #'cfengine3-completion-function nil t) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 2617a6e4cc..813b628bc3 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -250,8 +250,8 @@ emacs-lisp-mode (add-hook 'electric-pair-mode-hook #'emacs-lisp-set-electric-text-pairs)) (setq-local electric-quote-string t) (setq imenu-case-fold-search nil) - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (add-hook 'xref-backend-functions #'elisp--xref-backend nil t) (setq-local project-vc-external-roots-function #'elisp-load-path-roots) (add-hook 'completion-at-point-functions diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el index 9e03956254..352c1810d1 100644 --- a/lisp/progmodes/octave.el +++ b/lisp/progmodes/octave.el @@ -619,8 +619,7 @@ octave-mode (add-hook 'before-save-hook 'octave-sync-function-file-names nil t) (setq-local beginning-of-defun-function 'octave-beginning-of-defun) (and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment)) - (add-function :before-until (local 'eldoc-documentation-function) - 'octave-eldoc-function) + (add-hook 'eldoc-documentation-functions 'octave-eldoc-function nil t) (easy-menu-add octave-mode-menu)) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index a2d85d0bef..48401b1e54 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5544,8 +5544,10 @@ python-mode ;; Emacs<25 (set (make-local-variable 'eldoc-documentation-function) #'python-eldoc-function) - (add-function :before-until (local 'eldoc-documentation-function) - #'python-eldoc-function)) + (if (< emacs-major-version 26) + (add-function :before-until (local 'eldoc-documentation-function) + #'python-eldoc-function) + (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil t))) (add-to-list 'hs-special-modes-alist