From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Arthur Miller Newsgroups: gmane.emacs.devel Subject: Patch proposal: display symbol source code in help buffers Date: Sun, 19 Sep 2021 21:50:35 +0200 Message-ID: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="25863"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Sep 19 21:56:47 2021 Return-path: Envelope-to: ged-emacs-devel@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 1mS2vd-0006XR-QX for ged-emacs-devel@m.gmane-mx.org; Sun, 19 Sep 2021 21:56:46 +0200 Original-Received: from localhost ([::1]:43674 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mS2vb-0004eq-GG for ged-emacs-devel@m.gmane-mx.org; Sun, 19 Sep 2021 15:56:43 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:43634) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mS2ue-0003wL-Kg for emacs-devel@gnu.org; Sun, 19 Sep 2021 15:55:44 -0400 Original-Received: from mail-db8eur05olkn20803.outbound.protection.outlook.com ([2a01:111:f400:7e1a::803]:53793 helo=EUR05-DB8-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mS2ua-0000eU-Qt for emacs-devel@gnu.org; Sun, 19 Sep 2021 15:55:42 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZGgtTbovZm8RFeWsuAC1xrMo2kNhXkQDig8FHhT0yZ2dY63Ee1iHmtewyJfQabOrtV0FehzgII85zUjznZKGLgpNY0oaGJ1OxvsMgS3PSj8rGP15vdAPcf13z9IZ9LRXYpSkhbSuyAvzj92MiGJChJFxbCuETP/j8IbdOuVrq8TapOpLYN1DnxgSMgVFt8zjkdvl5dfRsVlkOxKBgiexpClE9bhn+DoRokiYcv3T/GZvZme1F6MA+Qm3khYIEItu9Na3/gMZ7KfhuTb33J9f8+/61B7uOICzBUp46j8fMFArAAxlcR0RQPvCzjm0mGQJCnDf+Pp5xTxnkvW4VBzwfg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=4GepCPawf9DWJpZl+4kWiaxlGRBDgUS69/mInkZXH+Y=; b=Q5aq6JpZ/3vt9gkapH70bRofX12942VM/OpvLmOsQAXK/7mcdO3cdnFqkw1DBC4wOn/jkdwDaD6p884doxvGa7HEtw1v6v7Q0RNOpjgDsm0m1ptquj4S7/0CYIeYTdXGVgq3QozNd0YocHS2BkpWmpRbN1VPEJ/8FAcX24rEGIV8w5NBDvzPqu7lIpcecyZXnttmt3psvwVuiatlOWUyeWEBA+dOZi2QMUYoxlZ8yN7lvv1mD2czejPcmeiyMMvZwPZu1KN2QGHzvRCWmyIusBXNgrlT1MM0fDdtHemGQ3cgtIUi2tie16aWNffcSLBVAK2/3gz6at+M3y0TyYJ+1g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=4GepCPawf9DWJpZl+4kWiaxlGRBDgUS69/mInkZXH+Y=; b=eHfIqbiaK0b2AsuUhpazfVXUcheRfzOLJ8NoxgeCYjEB8+m4vpAPDo7q7AhN+K7XF4b2gGW7nvWYwYEJrEf1YaDKDI14HwP6Fh/xWci8wMNHKwzxIaRpw+PYYA62jk7xiMciEtSyOB8FRa81Bi89ap4SGaao0zqjUByDXR3heopQtj8zhz+9cLgAZNUJNOkYhJ2b1+ygxmq1BRqfhnL07uw73+oyQVc9rIsFTCJi3vdkDDbXOEwCsXeyZBGLFz9ViTZnnZsR79axYdMGqx1H+v8y4rzkl/RayMxx2hWObAwGEW4+dlNAstLl+pf2OI/QeZ1MVzu5zSsodJhwb2nRjw== Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) by AM9PR09MB4675.eurprd09.prod.outlook.com (2603:10a6:20b:2dc::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14; Sun, 19 Sep 2021 19:50:36 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::c55c:ece5:bed2:a9dc]) by AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::c55c:ece5:bed2:a9dc%9]) with mapi id 15.20.4523.018; Sun, 19 Sep 2021 19:50:36 +0000 X-TMN: [KJeIl/TTa+QKt5u1XkNVG+Psl5iavaz1] X-ClientProxiedBy: AS8P250CA0007.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:330::12) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <875yuwe450.fsf@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 Original-Received: from pascal.homepc (81.232.177.30) by AS8P250CA0007.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:330::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14 via Frontend Transport; Sun, 19 Sep 2021 19:50:35 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d5409d1f-52b3-463b-8592-08d97ba6bf90 X-MS-TrafficTypeDiagnostic: AM9PR09MB4675: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: AwLhAv1UyTvTdJqi+Rlpjc85ug5q0Ujh7PbAQElSCCbRdLBchHpN3h7pM40nKoIdfKf1lqE4TU/Ex7V/HVjVdmS049W1iPpz+eK0oLGkOeEDRQoqsQEyDXpUlbTk9ZLB8B2M2Wd2E7UzQicYkUQ2PlRue6yH7CQhahKxctySC8fgnWKtKJ3iA6NTcmXaPy4tgZgLxf7PqJ5yMbHnwmkoqN99qJzGMnN0GsCCJp1yDopSFbbROt/d6W1kwCj1AyyzQ3RCEnAloyMbSuGqeVsT7E4sSUbNIaAu0TFUkrRhz/pkOnEXlfjsDBsVO9EUOlQXTk3HpN4mLHSA1iGJZLbuAqjvPydsWrufhxqxrHt+rGHa6HBfssJwCG8Wa9yqVOKm6YGb1ttyznn4QUIgeloBzmnbwo6W0gimYSocUTvld2dZjmQxRFSijN+nVN9KvI+Y X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: equWBJh2WOSHP7QqopDnj/iq2m+Q0SSfByPcDcSskKoPSyw+RlzqP2a+hyot3nnLOne1tFNXlnyzSLDhhGnWgLMVcWszvLhK6jz1ehsPJF0TPAQErBhSRznpqsyN9h7nF89EVvU+NOcuTTmkBcirhA== X-OriginatorOrg: sct-15-20-3174-20-msonline-outlook-72e6e.templateTenant X-MS-Exchange-CrossTenant-Network-Message-Id: d5409d1f-52b3-463b-8592-08d97ba6bf90 X-MS-Exchange-CrossTenant-AuthSource: AM9PR09MB4977.eurprd09.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Sep 2021 19:50:36.2186 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9PR09MB4675 Received-SPF: pass client-ip=2a01:111:f400:7e1a::803; envelope-from=arthur.miller@live.com; helo=EUR05-DB8-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, MSGID_FROM_MTA_HEADER=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:275081 Archived-At: --=-=-= Content-Type: text/plain Here is my second proposal to bring built-in help on par with external offerings. This one is little bit more than just three lines as the previous one was, so I would really appreciate if I could get some thorough review and testing. It works fine for me, but Emacs source code is big; so there is always possibility that something is not displaying correctly. I had thoughts of writing automated test, a scraper sort of like autloads collects help to collect docs from files and than call new help routines and compare results, but that would be far more involved than actually hacking help-mode :). What I am worried about is how does it work with compressed sources? How do I test it and what would I need to do to get it to work? Do I need to manually decompress tar-ed sources or is it already taken care? I believe, and I hope, that it is, but I am really not at home with how that part of Emacs work. I appreciate advice and help there, also if someone can test. Another thing: can I assume that all DEFVAR_LISP statements in .c files end with a ');$'? I am using this in a regexp to fetch the entire source for those defvars. I have tried to be as least intrusive as I could, so everything is in help-mode. There is also a defcustom defaulting to nil to enable/disable this, and I think it should always stay at nil since this can be cpu intensive. I think it actually works quite well, I see no hickups, but I do run Emacs from surce directory, and I use it as 'source-directory'. By the way, this patch expects sources to be found in what this variable shows. If this would be acceptable, I can write some NEWS and manual, unless someone more english language savvy would like to help with that one. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Display-source-code-in-help-mode-buffers.patch >From 58eac63f759146cf7a601e1ae974dd373c837957 Mon Sep 17 00:00:00 2001 From: Arthur Miller Date: Sun, 19 Sep 2021 21:28:01 +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--symbol-source'): New function. ('help-make-xrefs): Check for 'help-mode-inline-source' and call 'help--symbol-source' to perform insertion when possible. --- lisp/help-mode.el | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 551cf7e1a3..935c54a6eb 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -149,6 +149,15 @@ help-mode-hook "Hook run by `help-mode'." :type 'hook :group 'help) + +(defcustom help-mode-inline-source nil + "Display inlined source code for SYMBOL in `help-mode' buffer. + +When enabled the source code of a symbol will be displayed inlined in +the help buffer, if the source code for the symbol is available." + :type 'boolean + :group 'help + :version "28.1") ;; Button types used by help @@ -503,6 +512,91 @@ 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 (sym type file) + "Find C source code for a Lisp symbol in a `file'. + +sym is the symbol to find. +type is the type as obtained by 'describe-*' functions. +file is the source file to search in." + (let (src pos) + (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 sym (find-function-advised-original + (indirect-function + (find-function-advised-original sym))))) + (when (re-search-forward + (if type + (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\"" + (regexp-quote (symbol-name sym)) + "\"") + (concat "DEFUN[ \t\n]*([ \t\n]*\"" + (regexp-quote (subr-name (advice--cd*r sym))) + "\"")) + nil t) + (if type ;; defvar here + (progn + (goto-char (line-beginning-position)) + (skip-chars-forward "[:blank:]") + (setq pos (point)) + (re-search-forward ");$" nil t) + (narrow-to-region pos (point))) + (narrow-to-defun)) + (if (fboundp 'font-lock-ensure) + (font-lock-ensure) + (with-no-warnings (font-lock-fontify-buffer))) + (setq src (buffer-string))))) + src)) + +(defun help--fetch-lisp-src (sym type file) + "Find emacs-lisp source code for a Lisp symbol in a `file'. + +sym is the symbol to find. +type is the type as obtained by 'describe-*' functions. +file is the source file to search in." + (let (src pos sxp) + (when file + (setq file (or file (find-lisp-object-file-name sym type)))) + (with-temp-buffer + (insert-file-contents file) + (delay-mode-hooks (funcall 'emacs-lisp-mode)) + (require 'find-func) + (setq pos (cdr (find-function-search-for-symbol sym type file))) + (when pos + (goto-char pos) + (forward-sexp) + (setq sxp (buffer-substring-no-properties pos (point))) + (when sxp + (erase-buffer) + (insert sxp) + (if (fboundp 'font-lock-ensure) + (font-lock-ensure) + (with-no-warnings (font-lock-fontify-buffer))) + (setq src (buffer-string))))) + src)) + +(defun help--symbol-source () + "Fnd and return string to be inserted in help-mode buffer for the +source code of the symbol. + +Used internally for `help-make-refs'." + (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) + (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))) + (if src src "Source code not available."))) + ;;;###autoload (defun help-make-xrefs (&optional buffer) "Parse and hyperlink documentation cross-references in the given BUFFER. @@ -651,6 +745,22 @@ help-make-xrefs (while (and (not (bobp)) (bolp)) (delete-char -1)) (insert "\n") + ;; get source string if needed and available + (when help-mode-inline-source + (insert "\nSource Code: \n") + ;; 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)))))))) + (insert (help--symbol-source)) + (insert "\n")) (when (or help-xref-stack help-xref-forward-stack) (insert "\n")) ;; Make a back-reference in this buffer if appropriate. -- 2.33.0 --=-=-=--