]> git.eshelyaron.com Git - sweep.git/commitdiff
ADDED: new command for showing help for Prolog modules V8.5.18-sweep-0.6.3
authorEshel Yaron <me@eshelyaron.com>
Sun, 16 Oct 2022 15:22:08 +0000 (18:22 +0300)
committerEshel Yaron <me@eshelyaron.com>
Sun, 16 Oct 2022 17:51:05 +0000 (20:51 +0300)
* sweep.pl: sweep_module_html_documentation/2: new predicate.
* sweeprolog.el:
- sweeprolog-read-module-history: new variable.
- sweeprolog-read-module-name: use it.
- sweeprolog--describe-module: new function.
- sweeprolog-describe-module: new command.
- sweeprolog-help-prefix-map: new keymap.
- sweeprolog-prefix-map: bind it keymap to `h'.
* README.org: Prolog Help: new section.

NEWS.org
README.org
sweep.pl
sweeprolog.el

index 232ce8b5007a67738e9d86c16ca4038038b4f895..3f61e9c5fdb36fc0b93d4159e29d5e31af850c99 100644 (file)
--- a/NEWS.org
+++ b/NEWS.org
@@ -11,6 +11,21 @@ SWI-Prolog in Emacs.
 For further details, please consult the manual:
 <https://eshelyaron.com/sweep.html>.
 
+* Version 0.6.3 on 2022-10-16
+
+** New command ~sweeprolog-describe-module~
+
+Experimental.  Renders the full =PlDoc= documentation of the specified
+Prolog module in a ~help-mode~ buffer.
+
+** Bug fix affecting ~sweeprolog-document-predicate-at-point~
+
+This version includes a fix in ~sweeprolog-beginning-of-top-term~, which
+is used to locate the beginning of the current clause.  Previously
+this function could hang when invoked with point before the first term
+on the buffer.  This affected commands that depend of this function,
+such as ~M-x sweeprolog-document-predicate-at-point~.
+
 * Version 0.6.2 on 2022-10-15
 
 ** New command ~sweeprolog-export-predicate~ in ~sweeprolog-mode~ buffers
@@ -20,7 +35,7 @@ For further details, please consult the manual:
 the current module's export list.  Bound to =C-c C-e= in
 ~sweeprolog-mode-map~.
 
-** Added a Prolog indicating the Prolog is running under ~sweep~
+** Added a Prolog flag indicating the Prolog is running under ~sweep~
 
 =sweeprolog.el= now creates a boolean Prolog flag ~sweep~ set to ~true~ when
 initiating Prolog, to allow users to customize their Prolog init file
index 5b28a7a9572af2fba0cc7d5af59833ee36bbc626..df8602c94f84d01eeb9d1a56da271688ac0bbb09 100644 (file)
@@ -872,6 +872,10 @@ called with a prefix argument (~C-u C-c C-`~), shows a list of
 diagnostics for all buffers in the current project.
 
 ** Exporting predicates
+:PROPERTIES:
+:CUSTOM_ID: exporting-predicates
+:DESCRIPTION: Commands for adding Prolog predicates to their module's export list
+:END:
 
 #+CINDEX: exported predicates
 By default, a predicate defined in Prolog module is not visible to
@@ -894,6 +898,26 @@ the non-exported predicates defined in the current buffer.  To force
 prompting for a predicate, invoke ~sweeprolog-export-predicate~ with a
 prefix argument (~C-u C-c C-e~).
 
+* Prolog Help
+:PROPERTIES:
+:CUSTOM_ID: prolog-help
+:DESCRIPTION: Commands for displaying detailed Prolog documentation
+:END:
+
+#+CINDEX: prolog help
+~sweep~ provides a way to read SWI-Prolog documentation via the standard
+Emacs ~help~ user interface, akin to Emacs' built-in ~describe-function~
+(~C-h f~) and ~describe-variable~ (~C-h v~).  For more information about
+Emacs ~help~ and its special major mode, ~help-mode~, see [[info:emacs#Help Mode][Help Mode in the
+Emacs manual]].
+
+#+FINDEX: sweeprolog-describe-module
+#+KINDEX: s (help-mode)
+The command ~M-x sweeprolog-describe-module~ prompts for the name of a
+Prolog module and displays its documentation in the =*Help*= buffer.  To
+jump to the source code from its documentation, press ~s~
+(~help-view-source~).
+
 * The Prolog top-level
 :PROPERTIES:
 :CUSTOM_ID: prolog-top-level
@@ -1270,11 +1294,6 @@ there some further improvements that we want to pursue:
   ~help-echo~ property that says what kind of token this is, to expose
   the precise semantics of each token to the user.
 
-- Add a command for exporting the current predicate :: ~sweeprolog-mode~
-  should provide a command for adding a predicate to the export list
-  of the module defined in the current buffer, defaulting to the
-  predicate at point.
-
 - Add a command for updating the dependencies for the current module :: ~sweeprolog-mode~
   should provide a command for adding and/or updating ~use_module/2~ and
   ~autoload/2~ directives as needed according to the predicates that the
@@ -1356,7 +1375,9 @@ there some further improvements that we want to pursue:
   should include a command ~sweeprolog-describe-predicate~ that works
   similarly to the built-in ~describe-function~ by opening a ~help-mode~
   buffer and populating it with the full cross-referenced
-  documentation of a given Prolog predicate.
+  documentation of a given Prolog predicate.  We currently have
+  ~sweeprolog-describe-module~ as a proof of concept which should be
+  extended to cover predicate documentation as well.
 
 - Integrate with =project.el= adding support for SWI-Prolog packs :: It
   would be nice if ~sweep~ would "teach" =project.el= to detect
index 62ea14b521362994365c80f32321192b1ad8b911..42584444885741c77284f379d4a3ce600f437f0f 100644 (file)
--- a/sweep.pl
+++ b/sweep.pl
@@ -61,7 +61,8 @@
             sweep_top_level_threads/2,
             sweep_accept_top_level_client/2,
             sweep_local_predicate_export_comment/2,
-            write_sweep_module_location/0
+            write_sweep_module_location/0,
+            sweep_module_html_documentation/2
           ]).
 
 :- use_module(library(pldoc)).
 :- use_module(library(pldoc/doc_wiki)).
 :- use_module(library(pldoc/doc_modes)).
 :- use_module(library(pldoc/doc_man)).
+:- use_module(library(pldoc/doc_html)).
 :- use_module(library(pldoc/man_index)).
 :- use_module(library(lynx/html_text)).
+:- use_module(library(http/html_write)).
 :- use_module(library(prolog_pack)).
 
 :- meta_predicate with_buffer_stream(-, +, 0).
@@ -426,9 +429,22 @@ sweep_module_path(ModuleName, Path) :-
 
 sweep_module_path_(Module, Path) :-
     module_property(Module, file(Path)), !.
+sweep_module_path_(Module, Path) :-
+    xref_module(Path, Module), !.
 sweep_module_path_(Module, Path) :-
     '$autoload':library_index(_, Module, Path0), !, string_concat(Path0, ".pl", Path).
 
+sweep_module_html_documentation(M0, D) :-
+    atom_string(M, M0),
+    (   sweep_module_path_(M, _)
+    ->  true
+    ;   '$autoload':library_index(_, M, Path),
+        xref_source(Path, [comments(store)])
+    ),
+    doc_comment(M:module(Desc), Pos, _, Comment),
+    pldoc_html:pred_dom(M:module(Desc), [], Pos-Comment, DOM),
+    phrase(pldoc_html:html(DOM), HTML),
+    with_output_to(string(D), html_write:print_html(HTML)).
 
 sweep_modules_collection([], Modules) :-
     findall([M|P], ( module_property(M, file(P0)), atom_string(P0, P) ), Modules0, Tail),
index dd906df9c724033d94a789f4c92620c051f7d3db..76b81062933a82d8ede60ad42adbfeb423ed63a9 100644 (file)
@@ -6,7 +6,7 @@
 ;; Maintainer: Eshel Yaron <~eshel/dev@lists.sr.ht>
 ;; Keywords: prolog languages extensions
 ;; URL: https://git.sr.ht/~eshel/sweep
-;; Package-Version: 0.6.2
+;; Package-Version: 0.6.3
 ;; Package-Requires: ((emacs "28"))
 
 ;; This file is NOT part of GNU Emacs.
@@ -32,6 +32,9 @@
 (require 'autoinsert)
 (require 'eldoc)
 (require 'flymake)
+(require 'help-mode)
+(require 'find-func)
+(require 'shr)
 
 (defgroup sweeprolog nil
   "SWI-Prolog Embedded in Emacs."
@@ -572,6 +575,8 @@ module name, F is a functor name and N is its arity."
     (when (sweeprolog-true-p sol)
       (cdr sol))))
 
+(defvar sweeprolog-read-module-history nil)
+
 (defun sweeprolog-read-module-name ()
   "Read a Prolog module name from the minibuffer, with completion."
   (let* ((col (sweeprolog-modules-collection))
@@ -585,7 +590,9 @@ module name, F is a functor name and N is its arity."
                             (if des
                                 (concat pat (make-string (max 0 (- 80 (length pat))) ? ) des)
                               pat)))))))
-    (completing-read sweeprolog-read-module-prompt col)))
+    (completing-read sweeprolog-read-module-prompt col nil nil nil
+                     'sweeprolog-read-module-history
+                     sweeprolog-buffer-module)))
 
 
 (defun sweeprolog--set-buffer-module ()
@@ -1760,6 +1767,13 @@ Interactively, a prefix arg means to prompt for BUFFER."
 (sweeprolog--ensure-module)
 (when sweeprolog-init-on-load (sweeprolog-init))
 
+;;;###autoload
+(defvar sweeprolog-help-prefix-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "m" #'sweeprolog-describe-module)
+    map)
+  "Keymap for `sweeprolog' help commands.")
+
 ;;;###autoload
 (defvar sweeprolog-prefix-map
   (let ((map (make-sparse-keymap)))
@@ -1768,6 +1782,7 @@ Interactively, a prefix arg means to prompt for BUFFER."
     (define-key map "R" #'sweeprolog-restart)
     (define-key map "T" #'sweeprolog-list-top-levels)
     (define-key map "e" #'sweeprolog-view-messages)
+    (define-key map "h" sweeprolog-help-prefix-map)
     (define-key map "l" #'sweeprolog-load-buffer)
     (define-key map "m" #'sweeprolog-find-module)
     (define-key map "p" #'sweeprolog-find-predicate)
@@ -1933,6 +1948,8 @@ Interactively, PROJ is the prefix argument."
                   (buffer-list)) ]
     [ "Open Top-level Menu"    sweeprolog-list-top-levels t ]
     "--"
+    [ "Describe Prolog module" sweeprolog-describe-module t ]
+    "--"
     [ "Reset sweep"            sweeprolog-restart         t ]
     [ "View sweep messages"    sweeprolog-view-messages   t ]))
 
@@ -2902,6 +2919,54 @@ if-then-else constructs in SWI-Prolog."
       (tabulated-list-print))
     (pop-to-buffer-same-window buf)))
 
+(defun sweeprolog--describe-module (mod)
+  (let ((page
+         (progn
+           (sweeprolog-open-query "user"
+                                  "sweep"
+                                  "sweep_module_html_documentation"
+                                  mod)
+           (let ((sol (sweeprolog-next-solution)))
+             (sweeprolog-close-query)
+             (when (sweeprolog-true-p sol)
+               (with-temp-buffer
+                 (insert (cdr sol))
+                 (let ((shr-external-rendering-functions
+                        '((a . shr-generic))))
+                   (shr-render-region (point-min) (point-max)))
+                 (buffer-string)))))))
+    (help-setup-xref (list #'sweeprolog--describe-module mod)
+                     (called-interactively-p 'interactive))
+    (with-help-window (help-buffer)
+      (with-current-buffer (help-buffer)
+        (if-let ((path (sweeprolog-module-path mod)))
+            (progn
+              (setq help-mode--current-data
+                    (list :symbol (intern mod)
+                          :type   'swi-prolog-module
+                          :file   path))
+              (if page
+                  (insert (buttonize mod #'sweeprolog-find-module mod)
+                          " is a SWI-Prolog module.\n\n"
+                          page)
+                (insert (buttonize mod #'sweeprolog-find-module mod)
+                        " is an undocumented SWI-Prolog module.")))
+          (insert mod " is not documented as a SWI-Prolog module."))))))
+
+;;;###autoload
+(defun sweeprolog-describe-module (mod)
+  "Display the full documentation for MOD (a Prolog module)."
+  (interactive (list (sweeprolog-read-module-name)))
+  (sweeprolog--describe-module mod))
+
+(defvar sweeprolog-module-documentation-regexp (rx bol  (zero-or-more whitespace)
+                                                   ":-" (zero-or-more whitespace)
+                                                   "module("))
+
+(add-to-list 'find-function-regexp-alist
+             (cons 'swi-prolog-module
+                   'sweeprolog-module-documentation-regexp))
+
 (provide 'sweeprolog)
 
 ;;; sweeprolog.el ends here