[PATCH 1/1] devel: add post-release tools news2wiki.pl and man-to-mdwn.pl
authorTomi Ollila <tomi.ollila@iki.fi>
Fri, 8 Mar 2013 16:32:23 +0000 (18:32 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:53:58 +0000 (09:53 -0800)
99/68fe87ccf7d13c03bb2a65146ddc89e11c0066 [new file with mode: 0644]

diff --git a/99/68fe87ccf7d13c03bb2a65146ddc89e11c0066 b/99/68fe87ccf7d13c03bb2a65146ddc89e11c0066
new file mode 100644 (file)
index 0000000..a638f32
--- /dev/null
@@ -0,0 +1,370 @@
+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/& &amp;   < &lt;   > &gt;   ' &apos;   " &quot;/;\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> &nbsp; $_</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