Subject: [PATCH v3 1/3] doc: introduce a synopsis custom paragraph attribute

From: "Jean-Noël Avila via GitGitGadget" <[email-masked]>
Date: Sun, 11 Aug 2024 15:20:10 +0000

From: =?UTF-8?q?Jean-No=C3=ABl=20Avila?= <[email-masked]>

In order to follow the common manpage usage, the synopsis of the
commands needs to be heavily typeset. A first try was performed with
using native markup, but it turned out to make the document source
almost unreadable, difficult to write and prone to mistakes with
unwanted Asciidoc's role attributes.

In order to both simplify the writer's task and obtain a consistant
typesetting in the synopsis, a custom 'synopsis' paragraph type is
created and the backends of asciidoc and asciidoctor take in charge to
correctly add the required typesetting.

additionally, a 's' macro ('s' standing for synopsis) is introduced to
allow writers to freely apply automatic styling whereever required.

Signed-off-by: Jean-Noël Avila <[email-masked]>
---
 Documentation/asciidoc.conf             | 21 +++++++++++++++-
 Documentation/asciidoctor-extensions.rb | 33 +++++++++++++++++++++++++
 t/t0450-txt-doc-vs-help.sh              | 11 +++------
 3 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 60f76f43eda..04405453415 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -9,7 +9,7 @@
 
 [macros]
 (?su)[\\]?(?P<name>linkgit):(?P<target>\S*?)\[(?P<attrlist>.*?)\]=
-
+(?su)[\\]?(?P<name>s):(?P<target>\S*?)\["(?P<attrlist>.*?)"\]=
 [attributes]
 asterisk=&#42;
 plus=&#43;
@@ -28,6 +28,9 @@ ifdef::backend-docbook[]
 {0#<citerefentry>}
 {0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
 {0#</citerefentry>}
+
+[s-inlinemacro]
+{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<emphasis>\1</emphasis>', re.sub(r'([\[ |()>]|^|\]|&gt;)(\.?[-a-zA-Z0-9:+=~@,\/]+\.?)',r'\1<literal>\2</literal>', '{attrlist}'))}
 endif::backend-docbook[]
 
 ifdef::backend-docbook[]
@@ -56,4 +59,20 @@ ifdef::backend-xhtml11[]
 git-relative-html-prefix=
 [linkgit-inlinemacro]
 <a href="{git-relative-html-prefix}{target}.html">{target}{0?({0})}</a>
+
+[s-inlinemacro]
+{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<em>\1</em>', re.sub(r'([\[ |()>]|^|\]|&gt;)(\.?[-=a-zA-Z0-9:+,@]+\.?)',r'\1<code>\2</code>', '{attrlist}'))}
+
+endif::backend-xhtml11[]
+
+ifdef::backend-docbook[]
+ifdef::doctype-manpage[]
+[paradef-default]
+synopsis-style=template="verseparagraph",filter="sed -E 's!([\[ |()>]|^|\])(\.?[-=a-zA-Z0-9:+@]+\.?+)!\\1<literal>\\2</literal>!g;s!&lt;[-a-zA-Z0-9.]+&gt;!<emphasis>\\0</emphasis>!g'"
+endif::doctype-manpage[]
+endif::backend-docbook[]
+
+ifdef::backend-xhtml11[]
+[paradef-default]
+synopsis-style=template="verseparagraph",filter="sed -E 's!([\[ |()>]|^|\])(\.?[-=a-zA-Z0-9:+@]+\.?)!\\1<code>\\2</code>!g;s!&lt;[-a-zA-Z0-9.]+&gt;!<em>\\0</em>!g'"
 endif::backend-xhtml11[]
diff --git a/Documentation/asciidoctor-extensions.rb b/Documentation/asciidoctor-extensions.rb
index d906a008039..46cbbbbfd76 100644
--- a/Documentation/asciidoctor-extensions.rb
+++ b/Documentation/asciidoctor-extensions.rb
@@ -24,6 +24,21 @@ module Git
       end
     end
 
+    class SynopsisMacroProcessor < Asciidoctor::Extensions::InlineMacroProcessor
+      use_dsl
+
+      named :s
+      match(/s:\["(.+?)"\]/)
+
+      def process(parent, target, attrs)
+        l = target.gsub(/([\[\] |()]|^|&gt;)(\.?[-a-zA-Z0-9:+=~@,\/]+\.?)/, '\1{empty}`\2`{empty}')
+                  .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '__\\1__')
+                  .gsub(']', ']{empty}')
+
+        create_inline parent, :quoted, l, attributes: { 'subs' => :normal }
+      end
+    end
+
     class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor
       def process document, output
         if document.basebackend? 'docbook'
@@ -39,10 +54,28 @@ module Git
         output
       end
     end
+
+    class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor
+
+      use_dsl
+      named :synopsis
+      parse_content_as :simple
+
+      def process parent, reader, attrs
+        outlines = reader.lines.map do |l|
+          l.gsub(/([\[\] |()>]|^)([-a-zA-Z0-9:+=]+)/, '\1{empty}`\2`{empty}')
+           .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__')
+           .gsub(']', ']{empty}')
+        end
+        create_block parent, :verse, outlines, attrs
+      end
+    end
   end
 end
 
 Asciidoctor::Extensions.register do
   inline_macro Git::Documentation::LinkGitProcessor, :linkgit
+  inline_macro Git::Documentation::SynopsisMacroProcessor
+  block Git::Documentation::SynopsisBlock
   postprocessor Git::Documentation::DocumentPostProcessor
 end
diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh
index 69917d7b845..f99a69ae1b7 100755
--- a/t/t0450-txt-doc-vs-help.sh
+++ b/t/t0450-txt-doc-vs-help.sh
@@ -56,14 +56,11 @@ txt_to_synopsis () {
 	fi &&
 	b2t="$(builtin_to_txt "$builtin")" &&
 	sed -n \
-		-e '/^\[verse\]$/,/^$/ {
+		-E '/^\[(verse|synopsis)\]$/,/^$/ {
 			/^$/d;
-			/^\[verse\]$/d;
-			s/_//g;
-			s/++//g;
-			s/`//g;
-			s/{litdd}/--/g;
-			s/'\''\(git[ a-z-]*\)'\''/\1/g;
+			/^\[(verse|synopsis)\]$/d;
+			s/\{litdd\}/--/g;
+			s/'\''(git[ a-z-]*)'\''/\1/g;
 
 			p;
 		}' \
-- 
gitgitgadget