all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Arthur Miller <arthur.miller@live.com>
To: Tassilo Horn <tsdh@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: Path & Demo: Source View in Help Buffers
Date: Wed, 22 Sep 2021 15:42:11 +0200	[thread overview]
Message-ID: <DB9PR09MB498669AD1D02349BD1C5CCC096A29@DB9PR09MB4986.eurprd09.prod.outlook.com> (raw)
In-Reply-To: <87k0j8j0v3.fsf@gnu.org> (Tassilo Horn's message of "Wed, 22 Sep 2021 13:32:57 +0200")

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

Tassilo Horn <tsdh@gnu.org> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
>>> Out of curiosity, why do you have fboundp-checks for font-lock-ensure
>>> in the code?  That's always true, isn't it?
>>
>> I don't know. Since font-lock has all its stuff abstracted into buffer
>> local function variables, I am not sure if I can count it is not nil?
>
> But it's no buffer-local variable, it's a function.  If you have emacs
> 25.1 upwards, you have `font-lock-ensure'.
>
>> If I can I would gladly remove the check. I appreciate advice, I am
>> not so familiar with all the details of everything.
>
> I think that's a common check for 3rd-party packages which want to keep
> supporting emacs 24.  But since you are hacking emacs core, there's no
> need for that unless the function/variable is only defined if some
> configure option is given or some lib is available.  But none of the
> latter applies to font-lock.el.
>

Yes, I have tested now, it works fine. I did even som minor refactoring.

Don't know if anyone else cares at all, anyway here is updated patch.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Display-source-code-in-help-mode-buffers.patch --]
[-- Type: text/x-patch, Size: 8239 bytes --]

From 63f6f0a9806c8326b8913f5d6856d841c019b4d0 Mon Sep 17 00:00:00 2001
From: Arthur Miller <arthur.miller@live.com>
Date: Wed, 22 Sep 2021 15:33:56 +0200
Subject: [PATCH] Display source code in 'help-mode' buffers

* lisp/help-mode.el (help-mode-inline-source): New option.
(help--fetch-c-src): New function.
(help--fetch-lisp-src): New function.
(help--insert-source): New function.
(help--remove-source): New function.
(help--toggle-source-view): New function.
(help-source-view): New button.
(help-make-xrefs): Check for 'help-mode-inline-source' and
call 'help--insert-source' to perform insertion when possible.
---
 lisp/help-mode.el | 152 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 147 insertions(+), 5 deletions(-)

diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 551cf7e1a3..dc6a532c63 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -149,6 +149,16 @@ help-mode-hook
   "Hook run by `help-mode'."
   :type 'hook
   :group 'help)
+
+(defcustom help-mode-inline-source nil
+  "Display inlined source code in `help-mode' buffers.
+
+When enabled the source code of a symbol currently shown in the
+help-buffer will be displayed inlined in the help buffer, if the
+source code for the symbol is available."
+  :type 'boolean
+  :group 'help
+  :version "28.1")
 \f
 ;; Button types used by help
 
@@ -367,6 +377,11 @@ 'help-news
     (view-buffer-other-window (find-file-noselect file))
     (goto-char pos))
   'help-echo (purecopy "mouse-2, RET: show corresponding NEWS announcement"))
+
+(define-button-type 'help-source-view
+  :supertype 'help-xref
+  'help-function #'help-toggle-source-view
+  'help-echo (purecopy "mouse-2, RET: toggle source view in help-buffer"))
 \f
 (defvar bookmark-make-record-function)
 (defvar help-mode--current-data nil)
@@ -503,6 +518,102 @@ describe-symbol-backends
     and a frame), inserts the description of that symbol in the current buffer
     and returns that text as well.")
 
+(defun help--fetch-c-src (symbol type file)
+  "Find C source code for a Lisp SYMBOL in a FILE.
+
+symbol - the symbol to find.
+type - the type as obtained by 'describe-*' functions.
+file - the source file to search in."
+  (let (src beg)
+    (setq file (expand-file-name file source-directory))
+    (when (file-readable-p file)
+      (with-temp-buffer
+        (insert-file-contents-literally file)
+        (delay-mode-hooks (funcall 'c-mode))
+        (goto-char (point-min))
+        (unless type
+          ;; Either or both an alias and its target might be advised.
+          (setq symbol (find-function-advised-original
+		            (indirect-function
+		             (find-function-advised-original symbol)))))
+        (when (re-search-forward
+	       (if type
+		   (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
+			   (regexp-quote (symbol-name symbol))
+			   "\"")
+	         (concat "DEFUN[ \t\n]*([ \t\n]*\""
+		         (regexp-quote (subr-name (advice--cd*r symbol)))
+		         "\""))
+	       nil t)
+          (if type
+              (and (re-search-backward "DEFVAR" nil t)
+                   (setq beg (point))
+                   (re-search-forward ");$" nil t))
+            (and (re-search-backward "DEFUN" nil t)
+                 (setq beg (point))
+                 (re-search-forward ")[\n\s\t\r]*{")
+                 (re-search-forward "^}[\n\s\t\r]+")))
+          (narrow-to-region beg (point))
+          (with-no-warnings (font-lock-fontify-buffer))
+          (setq src (buffer-string)))))
+    src))
+
+(defun help--fetch-lisp-src (symbol type file)
+  "Find emacs-lisp source code for a Lisp SYMBOL in a FILE.
+
+symbol - the symbol to find.
+type - the type as obtained by 'describe-*' functions.
+file - the source file to search in."
+  (let (src pos)
+    (when file
+      (setq file (or file (find-lisp-object-file-name symbol type))))
+    (with-temp-buffer
+      (insert-file-contents file)
+      (delay-mode-hooks (funcall 'emacs-lisp-mode))
+      (setq pos (cdr (find-function-search-for-symbol symbol type file)))
+      (when pos
+        (goto-char pos)
+        (forward-sexp)
+        (narrow-to-region pos (point))
+        (with-no-warnings (font-lock-fontify-buffer))
+        (setq src (buffer-string))))
+    src))
+
+(defun help--insert-source ()
+  "Fnd and insert source for the current symbol into the help-mode
+buffer."
+  (with-silent-modifications
+    (with-current-buffer (help-buffer)
+      (save-excursion
+        (let* ((file (plist-get help-mode--current-data :file))
+               (type (plist-get help-mode--current-data :type))
+               (sym (plist-get help-mode--current-data :symbol))
+               (src "Source code not available."))
+          (require 'find-func)
+          (when (eq file 'C-source)
+            (setq file (help-C-file-name (indirect-function sym) 'fun)))
+          (setq src (if (string-suffix-p ".c" file)
+                        (help--fetch-c-src sym type file)
+                      (help--fetch-lisp-src sym type file)))
+          (goto-char (point-max))
+          (let ((end (point)))
+            (when (search-backward "View Source Code:" nil t)
+              (delete-region (point) end)
+              (help-insert-xref-button "Hide Source Code:" 'help-source-view)
+              (insert (concat "\n" src "\n")))))))))
+
+(defun help--remove-source ()
+  "Remove source code from the help buffer when present."
+  (with-current-buffer (help-buffer)
+    (with-silent-modifications
+      (save-excursion
+        (goto-char (point-max))
+        (let ((end (point)))
+          (when (search-backward "Hide Source Code:" nil t)
+            (delete-region (point) end)
+            (help-insert-xref-button
+             "View Source Code:" 'help-source-view)))))))
+
 ;;;###autoload
 (defun help-make-xrefs (&optional buffer)
   "Parse and hyperlink documentation cross-references in the given BUFFER.
@@ -664,7 +775,25 @@ help-make-xrefs
             (help-insert-xref-button help-forward-label 'help-forward
                                      (current-buffer)))
           (when (or help-xref-stack help-xref-forward-stack)
-            (insert "\n")))
+            (insert "\n"))
+          (insert "\n")
+          ;; get source string if needed and available
+          ;; describe-symbol does not produce 'current-data' plist
+          (unless help-mode--current-data
+            (save-excursion
+              (goto-char (point-min))
+              (when (re-search-forward "\\.\\(el\\|c\\)" nil t)
+                (goto-char (- (point) 2))
+                (let ((props (get-text-property (point) 'help-args)))
+                  (when props
+                    (setq help-mode--current-data
+                          (list :symbol (nth 0 props)
+                                :file (nth 1 props))))))))
+          (if help-mode-inline-source
+              (progn
+                (insert "View Source Code:") ;; just a little hack
+                (help--insert-source))
+            (help-insert-xref-button "View Source Code:" 'help-source-view)))
         (set-buffer-modified-p old-modified)))))
 
 ;;;###autoload
@@ -819,10 +948,23 @@ help-do-xref
                         (append args (list (generate-new-buffer-name "*info*")))
                       args))))
 
-;; The doc string is meant to explain what buttons do.
-(defun help-follow-mouse ()
-  "Follow the cross-reference that you click on."
-  (declare (obsolete nil "28.1"))
+(defun help-toggle-source-view ()
+  "Toggle source code display in help buffer for the current symbol."
+  (interactive)
+  (when (get-buffer-window (help-buffer))
+    (with-current-buffer (help-buffer)
+      (unless (plist-get help-mode--current-data :file)
+        (error "Source file for the current help item is not defined"))
+      (save-excursion
+        (goto-char (point-min))
+        (if (search-forward "Hide Source Code:" nil t)
+            (help--remove-source)
+          (help--insert-source))))))
+
+  ;; The doc string is meant to explain what buttons do.
+  (defun help-follow-mouse ()
+    "Follow the cross-reference that you click on."
+    (declare (obsolete nil "28.1"))
   (interactive)
   (error "No cross-reference here"))
 
-- 
2.33.0


  parent reply	other threads:[~2021-09-22 13:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-22  8:59 Path & Demo: Source View in Help Buffers Arthur Miller
2021-09-22 10:55 ` Tassilo Horn
2021-09-22 11:06   ` Arthur Miller
2021-09-22 11:32     ` Tassilo Horn
2021-09-22 12:01       ` Arthur Miller
2021-09-22 13:42       ` Arthur Miller [this message]
2021-09-22 14:08         ` Tassilo Horn
2021-09-22 16:50           ` Arthur Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DB9PR09MB498669AD1D02349BD1C5CCC096A29@DB9PR09MB4986.eurprd09.prod.outlook.com \
    --to=arthur.miller@live.com \
    --cc=emacs-devel@gnu.org \
    --cc=tsdh@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.