For more information about =PlDoc= and source documentation in
SWI-Prolog, see [[https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/pldoc.html%27)][the PlDoc manual]].
+** Example Usage Comments
+:PROPERTIES:
+:CUSTOM_ID: usage-comments
+:DESCRIPTION: Commands for inserting comments that show example usage of your code
+:ALT_TITLE: Usage Comments
+:END:
+
+Beyond documenting your code with =PlDoc= comments as described in
+[[#sweeprolog-pldoc][Documenting Predicates]], you might want to have comments in your source
+code that shows example usage of some predicate. Creating such
+comments usually involves posting queries in a Prolog top-level,
+copying the queries and their results into the relevant source code
+buffer, and formatting them as comments. Sweep provides the following
+command to streamline this process:
+
+#+FINDEX: sweeprolog-make-example-usage-comment
+- Key: C-c C-% (sweeprolog-make-example-usage-comment) :: Start a
+ new top-level for recording example usage. When you finish
+ interacting with the top-level its contents are formatted as a
+ comment in the buffer and position where you invoked this command.
+
+The command ~sweeprolog-make-example-usage-comment~, bound to ~C-c
+C-%~ in ~sweeprolog-mode~ buffers, creates and switches to a new
+top-level buffer for recording example usage that you want to
+demonstrate. The /example usage top-level/ is a regular top-level
+buffer (see [[*The Prolog Top-Level][The Prolog Top-Level]]), except that it's tied to the
+specific position in the source buffer where you invoke this command.
+You can post queries in the example usage top-level and edit it
+freely, then type ~C-c C-q~ in to quit the top-level buffer and format
+its contents as a comment in the source buffer.
+
+You can have multiple example usage top-levels for different parts of
+your code at the same time. To display the source position where you
+created a certain usage example top-level buffer by, type ~C-c C-b~ in
+that buffer.
+
** Displaying Predicate Documentation
:PROPERTIES:
:CUSTOM_ID: eldoc-integration
#'sweeprolog-show-diagnostics
#'flymake-show-diagnostics-buffer))
(define-key map (kbd "C-c C-&") #'sweeprolog-async-goal)
+ (define-key map (kbd "C-c C-%") #'sweeprolog-make-example-usage-comment)
(define-key map (kbd "C-c C--") #'sweeprolog-decrement-numbered-variables)
(define-key map (kbd "C-c C-+") #'sweeprolog-increment-numbered-variables)
(define-key map (kbd "C-M-^") #'kill-backward-up-list)
map)
"Keymap for moving to next hole with TAB.")
+(defvar sweeprolog-top-level-example-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-c C-b") #'sweeprolog-top-level-example-display-source)
+ (define-key map (kbd "C-c C-q") #'sweeprolog-top-level-example-done)
+ map)
+ "Keymap for example top-level buffer.")
+
;;;; Menu bar
(easy-menu-define sweeprolog-menu (list sweeprolog-mode-map
(defvar-local sweeprolog-top-level-thread-id nil
"Prolog top-level thread ID corresponding to this buffer.")
+(defvar-local sweeprolog-top-level-example-marker nil)
+
(defvar-local sweeprolog--buffer-last-modified-time nil)
(defvar-local sweeprolog--buffer-modified nil)
(unless (sweeprolog-expand-macro-at-pos point)
(user-error "No macro invocation at point")))
+(define-minor-mode sweeprolog-top-level-example-mode
+ "Minor mode for example top-level sessions.
+This mode is enabled in top-level buffers created by
+\\[sweeprolog-make-example-usage-comment]."
+ :lighter " Example"
+ :group 'sweeprolog)
+
+(defun sweeprolog-top-level-example-display-source ()
+ "Pop to the source position where this example session was started.
+This is the position where
+`sweeprolog-make-example-usage-comment' was invoked to create
+the current top-level buffer, and where
+\\[sweeprolog-top-level-example-done] inserts its contents of as
+a comment."
+ (interactive "" sweeprolog-top-level-mode)
+ (unless sweeprolog-top-level-example-mode
+ (user-error "Not in an example top-level session"))
+ (let ((source-buffer (marker-buffer sweeprolog-top-level-example-marker)))
+ (unless (buffer-live-p source-buffer)
+ (user-error "Source buffer for this example session no longer alive"))
+ (let ((marker sweeprolog-top-level-example-marker))
+ (display-buffer source-buffer)
+ (goto-char marker))))
+
+(defun sweeprolog-top-level-example-done ()
+ "Finalize the current example top-level session.
+This kills the current top-level buffer and inserts its contents
+as a comment in the source location where you invoked
+`sweeprolog-make-example-usage-comment' to create it."
+ (interactive "" sweeprolog-top-level-mode)
+ (unless sweeprolog-top-level-example-mode
+ (user-error "Not in an example top-level session"))
+ (let ((source-buffer (marker-buffer sweeprolog-top-level-example-marker)))
+ (unless (buffer-live-p source-buffer)
+ (user-error "Source buffer for this example session no longer alive"))
+ (let ((top-level-buffer (current-buffer))
+ (example (replace-regexp-in-string
+ (rx "?- " eos) ""
+ (string-replace
+ "\n\n" "\n"
+ (buffer-substring-no-properties (point-min)
+ (point-max)))))
+ (marker sweeprolog-top-level-example-marker))
+ (pop-to-buffer source-buffer)
+ (unless (string-empty-p example)
+ (save-excursion
+ (goto-char marker)
+ (insert example)
+ (comment-region marker (point))))
+ (delete-process (get-buffer-process top-level-buffer))
+ (kill-buffer top-level-buffer))))
+
+(defun sweeprolog-make-example-usage-comment (point)
+ "Start a top-level and record it as a comment at POINT.
+This creates a new example top-level buffer where you can perform
+queries in this top-level as usual. Use
+\\<sweeprolog-top-level-example-mode-map>\\[sweeprolog-top-level-example-done]
+in the example top-level buffer to finish and format the session
+as a comment in the source buffer at starting at POINT."
+ (interactive "d" sweeprolog-mode)
+ (let ((marker (copy-marker point))
+ (buffer (sweeprolog-top-level-buffer (generate-new-buffer-name
+ "*Example Session*"))))
+ (pop-to-buffer buffer)
+ (setq sweeprolog-top-level-example-marker marker
+ header-line-format (substitute-command-keys
+ (format "`\\<sweeprolog-top-level-example-mode-map>\\[sweeprolog-top-level-example-done]' to quit and write contents as a comment in buffer %s" (buffer-name (marker-buffer marker)))))
+ (sweeprolog-top-level-example-mode)))
+
;;;; Footer
(provide 'sweeprolog)