manned/lib/ManUtils/ManUtils.pm

67 lines
1.6 KiB
Perl

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;