--- /dev/null
+Return-Path: <too@guru-group.fi>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 55ED4431FAF\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Mar 2013 08:32:41 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
+ autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id M0cftwnvtSsH for <notmuch@notmuchmail.org>;\r
+ Fri, 8 Mar 2013 08:32:38 -0800 (PST)\r
+Received: from guru.guru-group.fi (guru.guru-group.fi [46.183.73.34])\r
+ by olra.theworths.org (Postfix) with ESMTP id CF9DF431FAE\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Mar 2013 08:32:37 -0800 (PST)\r
+Received: by guru.guru-group.fi (Postfix, from userid 501)\r
+ id A6BA1100650; Fri, 8 Mar 2013 18:32:25 +0200 (EET)\r
+From: Tomi Ollila <tomi.ollila@iki.fi>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 1/1] devel: add post-release tools news2wiki.pl and\r
+ man-to-mdwn.pl\r
+Date: Fri, 8 Mar 2013 18:32:23 +0200\r
+Message-Id: <1362760343-32620-1-git-send-email-tomi.ollila@iki.fi>\r
+X-Mailer: git-send-email 1.8.0\r
+Cc: tomi.ollila@iki.fi\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Fri, 08 Mar 2013 16:32:41 -0000\r
+\r
+After new notmuch release has been published the NEWS and manual\r
+pages have been updated using these 2 programs.\r
+\r
+Adding the tools to notmuch repository eases their use, adds more\r
+transparency to the "process" and gives more people chance to\r
+do the updates is one is unavailable to do it at the time being.\r
+---\r
+ devel/man-to-mdwn.pl | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ devel/news2wiki.pl | 102 ++++++++++++++++++++++++++\r
+ 2 files changed, 299 insertions(+)\r
+ create mode 100755 devel/man-to-mdwn.pl\r
+ create mode 100755 devel/news2wiki.pl\r
+\r
+diff --git a/devel/man-to-mdwn.pl b/devel/man-to-mdwn.pl\r
+new file mode 100755\r
+index 0000000..4b59bd6\r
+--- /dev/null\r
++++ b/devel/man-to-mdwn.pl\r
+@@ -0,0 +1,197 @@\r
++#!/usr/bin/perl\r
++#\r
++# Author: Tomi Ollila\r
++# License: same as notmuch\r
++#\r
++# This program is used to generate mdwn-formatted notmuch manual pages\r
++# for notmuch wiki. Example run:\r
++#\r
++# $ ./devel/man-to-mdwn.pl man ../notmuch-wiki\r
++#\r
++# In case taken into more generic use, modify these comments and examples.\r
++\r
++use 5.8.1;\r
++use strict;\r
++use warnings;\r
++\r
++unless (@ARGV == 2) {\r
++ warn "\n$0 <source-directory> <destination-directory>\n\n";\r
++ # Remove/edit this comment if this script is taken into generic use.\r
++ warn "Example: ./devel/man-to-mdwn.pl man ../notmuch-wiki\n\n";\r
++ exit 1;\r
++}\r
++\r
++die "'$ARGV[0]': no such source directory\n" unless -d $ARGV[0];\r
++die "'$ARGV[1]': no such destination directory\n" unless -d $ARGV[1];\r
++\r
++#die "'manpages' exists\n" if -e 'manpages';\r
++#die "'manpages.mdwn' exists\n" if -e 'manpages.mdwn';\r
++\r
++die "Expecting '$ARGV[1]/manpages' to exist.\n" .\r
++ "Please create it first or adjust <destination-directory>.\n"\r
++ unless -d $ARGV[1] . '/manpages';\r
++\r
++my $ev = 0;\r
++my %fhash;\r
++\r
++open P, '-|', 'find', $ARGV[0], qw/-name *.[0-9] -print/;\r
++while (<P>)\r
++{\r
++ chomp;\r
++ next unless -f $_; # follows symlink.\r
++ $ev = 1, warn "'$_': no such file\n" unless -f $_;\r
++ my ($in, $on) = ($_, $_);\r
++ $on =~ s|.*/||; $on =~ tr/./-/;\r
++ my $f = $fhash{$on};\r
++ $ev = 1, warn "'$in' collides with '$f' ($on.mdwn)\n" if defined $f;\r
++ $fhash{$on} = $in;\r
++}\r
++close P;\r
++\r
++#undef $ENV{'GROFF_NO_SGR'};\r
++#delete $ENV{'GROFF_NO_SGR'};\r
++$ENV{'GROFF_NO_SGR'} = '1';\r
++$ENV{'TERM'} = 'vt100'; # does this matter ?\r
++\r
++my %htmlqh = qw/& & < < > > ' ' " "/;\r
++# do html quotation to $_[0] (which is an alias to the given arg)\r
++sub htmlquote($)\r
++{\r
++ $_[0] =~ s/([&<>'"])/$htmlqh{$1}/ge;\r
++}\r
++\r
++sub maymakelink($);\r
++sub mayconvert($$);\r
++\r
++#warn keys %fhash, "\n";\r
++\r
++while (my ($k, $v) = each %fhash)\r
++{\r
++ #next if -l $v; # skip symlinks here. -- not... references there may be.\r
++\r
++ my @lines;\r
++ #open I, '-|', qw/groff -man -T utf8/, $v;\r
++ open I, '-|', qw/groff -man -T latin1/, $v; # this and GROFF_NO_SGR='1'\r
++\r
++ my ($emptyline, $pre, $hl) = (0, 0, 'h1');\r
++ while (<I>) {\r
++ if (/^\s*$/) {\r
++ $emptyline = 1;\r
++ next;\r
++ }\r
++ s/(?<=\S)\s{8,}.*//; # $hl = 'h1' if s/(?<=\S)\s{8,}.*//;\r
++ htmlquote $_;\r
++ s/[_&]\010&/&/g;\r
++ s/((?:_\010[^_])+)/<u>$1<\/u>/g;\r
++ s/_\010(.)/$1/g;\r
++ s/((?:.\010.)+)/<b>$1<\/b>/g;\r
++ s/.\010(.)/$1/g;\r
++\r
++ if (/^\S/) {\r
++ $pre = 0, push @lines, "</pre>\n" if $pre;\r
++ s/<\/?b>//g;\r
++ chomp;\r
++ $_ = "\n<$hl>$_</$hl>\n";\r
++ $hl = 'h2';\r
++ $emptyline = 0;\r
++ }\r
++ elsif (/^\s\s\s\S/) {\r
++ $pre = 0, push @lines, "</pre>\n" if $pre;\r
++ s/(?:^\s+)?<\/?b>//g;\r
++ chomp;\r
++ $_ = "\n<h3> $_</h3>\n";\r
++ $emptyline = 0;\r
++ }\r
++ else {\r
++ $pre = 1, push @lines, "<pre>\n" unless $pre;\r
++ $emptyline = 0, push @lines, "\n" if $emptyline;\r
++ }\r
++ push @lines, $_;\r
++ }\r
++ $lines[0] =~ s/^\n//;\r
++ $k = "$ARGV[1]/manpages/$k.mdwn";\r
++ open O, '>', $k or die;\r
++ print STDOUT 'Writing ', "'$k'\n";\r
++ select O;\r
++ my $pe = '';\r
++ foreach (@lines) {\r
++ if ($pe) {\r
++ if (s/^(\s+)<b>([^<]+)<\/b>\((\d+)\)//) {\r
++ my $link = maymakelink "$pe-$2-$3";\r
++ $link = maymakelink "$pe$2-$3" unless $link;\r
++ if ($link) {\r
++ print "<a href='$link'>$pe-</a>\n";\r
++ print "$1<a href='$link'>$2</a>($3)";\r
++ }\r
++ else {\r
++ print "<b>$pe-</b>\n";\r
++ print "$1<b>$2</b>($3)";\r
++ }\r
++ } else {\r
++ print "<b>$pe-</b>\n";\r
++ }\r
++ $pe = '';\r
++ }\r
++ s/<b>([^<]+)<\/b>\((\d+)\)/mayconvert($1, $2)/ge;\r
++ $pe = $1 if s/<b>([^<]+)-<\/b>\s*$//;\r
++ print $_;\r
++ }\r
++}\r
++\r
++sub maymakelink($)\r
++{\r
++# warn "$_[0]\n";\r
++ return "../$_[0]/" if exists $fhash{$_[0]};\r
++ return '';\r
++}\r
++\r
++sub mayconvert($$)\r
++{\r
++ my $f = "$_[0]-$_[1]";\r
++# warn "$f\n";\r
++ return "<a href='../$f/'>$_[0]</a>($_[1])" if exists $fhash{$f};\r
++ return "<b>$_[0]</b>($_[1])";\r
++}\r
++\r
++# Finally, make manpages.mdwn\r
++\r
++open O, '>', $ARGV[1] . '/manpages.mdwn' or die $!;\r
++print STDOUT "Writing '$ARGV[1]/manpages.mdwn'\n";\r
++select O;\r
++print "Manual page index\n";\r
++print "=================\n\n";\r
++\r
++sub srt { my ($x, $y) = ($a, $b); $x =~ tr/./-/; $y =~ tr/./-/; $x cmp $y; }\r
++\r
++foreach (sort srt values %fhash)\r
++{\r
++ my $in = $_;\r
++ open I, '<', $in or die $!;\r
++ my $s;\r
++ while (<I>) {\r
++ if (/^\s*[.]TH\s+\S+\s+(\S+)/) {\r
++ $s = $1;\r
++ last;\r
++ }\r
++ }\r
++ while (<I>) {\r
++ last if /^\s*[.]SH NAME/\r
++ }\r
++ my $line = '';\r
++ while (<I>) {\r
++ tr/\\//d;\r
++ if (/\s*(\S+)\s+(.*)/) {\r
++ my $e = $2;\r
++ # Ignoring the NAME in file, get from file name instead.\r
++ #my $on = (-l $in)? readlink $in: $in;\r
++ my $on = $in;\r
++ $on =~ tr/./-/; $on =~ s|.*/||;\r
++ my $n = $in; $n =~ s|.*/||; $n =~ tr/./-/; $n =~ s/-[^-]+$//;\r
++ $line = "<a href='$on/'>$n</a>($s) $e\n";\r
++ last;\r
++ }\r
++ }\r
++ die "No NAME in '$in'\n" unless $line;\r
++ print "* $line";\r
++ #warn $line;\r
++}\r
+diff --git a/devel/news2wiki.pl b/devel/news2wiki.pl\r
+new file mode 100755\r
+index 0000000..8066ba7\r
+--- /dev/null\r
++++ b/devel/news2wiki.pl\r
+@@ -0,0 +1,102 @@\r
++#!/usr/bin/perl\r
++#\r
++# Author: Tomi Ollila\r
++# License: same as notmuch\r
++\r
++# This program is used to split NEWS file to separate (mdwn) files\r
++# for notmuch wiki. Example run:\r
++#\r
++# $ ./devel/news2wiki.pl NEWS ../notmuch-wiki/news\r
++#\r
++# In case taken into more generic use, modify these comments and examples.\r
++\r
++use strict;\r
++use warnings;\r
++\r
++unless (@ARGV == 2) {\r
++ warn "\n$0 <source-file> <destination-directory>\n\n";\r
++ warn "Example: ./devel/news2wiki.pl NEWS ../notmuch-wiki/news\n\n";\r
++ exit 1;\r
++}\r
++\r
++die "'$ARGV[0]': no such file\n" unless -f $ARGV[0];\r
++die "'$ARGV[1]': no such directory\n" unless -d $ARGV[1];\r
++\r
++open I, '<', $ARGV[0] or die "Cannot open '$ARGV[0]': $!\n";\r
++\r
++open O, '>', '/dev/null' or die $!;\r
++my @emptylines = ();\r
++my $cln;\r
++print "\nWriting to $ARGV[1]:\n";\r
++while (<I>)\r
++{\r
++ warn "$ARGV[0]:$.: tab(s) in line!\n" if /\t/;\r
++ warn "$ARGV[0]:$.: trailing whitespace\n" if /\s\s$/;\r
++ # The date part in regex recognizes wip version dates like: (201x-xx-xx).\r
++ if (/^Notmuch\s+(\S+)\s+\((\w\w\w\w-\w\w-\w\w)\)\s*$/) {\r
++ # open O... autocloses previously opened file.\r
++ open O, '>', "$ARGV[1]/release-$1.mdwn" or die $!;\r
++ print "+ release-$1.mdwn...\n";\r
++ print O "[[!meta date=\"$2\"]]\n\n";\r
++ @emptylines = ();\r
++ }\r
++\r
++ last if /^<!--\s*$/; # Local variables block at the end (as of now).\r
++\r
++ # Buffer "trailing" empty lines -- dropped at end of file.\r
++ push(@emptylines, $_), next if s/^\s*$/\n/;\r
++ if (@emptylines) {\r
++ print O @emptylines;\r
++ @emptylines = ();\r
++ }\r
++\r
++ # Convert '*' to '`*`' and "*" to "`*`" so that * is not considered\r
++ # as starting emphasis character there. We're a bit opportunistic\r
++ # there -- some single * does not cause problems and, on the other\r
++ # hand, this would not regognize already 'secured' *:s.\r
++ s/'[*]'/'`*`'/g; s/"[*]"/"`*`"/g;\r
++\r
++ # Convert nonindented lines that aren't already headers or\r
++ # don't contain periods (.) or '!'s to level 4 header.\r
++ if ( /^[^\s-]/ ) {\r
++ my $tbc = ! /[.!]\s/;\r
++ chomp;\r
++ my @l = $_;\r
++ $cln = $.;\r
++ while (<I>) {\r
++ last if /^\s*$/;\r
++ #$cln = 0 if /^---/ or /^===/; # used for debugging.\r
++ $tbc = 0 if /[.!]\s/ or /^---/ or /^===/;\r
++ chomp; s/^\s+//;\r
++ push @l, $_;\r
++ }\r
++ if ($tbc) {\r
++ print O "### ", (join ' ', @l), "\n";\r
++ }\r
++ else {\r
++ #print "$ARGV[0]:$cln: skip level 4 header conversion\n" if $cln;\r
++ print O (join "\n", @l), "\n";\r
++ }\r
++ @emptylines = ( "\n" );\r
++ next;\r
++ }\r
++\r
++ # Markdown doc specifies that list item may have paragraphs if those\r
++ # are indented by 4 spaces (or a tab) from current list item marker\r
++ # indentation (paragraph meaning there is empty line in between).\r
++ # If there is empty line and next line is not indented 4 chars then\r
++ # that should end the above list. This doesn't happen in all markdown\r
++ # implementations.\r
++ # In our NEWS case this problem exists in release 0.6 documentation.\r
++ # It can be avoided by removing 2 leading spaces in lines that are not\r
++ # list items and requiring all that indents are 0, 2, and 4+ (to make\r
++ # regexp below work).\r
++ # Nested lists are supported but one needs to be more careful with\r
++ # markup there (as the hack below works only on first level).\r
++\r
++ s/^[ ][ ]// unless /^[ ][ ](?:[\s*+-]|\d+\.)\s/;\r
++\r
++ print O $_;\r
++}\r
++print "\ndone.\n";\r
++close O;\r
+-- \r
+1.8.0\r
+\r