summaryrefslogtreecommitdiff
path: root/manpages/TDM.el
diff options
context:
space:
mode:
Diffstat (limited to 'manpages/TDM.el')
-rw-r--r--manpages/TDM.el172
1 files changed, 172 insertions, 0 deletions
diff --git a/manpages/TDM.el b/manpages/TDM.el
new file mode 100644
index 00000000..a58fb1c8
--- /dev/null
+++ b/manpages/TDM.el
@@ -0,0 +1,172 @@
+;;; TDM.el --- editing Taler docs.git/manpages/* -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021, 2022 Taler Systems SA
+;;
+;; This file is part of GNU TALER.
+;;
+;; TALER is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU Affero General Public License as
+;; published by the Free Software Foundation; either version 2.1,
+;; or (at your option) any later version.
+;;
+;; TALER is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU Affero General Public License for more details.
+;;
+;; You should have received a copy of the GNU Affero General Public
+;; License along with TALER; see the file COPYING. If not, see
+;; <http://www.gnu.org/licenses/>.
+;;
+;; Author: Thien-Thi Nguyen <ttn@gnu.org>
+
+;;; Commentary:
+
+;; This library currently provides two commands: ‘TDM-convert-options’
+;; and ‘TDM-recursive-help’.
+;;
+;; * ‘TDM-convert-options’
+;; The intended workflow is simple:
+;; - Create a new file from template.
+;; - Do the <FOO> substitutions / deletions as necessary.
+;; - Split the window, one half for Synopsis, one for Description.
+;; - Do ‘COMMAND --help’ and copy the portion of its output that
+;; describes the options into the buffer in the Synopsis section.
+;; + Place point at bol of an option and call ‘TDM-convert-options’.
+;; (Personally, I locally bind this to ‘C-c C-o’.)
+;; - Set mark at point and move point to the end of the
+;; description text (for that option).
+;; - Kill the region (with ‘C-w’).
+;; - Switch to the other window, find a suitable place, and
+;; yank (with ‘C-y’) the text there.
+;; - Edit the description as necessary.
+;; - Loop from "+" until finished.
+;;
+;; At the end, you may have to delete some extra blank lines
+;; in the Synopsis section.
+;;
+;; ‘TDM-convert-options’ takes a prefix arg, which inhibits the
+;; deletion of the original (--help output) text. This can be
+;; useful if you don't trust (yet :-D) the conversion process.
+;;
+;; There are a couple TODO items, which point to situations that
+;; have not yet arisen in practice, but that might theoretically
+;; bother us in the future.
+;;
+;; * ‘TDM-recursive-help’
+;; This command is intended for libeufin programs, specifically
+;; libeufin-sandbox, libeufin-nexus, and libeufin-cli. However,
+;; it should work with any Java program that uses clikt, or any
+;; Python program that uses click, for its command-line handling.
+;;
+;; You can obtain the --help output (recursively) in a buffer
+;; and write it to a file for further analysis / processing.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defun TDM-parse-option-triple ()
+ "Return a triple formed by parsing option text at point.
+The triple has the form (ARG SHORT LONG), where each element
+can be either a string or ‘nil’.
+
+Signal error if parsing fails.
+Leave point after the end of the parsed text."
+ (cl-flet ((peer (regexp)
+ (re-search-forward regexp (line-end-position) t)))
+ (cond
+ ;; Full form: (ARG SHORT LONG).
+ ((peer " *-\\(.\\), --\\([^=\n]+\\)=\\(\\S +\\)")
+ (mapcar #'match-string-no-properties (list 3 1 2)))
+ ;; No argument: (nil SHORT LONG).
+ ((peer " *-\\(.\\), --\\(\\S +\\)")
+ (list nil
+ (match-string-no-properties 1)
+ (match-string-no-properties 2)))
+ ;; TODO: Handle other combinations.
+ (t
+ (error "Could not parse option text")))))
+
+(defun TDM-insert-options (arg short long)
+ "Insert formatted options, twice (on two lines).
+The first is for the Synopsis section, the second for Description."
+ (unless (zerop (current-column))
+ (open-line 1)
+ (forward-line 1))
+ (cl-flet ((ins (short-space sep)
+ (cond
+ ;; Both available.
+ ((and short long)
+ (insert "**-" short "**")
+ (when arg
+ (insert short-space "*" arg "*"))
+ (insert sep)
+ (insert "**--" long (if arg "=" "") "**")
+ (when arg
+ (insert "\\ \\ *" arg "*")))
+ ;; TODO: Handle other combinations.
+ (t
+ (error "Could not handle (%S %S %S)"
+ arg short long)))))
+ ;; First line.
+ (insert "[")
+ (ins " " " | ")
+ (insert "]\n")
+ ;; Second line. Leave point at its beginning.
+ (save-excursion
+ (ins " " " \\| ")
+ ;; Add a newline only if necessary.
+ (unless (eolp)
+ (insert "\n")))))
+
+(defun TDM-convert-options (&optional keep-orig)
+ "Grok the options at point and insert formatted ones.
+If successful, delete the parsed options as well.
+Prefix arg KEEP-ORIG means don't delete them."
+ (interactive "P")
+ (let* ((p (point))
+ (triple (TDM-parse-option-triple))
+ (q (point)))
+ (apply #'TDM-insert-options triple)
+ (unless keep-orig
+ (save-excursion
+ (delete-region p q)))))
+
+(defun TDM-recursive-help (command)
+ "Call COMMAND --help and recurse on its subcommands.
+Subcommands are identified by \"Commands:\" in column 0
+in the output.
+
+Collect the output in a new buffer *COMMAND --help*,
+with one page per --help output."
+ (interactive "sCommand: ")
+ (let ((out (get-buffer-create (format "*%s --help*" command))))
+ (with-current-buffer out
+ (erase-buffer))
+ (cl-labels
+ ;; visit command
+ ((v (c) (with-temp-buffer
+ (apply #'call-process (car c) nil t nil
+ (append (cdr c) (list "--help")))
+ (goto-char (point-min))
+ (when (re-search-forward "^Commands:\n" nil t)
+ (while (looking-at "[ ][ ]\\(\\S +\\)")
+ (let ((sub (match-string 1)))
+ (v (append c (list sub))))
+ (forward-line 1)
+ (while (looking-at "[ ][ ][ ]")
+ (forward-line 1))))
+ (let ((s (buffer-string)))
+ (message "c: %s" c)
+ (with-current-buffer out
+ (goto-char (point-min))
+ (insert "\f\n")
+ (insert "$ " (substring (format "%s" c) 1 -1) "\n")
+ (insert s "\n"))))))
+ (v (list command)))
+ (switch-to-buffer out)))
+
+(provide 'TDM)
+
+;;; TDM.el ends here