Skip to content

Commit 974cdca

Browse files
jnavilagitster
authored andcommitted
doc: introduce a synopsis typesetting
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 processor for backticked text are modified. The backends of asciidoc and asciidoctor take in charge to correctly add the required typesetting. Signed-off-by: Jean-Noël Avila <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ad57f14 commit 974cdca

File tree

4 files changed

+112
-7
lines changed

4 files changed

+112
-7
lines changed

Documentation/asciidoc.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ ifdef::backend-docbook[]
2828
{0#<citerefentry>}
2929
{0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
3030
{0#</citerefentry>}
31+
32+
[literal-inlinemacro]
33+
{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<emphasis>\1</emphasis>', re.sub(r'([\[\s|()>]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<literal>\2</literal>', re.sub(r'(\.\.\.?)([^\]$.])', r'<literal>\1</literal>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))}
34+
3135
endif::backend-docbook[]
3236

3337
ifdef::backend-docbook[]
@@ -56,4 +60,20 @@ ifdef::backend-xhtml11[]
5660
git-relative-html-prefix=
5761
[linkgit-inlinemacro]
5862
<a href="{git-relative-html-prefix}{target}.html">{target}{0?({0})}</a>
63+
64+
[literal-inlinemacro]
65+
{eval:re.sub(r'(&lt;[-a-zA-Z0-9.]+&gt;)', r'<em>\1</em>', re.sub(r'([\[\s|()>]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<code>\2</code>', re.sub(r'(\.\.\.?)([^\]$.])', r'<code>\1</code>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))}
66+
67+
endif::backend-xhtml11[]
68+
69+
ifdef::backend-docbook[]
70+
ifdef::doctype-manpage[]
71+
[paradef-default]
72+
synopsis-style=template="verseparagraph",filter="sed 's!&#8230;\\(\\]\\|$\\)!<phrase>\\0</phrase>!g;s!\\([\\[ |()]\\|^\\|\\]\\|&gt;\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|&#8230;\\)!\\1<literal>\\2</literal>!g;s!&lt;[-a-zA-Z0-9.]\\+&gt;!<emphasis>\\0</emphasis>!g'"
73+
endif::doctype-manpage[]
74+
endif::backend-docbook[]
75+
76+
ifdef::backend-xhtml11[]
77+
[paradef-default]
78+
synopsis-style=template="verseparagraph",filter="sed 's!&#8230;\\(\\]\\|$\\)!<span>\\0</span>!g;s!\\([\\[ |()]\\|^\\|\\]\\|&gt;\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|&#8230;\\)!\\1<code>\\2</code>!g;s!&lt;[-a-zA-Z0-9.]\\+&gt;!<em>\\0</em>!g'"
5979
endif::backend-xhtml11[]

Documentation/asciidoctor-extensions.rb

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
require 'asciidoctor'
22
require 'asciidoctor/extensions'
3+
require 'asciidoctor/converter/docbook5'
4+
require 'asciidoctor/converter/html5'
35

46
module Git
57
module Documentation
@@ -39,10 +41,95 @@ def process document, output
3941
output
4042
end
4143
end
44+
45+
class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor
46+
47+
use_dsl
48+
named :synopsis
49+
parse_content_as :simple
50+
51+
def process parent, reader, attrs
52+
outlines = reader.lines.map do |l|
53+
l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2')
54+
.gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}')
55+
.gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__')
56+
.gsub(']', ']{empty}')
57+
end
58+
create_block parent, :verse, outlines, attrs
59+
end
60+
end
61+
62+
class GitDBConverter < Asciidoctor::Converter::DocBook5Converter
63+
64+
extend Asciidoctor::Converter::Config
65+
register_for 'docbook5'
66+
67+
def convert_inline_quoted node
68+
if (type = node.type) == :asciimath
69+
# NOTE fop requires jeuclid to process mathml markup
70+
asciimath_available? ? %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>) : %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>)
71+
elsif type == :latexmath
72+
# unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
73+
%(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
74+
elsif type == :monospaced
75+
node.text.gsub(/(\.\.\.?)([^\]$.])/, '<literal>\1</literal>\2')
76+
.gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>')
77+
.gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<emphasis>\1</emphasis>')
78+
else
79+
open, close, supports_phrase = QUOTE_TAGS[type]
80+
text = node.text
81+
if node.role
82+
if supports_phrase
83+
quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
84+
else
85+
quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
86+
end
87+
else
88+
quoted_text = %(#{open}#{text}#{close})
89+
end
90+
node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
91+
end
92+
end
93+
end
94+
95+
# register a html5 converter that takes in charge to convert monospaced text into Git style synopsis
96+
class GitHTMLConverter < Asciidoctor::Converter::Html5Converter
97+
98+
extend Asciidoctor::Converter::Config
99+
register_for 'html5'
100+
101+
def convert_inline_quoted node
102+
if node.type == :monospaced
103+
node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2')
104+
.gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>')
105+
.gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<em>\1</em>')
106+
107+
else
108+
open, close, tag = QUOTE_TAGS[node.type]
109+
if node.id
110+
class_attr = node.role ? %( class="#{node.role}") : ''
111+
if tag
112+
%(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
113+
else
114+
%(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
115+
end
116+
elsif node.role
117+
if tag
118+
%(#{open.chop} class="#{node.role}">#{node.text}#{close})
119+
else
120+
%(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
121+
end
122+
else
123+
%(#{open}#{node.text}#{close})
124+
end
125+
end
126+
end
127+
end
42128
end
43129
end
44130

45131
Asciidoctor::Extensions.register do
46132
inline_macro Git::Documentation::LinkGitProcessor, :linkgit
133+
block Git::Documentation::SynopsisBlock
47134
postprocessor Git::Documentation::DocumentPostProcessor
48135
end

ci/install-dependencies.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Documentation)
103103

104104
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
105105
sudo gem install --version 1.5.8 asciidoctor
106+
sudo gem install concurrent-ruby
106107
;;
107108
esac
108109

t/t0450-txt-doc-vs-help.sh

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,11 @@ txt_to_synopsis () {
5656
fi &&
5757
b2t="$(builtin_to_txt "$builtin")" &&
5858
sed -n \
59-
-e '/^\[verse\]$/,/^$/ {
59+
-E '/^\[(verse|synopsis)\]$/,/^$/ {
6060
/^$/d;
61-
/^\[verse\]$/d;
62-
s/_//g;
63-
s/++//g;
64-
s/`//g;
65-
s/{litdd}/--/g;
66-
s/'\''\(git[ a-z-]*\)'\''/\1/g;
61+
/^\[(verse|synopsis)\]$/d;
62+
s/\{litdd\}/--/g;
63+
s/'\''(git[ a-z-]*)'\''/\1/g;
6764
6865
p;
6966
}' \

0 commit comments

Comments
 (0)