doc: Adds xml fixing script. (see previous and next commits)

This script is used to automatically fix issues within xml documentation
files.

The script is *for now* intended to be used ad-hoc, and the commits to
be examined.

A future discussion will define whether:

  * This commit and scripts are kept.
  * The script is extended for common use.

The biggest issue right now with the script is that it *could* in theory
destroy a valid space-less varlistentry.

The script could, in practical use, be changed and extended to normalize
some parts of the XML files, mainly:

  * A common quoting style for attributes
  * Fix-up some weird formatting automatically that xmlformat doesn't
    catch
This commit is contained in:
Samuel Dionne-Riel 2018-05-31 20:26:27 -04:00
parent aa59151c21
commit bc0421c4cf
5 changed files with 136 additions and 2 deletions

View file

@ -12,6 +12,11 @@ format:
find . -iname '*.xml' -type f -print0 | xargs -0 -I{} -n1 \
xmlformat --config-file "$$XMLFORMAT_CONFIG" -i {}
.PHONY: fix-misc-xml
fix-misc-xml:
find . -iname '*.xml' -type f \
-exec ../nixos/doc/varlistentry-fixer.rb {} ';'
.PHONY: clean
clean:
rm -f ${MD_TARGETS} .version manual-full.xml

View file

@ -1,5 +1,5 @@
{ pkgs ? import ../. {} }:
(import ./default.nix).overrideAttrs (x: {
buildInputs = x.buildInputs ++ [ pkgs.xmloscopy ];
buildInputs = x.buildInputs ++ [ pkgs.xmloscopy pkgs.ruby ];
})

View file

@ -14,6 +14,11 @@ format:
find . -iname '*.xml' -type f -print0 | xargs -0 -I{} -n1 \
xmlformat --config-file "../xmlformat.conf" -i {}
.PHONY: fix-misc-xml
fix-misc-xml:
find . -iname '*.xml' -type f \
-exec ../varlistentry-fixer.rb {} ';'
.PHONY: clean
clean:
rm -f manual-combined.xml generated

View file

@ -4,5 +4,5 @@ in
pkgs.mkShell {
name = "nixos-manual";
buildInputs = with pkgs; [ xmlformat jing xmloscopy ];
buildInputs = with pkgs; [ xmlformat jing xmloscopy ruby ];
}

124
nixos/doc/varlistentry-fixer.rb Executable file
View file

@ -0,0 +1,124 @@
#!/usr/bin/env ruby
# This script is written intended as a living, evolving tooling
# to fix oopsies within the docbook documentation.
#
# This is *not* a formatter. It, instead, handles some known cases
# where something bad happened, and fixing it manually is tedious.
#
# Read the code to see the different cases it handles.
#
# ALWAYS `make format` after fixing with this!
# ALWAYS read the changes, this tool isn't yet proven to be always right.
require "rexml/document"
include REXML
if ARGV.length < 1 then
$stderr.puts "Needs a filename."
exit 1
end
filename = ARGV.shift
doc = Document.new(File.open(filename))
$touched = false
# Fixing varnames having a sibling element without spacing.
# This is to fix an initial `xmlformat` issue where `term`
# would mangle as spaces.
#
# <varlistentry>
# <term><varname>types.separatedString</varname><replaceable>sep</replaceable> <----
# </term>
# ...
#
# Generates: types.separatedStringsep
# ^^^^
#
# <varlistentry xml:id='fun-makeWrapper'>
# <term>
# <function>makeWrapper</function><replaceable>executable</replaceable><replaceable>wrapperfile</replaceable><replaceable>args</replaceable> <----
# </term>
#
# Generates: makeWrapperexecutablewrapperfileargs
# ^^^^ ^^^^ ^^ ^^
#
# <term>
# <option>--option</option><replaceable>name</replaceable><replaceable>value</replaceable> <-----
# </term>
#
# Generates: --optionnamevalue
# ^^ ^^
doc.elements.each("//varlistentry/term") do |term|
["varname", "function", "option", "replaceable"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
# <cmdsynopsis>
# <command>nixos-option</command>
# <arg>
# <option>-I</option><replaceable>path</replaceable> <------
# </arg>
#
# Generates: -Ipath
# ^^
doc.elements.each("//cmdsynopsis/arg") do |term|
["option", "replaceable"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
# <cmdsynopsis>
# <arg>
# <group choice='req'>
# <arg choice='plain'>
# <option>--profile-name</option>
# </arg>
#
# <arg choice='plain'>
# <option>-p</option>
# </arg>
# </group><replaceable>name</replaceable> <----
# </arg>
#
# Generates: [{--profile-name | -p }name]
# ^^^^
doc.elements.each("//cmdsynopsis/arg") do |term|
["group"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
if $touched then
doc.context[:attribute_quote] = :quote
doc.write(output: File.open(filename, "w"))
end