TDM.el (6482B)
1 ;;; TDM.el --- editing Taler docs.git/manpages/* -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2021, 2022 Taler Systems SA 4 ;; 5 ;; This file is part of GNU TALER. 6 ;; 7 ;; TALER is free software; you can redistribute it and/or modify it 8 ;; under the terms of the GNU Affero General Public License as 9 ;; published by the Free Software Foundation; either version 2.1, 10 ;; or (at your option) any later version. 11 ;; 12 ;; TALER is distributed in the hope that it will be useful, but 13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of 14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ;; GNU Affero General Public License for more details. 16 ;; 17 ;; You should have received a copy of the GNU Affero General Public 18 ;; License along with TALER; see the file COPYING. If not, see 19 ;; <http://www.gnu.org/licenses/>. 20 ;; 21 ;; Author: Thien-Thi Nguyen <ttn@gnu.org> 22 23 ;;; Commentary: 24 25 ;; This library currently provides two commands: ‘TDM-convert-options’ 26 ;; and ‘TDM-recursive-help’. 27 ;; 28 ;; * ‘TDM-convert-options’ 29 ;; The intended workflow is simple: 30 ;; - Create a new file from template. 31 ;; - Do the <FOO> substitutions / deletions as necessary. 32 ;; - Split the window, one half for Synopsis, one for Description. 33 ;; - Do ‘COMMAND --help’ and copy the portion of its output that 34 ;; describes the options into the buffer in the Synopsis section. 35 ;; + Place point at bol of an option and call ‘TDM-convert-options’. 36 ;; (Personally, I locally bind this to ‘C-c C-o’.) 37 ;; - Set mark at point and move point to the end of the 38 ;; description text (for that option). 39 ;; - Kill the region (with ‘C-w’). 40 ;; - Switch to the other window, find a suitable place, and 41 ;; yank (with ‘C-y’) the text there. 42 ;; - Edit the description as necessary. 43 ;; - Loop from "+" until finished. 44 ;; 45 ;; At the end, you may have to delete some extra blank lines 46 ;; in the Synopsis section. 47 ;; 48 ;; ‘TDM-convert-options’ takes a prefix arg, which inhibits the 49 ;; deletion of the original (--help output) text. This can be 50 ;; useful if you don't trust (yet :-D) the conversion process. 51 ;; 52 ;; There are a couple TODO items, which point to situations that 53 ;; have not yet arisen in practice, but that might theoretically 54 ;; bother us in the future. 55 ;; 56 ;; * ‘TDM-recursive-help’ 57 ;; This command is intended for libeufin programs, specifically 58 ;; libeufin-sandbox, libeufin-nexus, and libeufin-cli. However, 59 ;; it should work with any Java program that uses clikt, or any 60 ;; Python program that uses click, for its command-line handling. 61 ;; 62 ;; You can obtain the --help output (recursively) in a buffer 63 ;; and write it to a file for further analysis / processing. 64 65 ;;; Code: 66 67 (require 'cl-lib) 68 69 (defun TDM-parse-option-triple () 70 "Return a triple formed by parsing option text at point. 71 The triple has the form (ARG SHORT LONG), where each element 72 can be either a string or ‘nil’. 73 74 Signal error if parsing fails. 75 Leave point after the end of the parsed text." 76 (cl-flet ((peer (regexp) 77 (re-search-forward regexp (line-end-position) t))) 78 (cond 79 ;; Full form: (ARG SHORT LONG). 80 ((peer " *-\\(.\\), --\\([^=\n]+\\)=\\(\\S +\\)") 81 (mapcar #'match-string-no-properties (list 3 1 2))) 82 ;; No argument: (nil SHORT LONG). 83 ((peer " *-\\(.\\), --\\(\\S +\\)") 84 (list nil 85 (match-string-no-properties 1) 86 (match-string-no-properties 2))) 87 ;; TODO: Handle other combinations. 88 (t 89 (error "Could not parse option text"))))) 90 91 (defun TDM-insert-options (arg short long) 92 "Insert formatted options, twice (on two lines). 93 The first is for the Synopsis section, the second for Description." 94 (unless (zerop (current-column)) 95 (open-line 1) 96 (forward-line 1)) 97 (cl-flet ((ins (short-space sep) 98 (cond 99 ;; Both available. 100 ((and short long) 101 (insert "**-" short "**") 102 (when arg 103 (insert short-space "*" arg "*")) 104 (insert sep) 105 (insert "**--" long (if arg "=" "") "**") 106 (when arg 107 (insert "\\ \\ *" arg "*"))) 108 ;; TODO: Handle other combinations. 109 (t 110 (error "Could not handle (%S %S %S)" 111 arg short long))))) 112 ;; First line. 113 (insert "[") 114 (ins " " " | ") 115 (insert "]\n") 116 ;; Second line. Leave point at its beginning. 117 (save-excursion 118 (ins " " " \\| ") 119 ;; Add a newline only if necessary. 120 (unless (eolp) 121 (insert "\n"))))) 122 123 (defun TDM-convert-options (&optional keep-orig) 124 "Grok the options at point and insert formatted ones. 125 If successful, delete the parsed options as well. 126 Prefix arg KEEP-ORIG means don't delete them." 127 (interactive "P") 128 (let* ((p (point)) 129 (triple (TDM-parse-option-triple)) 130 (q (point))) 131 (apply #'TDM-insert-options triple) 132 (unless keep-orig 133 (save-excursion 134 (delete-region p q))))) 135 136 (defun TDM-recursive-help (command) 137 "Call COMMAND --help and recurse on its subcommands. 138 Subcommands are identified by \"Commands:\" in column 0 139 in the output. 140 141 Collect the output in a new buffer *COMMAND --help*, 142 with one page per --help output." 143 (interactive "sCommand: ") 144 (let ((out (get-buffer-create (format "*%s --help*" command)))) 145 (with-current-buffer out 146 (erase-buffer)) 147 (cl-labels 148 ;; visit command 149 ((v (c) (with-temp-buffer 150 (apply #'call-process (car c) nil t nil 151 (append (cdr c) (list "--help"))) 152 (goto-char (point-min)) 153 (when (re-search-forward "^Commands:\n" nil t) 154 (while (looking-at "[ ][ ]\\(\\S +\\)") 155 (let ((sub (match-string 1))) 156 (v (append c (list sub)))) 157 (forward-line 1) 158 (while (looking-at "[ ][ ][ ]") 159 (forward-line 1)))) 160 (let ((s (buffer-string))) 161 (message "c: %s" c) 162 (with-current-buffer out 163 (goto-char (point-min)) 164 (insert "\f\n") 165 (insert "$ " (substring (format "%s" c) 1 -1) "\n") 166 (insert s "\n")))))) 167 (v (list command))) 168 (switch-to-buffer out))) 169 170 (provide 'TDM) 171 172 ;;; TDM.el ends here