From patchwork Thu Sep 5 21:52:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Cai via GitGitGadget X-Patchwork-Id: 13793009 Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 430F71AB6CE for ; Thu, 5 Sep 2024 21:52:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725573134; cv=none; b=MgTYk3inT+vWEexys/1Jlnyp8u526sDFJNE+a3WCcLB8JVr1IOD0jKFfMH4kSSAlknXF+uRxdUbGaKQiKRoUfEuqC2VYB1CFqI6CIrD4kmjySG3lrsADp0vSQAsdq2WlMgXLHibKdsv7zQQbDXzOS/xRfWOeOKHcJp6xGHeMglY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725573134; c=relaxed/simple; bh=u0Yz2E50corh61z1BCQAh8+JborLrHxepJIdUutzSdI=; h=Message-Id:In-Reply-To:References:From:Date:Subject:MIME-Version: Content-Type:To:Cc; b=G/iJTHaX6ZgvW8MxvmfxcO02sCqzMFAXIJARozRb0RaStDvA88riju0y6ChVQ7KAOMHQl9OBndUAuG2tiRDyWRENlpQEyKbWKSUAZe07YYSGGcKWkw+hZRo/E5YqT5H7DiVdhRsfaKpBIvvUCp+BW9EoN9bD0qxYcnIZhSKmoso= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Ctt2KidK; arc=none smtp.client-ip=209.85.208.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ctt2KidK" Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-5c3ca32971cso1574022a12.0 for ; Thu, 05 Sep 2024 14:52:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725573129; x=1726177929; darn=vger.kernel.org; h=cc:to:fcc:content-transfer-encoding:mime-version:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=eKE4YhmpLUaDI5y3z/lRnrf/0qaBLKWTZB4/HEcdLv8=; b=Ctt2KidKYLVXAtNVbVPWxpomKZtH/YRmsP7UxNfGk/o2Q7DscaRz9bfWMzSyAK0n0n qq06n1bQfu0rpuvEDF1E8YOcEkoSJxO0xXttbaA8baClSvVNr1FrQ8c0isoRT2o6Pxv5 O+NvXX+JV4gfLpUFbpsgVn6ULG2NASKJuUx7uTaBlflYq/snZ9PSaF+rSru6/X5WMd46 KaUJRmZz5uH9i1QzHbzNR7NlVGpS6OQMa+QxG+xT3h/Sagv7EsmyWHLipOvG89S7ajVD smOTmQhZJIngeR+2AKRzGKJuxshriL3/alIbyljiCGRW7sxGLdsKEhlDLJMk4Y/sF+Ut MKnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725573129; x=1726177929; h=cc:to:fcc:content-transfer-encoding:mime-version:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eKE4YhmpLUaDI5y3z/lRnrf/0qaBLKWTZB4/HEcdLv8=; b=iKHAMTsWb5JLNi9r9VWll8G8wI6Sg05ozD8VW76eHQgBBiJpdwg25G7xZqwHcXHVLq 5TTrfCnNjnMSp1/Co/2A5PXGJ1aQNkWMeRyxW2sgtvAQtEQ6tJ0TWCK09oaFBHrMQ2xP 3nqopF38wQ2ZakoTGzV/FcCMuHCy6KTqTlR5PU2oInOF7HhF77iA3nXl46l08gwqjFoa IEzuat+EyW/l7P+xQH9jn67xSNvDM3vrOd5O4LAmgykrfO0N34uYguFW/vGdkqZwyUkU Ar/RjBpJbiIBNydPw28HYiqMqnwCKLepLp7TuAQoEeWJo90/0TnhK+zrpN8mhNogZEVr 9ufw== X-Gm-Message-State: AOJu0YwTOeaY4ybc8LoElyhM6fpqNHNzqPJbGJB4RkngPqG6Jano+8f8 Eppa95coODybI5x3UrLSzapHEVPnyatY/quKoYLF+UZ9Xjgi/QtXa83HoQ== X-Google-Smtp-Source: AGHT+IHt596s3GXf7z3xHFuAPtHkL3goCBGSmdV52b69eLey05uP2GG/f8D2XDUDctv43ygSnDv2oQ== X-Received: by 2002:a17:906:c156:b0:a86:789c:2d07 with SMTP id a640c23a62f3a-a8a885be5bemr36904466b.4.1725573127935; Thu, 05 Sep 2024 14:52:07 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8a6236d02bsm186499366b.109.2024.09.05.14.52.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Sep 2024 14:52:07 -0700 (PDT) Message-Id: In-Reply-To: References: From: " =?utf-8?q?Jean-No=C3=ABl?= Avila via GitGitGadget" Date: Thu, 05 Sep 2024 21:52:03 +0000 Subject: [PATCH v4 0/3] doc: introducing synopsis para Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Fcc: Sent To: git@vger.kernel.org Cc: Eric Sunshine , =?utf-8?q?Jean-No=C3=ABl?= Avila In the continuation of the simplification of manpage editing, the synopsis processing that was developed for synopsis paragraph style is also applied to all inline backquoted texts. Refining the magic regexp took more time than expected, but this one should really enhance writers'experience. I had to fight a bit more with asciidoctor, due to discrepancies between version 2.0 on my laptop and the 1.5.6 used by Github actions. The git-init and git-clone manpages are converted to this new system. Changes since V1: * switch to sed for asciidoc filter and refine the regex for support under macOS Changes since V2: * introduce the s macro to freely apply synopsis styling wherever needed, without formatting hassle. Changes since V3: * replace s macro by direct processing of literal text at the level of output processors. Jean-Noël Avila (3): doc: introduce a synopsis typesetting doc: update the guidelines to reflect the current formatting rules doc: apply synopsis simplification on git-clone and git-init Documentation/CodingGuidelines | 58 +++++++++-------- Documentation/asciidoc.conf | 20 ++++++ Documentation/asciidoctor-extensions.rb | 87 +++++++++++++++++++++++++ Documentation/git-clone.txt | 78 +++++++++++----------- Documentation/git-init.txt | 35 +++++----- Documentation/urls.txt | 26 ++++---- ci/install-dependencies.sh | 1 + t/t0450-txt-doc-vs-help.sh | 11 ++-- 8 files changed, 209 insertions(+), 107 deletions(-) base-commit: 2e7b89e038c0c888acf61f1b4ee5a43d4dd5e94c Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1766%2Fjnavila%2Fdoc_synopsis_para-v4 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1766/jnavila/doc_synopsis_para-v4 Pull-Request: https://github.com/gitgitgadget/git/pull/1766 Range-diff vs v3: 1: 0d7c1dd8f26 ! 1: c09968d7ccb doc: introduce a synopsis custom paragraph attribute @@ Metadata Author: Jean-Noël Avila ## Commit message ## - doc: introduce a synopsis custom paragraph attribute + 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 @@ Commit message 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. + 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 ## Documentation/asciidoc.conf ## -@@ - - [macros] - (?su)[\\]?(?Plinkgit):(?P\S*?)\[(?P.*?)\]= -- -+(?su)[\\]?(?Ps):(?P\S*?)\["(?P.*?)"\]= - [attributes] - asterisk=* - plus=+ @@ Documentation/asciidoc.conf: ifdef::backend-docbook[] {0#} {0#{target}{0}} {0#} + -+[s-inlinemacro] -+{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[ |()>]|^|\]|>)(\.?[-a-zA-Z0-9:+=~@,\/]+\.?)',r'\1\2', '{attrlist}'))} ++[literal-inlinemacro] ++{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} ++ endif::backend-docbook[] ifdef::backend-docbook[] @@ Documentation/asciidoc.conf: ifdef::backend-xhtml11[] [linkgit-inlinemacro] {target}{0?({0})} + -+[s-inlinemacro] -+{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[ |()>]|^|\]|>)(\.?[-=a-zA-Z0-9:+,@]+\.?)',r'\1\2', '{attrlist}'))} ++[literal-inlinemacro] ++{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'\1', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1\2', re.sub(r'(\.\.\.?)([^\]$.])', r'\1\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} + +endif::backend-xhtml11[] + +ifdef::backend-docbook[] +ifdef::doctype-manpage[] +[paradef-default] -+synopsis-style=template="verseparagraph",filter="sed -E 's!([\[ |()>]|^|\])(\.?[-=a-zA-Z0-9:+@]+\.?+)!\\1\\2!g;s!<[-a-zA-Z0-9.]+>!\\0!g'" ++synopsis-style=template="verseparagraph",filter="sed -E 's!([\[ |()>]|^|\])(\.?[-=a-zA-Z0-9:+@,\/_^\$]+\.?+)!\\1\\2!g;s!<[-a-zA-Z0-9.]+>!\\0!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\\2!g;s!<[-a-zA-Z0-9.]+>!\\0!g'" ++synopsis-style=template="verseparagraph",filter="sed -E 's!([\[ |()>]|^|\])(\.?[-=a-zA-Z0-9:+@,\/_^\$]+\.?)!\\1\\2!g;s!<[-a-zA-Z0-9.]+>!\\0!g'" endif::backend-xhtml11[] ## Documentation/asciidoctor-extensions.rb ## -@@ Documentation/asciidoctor-extensions.rb: module Git - end - end +@@ + require 'asciidoctor' + require 'asciidoctor/extensions' ++require 'asciidoctor/converter/docbook5' ++require 'asciidoctor/converter/html5' -+ class SynopsisMacroProcessor < Asciidoctor::Extensions::InlineMacroProcessor -+ use_dsl -+ -+ named :s -+ match(/s:\["(.+?)"\]/) -+ -+ def process(parent, target, attrs) -+ l = target.gsub(/([\[\] |()]|^|>)(\.?[-a-zA-Z0-9:+=~@,\/]+\.?)/, '\1{empty}`\2`{empty}') -+ .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\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' + module Git + module Documentation @@ Documentation/asciidoctor-extensions.rb: module Git output end @@ Documentation/asciidoctor-extensions.rb: module Git + + def process parent, reader, attrs + outlines = reader.lines.map do |l| -+ l.gsub(/([\[\] |()>]|^)([-a-zA-Z0-9:+=]+)/, '\1{empty}`\2`{empty}') ++ l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2') ++ .gsub(%r{([\[\] |()>]|^)([-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 ++ ++ class GitDBConverter < Asciidoctor::Converter::DocBook5Converter ++ ++ extend Asciidoctor::Converter::Config ++ register_for 'docbook5' ++ ++ def convert_inline_quoted node ++ if (type = node.type) == :asciimath ++ # NOTE fop requires jeuclid to process mathml markup ++ asciimath_available? ? %(#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}) : %() ++ elsif type == :latexmath ++ # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math ++ %() ++ elsif type == :monospaced ++ node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') ++ .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') ++ .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') ++ else ++ open, close, supports_phrase = QUOTE_TAGS[type] ++ text = node.text ++ if node.role ++ if supports_phrase ++ quoted_text = %(#{open}#{text}#{close}) ++ else ++ quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close}) ++ end ++ else ++ quoted_text = %(#{open}#{text}#{close}) ++ end ++ node.id ? %(#{quoted_text}) : quoted_text ++ end ++ end ++ end ++ ++ # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis ++ class GitHTMLConverter < Asciidoctor::Converter::Html5Converter ++ ++ extend Asciidoctor::Converter::Config ++ register_for 'html5' ++ ++ def convert_inline_quoted node ++ if node.type == :monospaced ++ node.text.gsub(/(\.\.\.?)([^\]$.])/, '\1\2') ++ .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1\2') ++ .gsub(/(<[-a-zA-Z0-9.]+>)/, '\1') ++ ++ else ++ open, close, tag = QUOTE_TAGS[node.type] ++ if node.id ++ class_attr = node.role ? %( class="#{node.role}") : '' ++ if tag ++ %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close}) ++ else ++ %(#{open}#{node.text}#{close}) ++ end ++ elsif node.role ++ if tag ++ %(#{open.chop} class="#{node.role}">#{node.text}#{close}) ++ else ++ %(#{open}#{node.text}#{close}) ++ end ++ else ++ %(#{open}#{node.text}#{close}) ++ end ++ end ++ 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 + ## ci/install-dependencies.sh ## +@@ ci/install-dependencies.sh: Documentation) + + test -n "$ALREADY_HAVE_ASCIIDOCTOR" || + sudo gem install --version 1.5.8 asciidoctor ++ sudo gem install concurrent-ruby + ;; + esac + + ## t/t0450-txt-doc-vs-help.sh ## @@ t/t0450-txt-doc-vs-help.sh: txt_to_synopsis () { fi && 2: 92f3121cf4e ! 2: c48649ccd63 doc: update the guidelines to reflect the current formatting rules @@ Commit message ## Documentation/CodingGuidelines ## @@ Documentation/CodingGuidelines: Markup: + __ + __ + +- A placeholder is not enclosed in backticks, as it is not a literal. +- + When needed, use a distinctive identifier for placeholders, usually + made of a qualification and a type: + __ __ - When literal and placeholders are mixed, each markup is applied for +- When literal and placeholders are mixed, each markup is applied for - each sub-entity. If they are stuck, a special markup, called - unconstrained formatting is required. - Unconstrained formating for placeholders is ____ @@ Documentation/CodingGuidelines: Markup: - ++--sort=++____ - ____++/.git++ - ++remote.++____++.mirror++ -- ++ Git's Asciidoc processor has been tailored to treat backticked text ++ as complex synopsis. When literal and placeholders are mixed, you can ++ use the backtick notation which will take care of correctly typesetting ++ the content. ++ `--jobs ` ++ `--sort=` ++ `/.git` ++ `remote..mirror` ++ `ssh://[@][:]/` + - caveat: ++ unconstrained format is not verbatim and may expand - content. Use Asciidoc escapes inside them. -+ each sub-entity. If the formatting is becoming too hairy, you can use the -+ s:["foo"] formatting macro and let it format the groups for you. -+ `--jobs` __ or s:["--jobs "] -+ s:["--sort= -+ s:["/.git"] -+ s:["remote..mirror"] -+ s:["ssh://[@][:]/"] -+ -+Note that the double-quotes are required by the macro. ++As a side effect, backquoted placeholders are correctly typeset, but ++this style is not recommended. Synopsis Syntax 3: 02406b91894 ! 3: 719188da711 doc: apply synopsis simplification on git-clone and git-init @@ Documentation/git-clone.txt: git-clone - Clone a repository into a new directory DESCRIPTION ----------- +@@ Documentation/git-clone.txt: OPTIONS + to save space when possible. + + + If the repository is specified as a local path (e.g., `/path/to/repo`), +-this is the default, and --local is essentially a no-op. If the ++this is the default, and `--local` is essentially a no-op. If the + repository is specified as a URL, then this flag is ignored (and we + never use the local optimizations). Specifying `--no-local` will + override the default when `/path/to/repo` is given, using the regular @@ Documentation/git-clone.txt: prevent the unintentional copying of files by dereferencing the symbolic links. + *NOTE*: this operation can race with concurrent modification to the -source repository, similar to running `cp -r src dst` while modifying -`src`. -+source repository, similar to running s:["cp -r "] while modifying ++source repository, similar to running `cp -r ` while modifying +__. `--no-hardlinks`:: @@ Documentation/git-clone.txt: If you want to break the dependency of a repository objects from the source repository into a pack in the cloned repository. -`--reference`[`-if-able`] __:: -+s:["--reference[-if-able] "]:: ++`--reference[-if-able] `:: If the reference __ is on the local machine, automatically setup `.git/objects/info/alternates` to obtain objects from the reference __. Using @@ Documentation/git-clone.txt: objects from the source repository into a pack in t standard error stream is not directed to a terminal. -++--server-option=++__