* 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.
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
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
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
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
~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
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
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).
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),
;; 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.
(require 'autoinsert)
(require 'eldoc)
(require 'flymake)
+(require 'help-mode)
+(require 'find-func)
+(require 'shr)
(defgroup sweeprolog nil
"SWI-Prolog Embedded in Emacs."
(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))
(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 ()
(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)))
(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)
(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 ]))
(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