# Script to be run whenever a section or an op is added or removed # from ops.markdown. Or just before every commit. It makes sure # that all sections and all entries are alphabetically sorted for # easier lookup, while the Miscellaneous section is always last. my @in = "ops.markdown".IO.slurp.lines(:!chomp); my $line; my @out; my %sections; class Section { has $.name; has $.label; has %.ops; method toc() { my $ops := %!ops.keys.sort.map( { my $name := .words.head; my $label := .subst(/ \s* '`' (\w+) '`' /, { "-$0" }, :g ); "[$name](#$label)" } ).join(" |\n"); "## [$!name](#$!label)\n\n$ops\n\n" } method doc() { my $doc := %!ops.sort(*.key).map( -> (:key($name), :value($text)) { "## $name\n$text" } ).join; "# $!name\n\n$doc" } } # until we get to the table of contents @out.push($line) until ($line := @in.shift).starts-with('## ['); # skip the table of contents Nil until ($line := @in.shift).starts-with('# '"' /); my $name := $line.match(/ 'a>' \s* <( .*/).chomp; my $section := %sections{$label} //= Section.new(:$label,:$name); # skip empty lines until first op Nil until ($line := @in.shift).starts-with('## '); # handle ops until end of file or next section repeat { my $op := $line.substr(3).chomp; my @lines; @lines.push($line) until !@in || ($line := @in.shift).starts-with('## ') || $line.starts-with('# comes last my @labels = %sections.keys.sort: { $_ eq 'misc' ?? 'zzz' !! $_ }; # push labels and then sections @out.push(%sections{$_}.toc) for @labels; @out.push(%sections{$_}.doc) for @labels; "ops.markdown".IO.spurt(@out.join);