diff options
Diffstat (limited to 'devel')
-rwxr-xr-x | devel/man-to-mdwn.pl | 197 | ||||
-rwxr-xr-x | devel/news2wiki.pl | 102 |
2 files changed, 299 insertions, 0 deletions
diff --git a/devel/man-to-mdwn.pl b/devel/man-to-mdwn.pl new file mode 100755 index 00000000..4b59bd66 --- /dev/null +++ b/devel/man-to-mdwn.pl @@ -0,0 +1,197 @@ +#!/usr/bin/perl +# +# Author: Tomi Ollila +# License: same as notmuch +# +# This program is used to generate mdwn-formatted notmuch manual pages +# for notmuch wiki. Example run: +# +# $ ./devel/man-to-mdwn.pl man ../notmuch-wiki +# +# In case taken into more generic use, modify these comments and examples. + +use 5.8.1; +use strict; +use warnings; + +unless (@ARGV == 2) { + warn "\n$0 <source-directory> <destination-directory>\n\n"; + # Remove/edit this comment if this script is taken into generic use. + warn "Example: ./devel/man-to-mdwn.pl man ../notmuch-wiki\n\n"; + exit 1; +} + +die "'$ARGV[0]': no such source directory\n" unless -d $ARGV[0]; +die "'$ARGV[1]': no such destination directory\n" unless -d $ARGV[1]; + +#die "'manpages' exists\n" if -e 'manpages'; +#die "'manpages.mdwn' exists\n" if -e 'manpages.mdwn'; + +die "Expecting '$ARGV[1]/manpages' to exist.\n" . + "Please create it first or adjust <destination-directory>.\n" + unless -d $ARGV[1] . '/manpages'; + +my $ev = 0; +my %fhash; + +open P, '-|', 'find', $ARGV[0], qw/-name *.[0-9] -print/; +while (<P>) +{ + chomp; + next unless -f $_; # follows symlink. + $ev = 1, warn "'$_': no such file\n" unless -f $_; + my ($in, $on) = ($_, $_); + $on =~ s|.*/||; $on =~ tr/./-/; + my $f = $fhash{$on}; + $ev = 1, warn "'$in' collides with '$f' ($on.mdwn)\n" if defined $f; + $fhash{$on} = $in; +} +close P; + +#undef $ENV{'GROFF_NO_SGR'}; +#delete $ENV{'GROFF_NO_SGR'}; +$ENV{'GROFF_NO_SGR'} = '1'; +$ENV{'TERM'} = 'vt100'; # does this matter ? + +my %htmlqh = qw/& & < < > > ' ' " "/; +# do html quotation to $_[0] (which is an alias to the given arg) +sub htmlquote($) +{ + $_[0] =~ s/([&<>'"])/$htmlqh{$1}/ge; +} + +sub maymakelink($); +sub mayconvert($$); + +#warn keys %fhash, "\n"; + +while (my ($k, $v) = each %fhash) +{ + #next if -l $v; # skip symlinks here. -- not... references there may be. + + my @lines; + #open I, '-|', qw/groff -man -T utf8/, $v; + open I, '-|', qw/groff -man -T latin1/, $v; # this and GROFF_NO_SGR='1' + + my ($emptyline, $pre, $hl) = (0, 0, 'h1'); + while (<I>) { + if (/^\s*$/) { + $emptyline = 1; + next; + } + s/(?<=\S)\s{8,}.*//; # $hl = 'h1' if s/(?<=\S)\s{8,}.*//; + htmlquote $_; + s/[_&]\010&/&/g; + s/((?:_\010[^_])+)/<u>$1<\/u>/g; + s/_\010(.)/$1/g; + s/((?:.\010.)+)/<b>$1<\/b>/g; + s/.\010(.)/$1/g; + + if (/^\S/) { + $pre = 0, push @lines, "</pre>\n" if $pre; + s/<\/?b>//g; + chomp; + $_ = "\n<$hl>$_</$hl>\n"; + $hl = 'h2'; + $emptyline = 0; + } + elsif (/^\s\s\s\S/) { + $pre = 0, push @lines, "</pre>\n" if $pre; + s/(?:^\s+)?<\/?b>//g; + chomp; + $_ = "\n<h3> $_</h3>\n"; + $emptyline = 0; + } + else { + $pre = 1, push @lines, "<pre>\n" unless $pre; + $emptyline = 0, push @lines, "\n" if $emptyline; + } + push @lines, $_; + } + $lines[0] =~ s/^\n//; + $k = "$ARGV[1]/manpages/$k.mdwn"; + open O, '>', $k or die; + print STDOUT 'Writing ', "'$k'\n"; + select O; + my $pe = ''; + foreach (@lines) { + if ($pe) { + if (s/^(\s+)<b>([^<]+)<\/b>\((\d+)\)//) { + my $link = maymakelink "$pe-$2-$3"; + $link = maymakelink "$pe$2-$3" unless $link; + if ($link) { + print "<a href='$link'>$pe-</a>\n"; + print "$1<a href='$link'>$2</a>($3)"; + } + else { + print "<b>$pe-</b>\n"; + print "$1<b>$2</b>($3)"; + } + } else { + print "<b>$pe-</b>\n"; + } + $pe = ''; + } + s/<b>([^<]+)<\/b>\((\d+)\)/mayconvert($1, $2)/ge; + $pe = $1 if s/<b>([^<]+)-<\/b>\s*$//; + print $_; + } +} + +sub maymakelink($) +{ +# warn "$_[0]\n"; + return "../$_[0]/" if exists $fhash{$_[0]}; + return ''; +} + +sub mayconvert($$) +{ + my $f = "$_[0]-$_[1]"; +# warn "$f\n"; + return "<a href='../$f/'>$_[0]</a>($_[1])" if exists $fhash{$f}; + return "<b>$_[0]</b>($_[1])"; +} + +# Finally, make manpages.mdwn + +open O, '>', $ARGV[1] . '/manpages.mdwn' or die $!; +print STDOUT "Writing '$ARGV[1]/manpages.mdwn'\n"; +select O; +print "Manual page index\n"; +print "=================\n\n"; + +sub srt { my ($x, $y) = ($a, $b); $x =~ tr/./-/; $y =~ tr/./-/; $x cmp $y; } + +foreach (sort srt values %fhash) +{ + my $in = $_; + open I, '<', $in or die $!; + my $s; + while (<I>) { + if (/^\s*[.]TH\s+\S+\s+(\S+)/) { + $s = $1; + last; + } + } + while (<I>) { + last if /^\s*[.]SH NAME/ + } + my $line = ''; + while (<I>) { + tr/\\//d; + if (/\s*(\S+)\s+(.*)/) { + my $e = $2; + # Ignoring the NAME in file, get from file name instead. + #my $on = (-l $in)? readlink $in: $in; + my $on = $in; + $on =~ tr/./-/; $on =~ s|.*/||; + my $n = $in; $n =~ s|.*/||; $n =~ tr/./-/; $n =~ s/-[^-]+$//; + $line = "<a href='$on/'>$n</a>($s) $e\n"; + last; + } + } + die "No NAME in '$in'\n" unless $line; + print "* $line"; + #warn $line; +} diff --git a/devel/news2wiki.pl b/devel/news2wiki.pl new file mode 100755 index 00000000..8066ba7f --- /dev/null +++ b/devel/news2wiki.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl +# +# Author: Tomi Ollila +# License: same as notmuch + +# This program is used to split NEWS file to separate (mdwn) files +# for notmuch wiki. Example run: +# +# $ ./devel/news2wiki.pl NEWS ../notmuch-wiki/news +# +# In case taken into more generic use, modify these comments and examples. + +use strict; +use warnings; + +unless (@ARGV == 2) { + warn "\n$0 <source-file> <destination-directory>\n\n"; + warn "Example: ./devel/news2wiki.pl NEWS ../notmuch-wiki/news\n\n"; + exit 1; +} + +die "'$ARGV[0]': no such file\n" unless -f $ARGV[0]; +die "'$ARGV[1]': no such directory\n" unless -d $ARGV[1]; + +open I, '<', $ARGV[0] or die "Cannot open '$ARGV[0]': $!\n"; + +open O, '>', '/dev/null' or die $!; +my @emptylines = (); +my $cln; +print "\nWriting to $ARGV[1]:\n"; +while (<I>) +{ + warn "$ARGV[0]:$.: tab(s) in line!\n" if /\t/; + warn "$ARGV[0]:$.: trailing whitespace\n" if /\s\s$/; + # The date part in regex recognizes wip version dates like: (201x-xx-xx). + if (/^Notmuch\s+(\S+)\s+\((\w\w\w\w-\w\w-\w\w)\)\s*$/) { + # open O... autocloses previously opened file. + open O, '>', "$ARGV[1]/release-$1.mdwn" or die $!; + print "+ release-$1.mdwn...\n"; + print O "[[!meta date=\"$2\"]]\n\n"; + @emptylines = (); + } + + last if /^<!--\s*$/; # Local variables block at the end (as of now). + + # Buffer "trailing" empty lines -- dropped at end of file. + push(@emptylines, $_), next if s/^\s*$/\n/; + if (@emptylines) { + print O @emptylines; + @emptylines = (); + } + + # Convert '*' to '`*`' and "*" to "`*`" so that * is not considered + # as starting emphasis character there. We're a bit opportunistic + # there -- some single * does not cause problems and, on the other + # hand, this would not regognize already 'secured' *:s. + s/'[*]'/'`*`'/g; s/"[*]"/"`*`"/g; + + # Convert nonindented lines that aren't already headers or + # don't contain periods (.) or '!'s to level 4 header. + if ( /^[^\s-]/ ) { + my $tbc = ! /[.!]\s/; + chomp; + my @l = $_; + $cln = $.; + while (<I>) { + last if /^\s*$/; + #$cln = 0 if /^---/ or /^===/; # used for debugging. + $tbc = 0 if /[.!]\s/ or /^---/ or /^===/; + chomp; s/^\s+//; + push @l, $_; + } + if ($tbc) { + print O "### ", (join ' ', @l), "\n"; + } + else { + #print "$ARGV[0]:$cln: skip level 4 header conversion\n" if $cln; + print O (join "\n", @l), "\n"; + } + @emptylines = ( "\n" ); + next; + } + + # Markdown doc specifies that list item may have paragraphs if those + # are indented by 4 spaces (or a tab) from current list item marker + # indentation (paragraph meaning there is empty line in between). + # If there is empty line and next line is not indented 4 chars then + # that should end the above list. This doesn't happen in all markdown + # implementations. + # In our NEWS case this problem exists in release 0.6 documentation. + # It can be avoided by removing 2 leading spaces in lines that are not + # list items and requiring all that indents are 0, 2, and 4+ (to make + # regexp below work). + # Nested lists are supported but one needs to be more careful with + # markup there (as the hack below works only on first level). + + s/^[ ][ ]// unless /^[ ][ ](?:[\s*+-]|\d+\.)\s/; + + print O $_; +} +print "\ndone.\n"; +close O; |