From b44b23f79590d2bd9874985a253f247f33d03b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 30 Nov 2020 22:26:50 +0100 Subject: Add 'mh' script mh is a simple Perl script that translates troff-like source text into HTML. --- mh | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100755 mh (limited to 'mh') diff --git a/mh b/mh new file mode 100755 index 0000000..cae73bf --- /dev/null +++ b/mh @@ -0,0 +1,119 @@ +#!/usr/bin/perl + +use v5.12; +use warnings; + +use Text::ParseWords qw/quotewords/; + + +# 1 Definitions + + +# 1.1 Global program state + +my $empty = ''; # currently buffered empty lines +my $opel = ''; # currently opened element + + +# 1.2 Elements + +# 1.2.1 Block elements +my %blels = ( + Pp_0 => '

%

', + Qp_0 => '

%

', + Pr_0 => '
%
', + Sh_0 => '

%

', + Sh_1 => '%', + Ti_0 => '%', +); + +# 1.2.2 Inline elements +my %inels = ( + Au_1 => '', + Bd_0 => '\\$3\\$1\\$2', + br_0 => '
', + Cd_0 => '\\$3\\$1\\$2', + Cs_1 => '', + Em_0 => '\\$3\\$1\\$2', + Hy_0 => '\\$1', + Im_0 => '\\$2', + It_0 => '\\$3\\$1\\$2', + St_0 => '\\$3\\$1\\$2', + Tt_0 => '\\$3\\$1\\$2', + Ul_0 => '\\$3\\$1\\$2', +); + + +# 1.3 Subroutines + +# 1.3.1 Handle element request +sub request { + my ($el, $args) = @_; + my @argv = quotewords('\s+', 0, $args); + my $n = @argv; + my $elkey = "${el}_$n"; + + if (exists $blels{$elkey}) { + # Clear empty line buffer + $empty = ''; + + # Close currently open block element, open new + if (exists $blels{$opel}) { + print end($blels{$opel}) . "\n"; + $opel = ''; + } + $opel = $elkey; + + print interpol(start($blels{$elkey}), @argv) . "\n"; + } elsif (exists $inels{$elkey}) { + print interpol($inels{$elkey}, @argv) . "\n"; + } else { + print STDERR "Error: $el/$n not implemented\n"; + exit 1; + } +} + +# 1.3.2 Interpolate \$n parameters +sub interpol { + my $s = shift; + my $i = 1; + my $arg; + while ($arg = shift) { + $s =~ s/\\\$$i/$arg/g; + $i++; + } + return $s; +} + +# 1.3.3 Retrieve first portion of block element string +sub start { + return (split '%', shift)[0]; +} + +# 1.3.4 Retrieve second portion of block element string +sub end { + return (split '%', shift)[1]; +} + + +# 2 Program + + +# 2.1 Translate mh source text to HTML +while (<>) { + chomp; + if (/^\.([A-Za-z][a-z])\s*(.*)/) { + request($1, $2); + } elsif ($_ eq '') { + $empty .= "\n"; + } else { + print $empty; $empty = ''; + print "$_\n"; + } +} + +# 2.2 Close currently open block element +if (exists $blels{$opel}) { + print end($blels{$opel}) . "\n"; + $opel = ''; +} -- cgit v1.2.3