package ManUtils; use strict; use warnings; use AE; use AnyEvent::Util; use Encode 'decode_utf8', 'encode_utf8'; our $VERSION = '0.01'; require XSLoader; XSLoader::load('ManUtils', $VERSION); # Usage: $cv = fmt($input, \$output, \@errors) # $cv = AnyEvent condition variable, fired when done. # $input = UTF-8 encoded manual page source # $output = variable that will hold the output when done # @errors = list of warnings/errors while running groff sub fmt { my($input, $output, $errors) = @_; $$output = ''; @$errors = (); my @cmd = 'groff'; push @cmd, '-t' if $input =~ /^\.TS/m; push @cmd, '-e' if $input =~ /^\.EQ/m; # $MANWIDTH works by using the following groff options: -rLL=100n -rLT=100n push @cmd, qw/-mandoc -Tutf8 -DUTF-8 -P-c -rLL=80n -rLT=80n -/; $input = # Disable hyphenation, since that screws up man page references. :-( ".hy 0\n.de hy\n..\n" # Emulate man-db's --nj option .".na\n.de ad\n..\n" # Unbreak some quotes, there's plenty of man pages that ("incorrectly") use these for code samples. .".char ` \\`\n" .".char ' \\[aq]\n" .encode_utf8($input); my $groff = run_cmd \@cmd, '<' => \$input, '>' => $output, '2>' => sub { if($_[0]) { chomp(my $e = $_[0]); push @$errors, "groff: $e" } }; my $cv = AE::cv; $groff->cb(sub { decode_utf8 $$output; $$output =~ s/[\t\s\r\n]+$//; $cv->send; }); $cv } # Blocking version of fmt(). Returns the formatted man page, errors are # forwarded to warn(). sub fmt_block { my $c = shift; my $cv = fmt $c, \my $out, \my @err; $cv->recv; #warn "$_\n" for @err; $out; } 1;