Home | History | Annotate | Line # | Download | only in 0-old
mdoc2man revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  riz #!/usr/bin/perl
      2  1.1.1.1.2.2  riz 
      3  1.1.1.1.2.2  riz ### ToDo
      4  1.1.1.1.2.2  riz # Properly implement -columns in the "my %lists" definition...
      5  1.1.1.1.2.2  riz #
      6  1.1.1.1.2.2  riz # .Xr requires at least 1 arg, the code here expects at least 2
      7  1.1.1.1.2.2  riz ###
      8  1.1.1.1.2.2  riz 
      9  1.1.1.1.2.2  riz package mdoc2man;
     10  1.1.1.1.2.2  riz use strict;
     11  1.1.1.1.2.2  riz use warnings;
     12  1.1.1.1.2.2  riz use File::Basename;
     13  1.1.1.1.2.2  riz use lib dirname(__FILE__);
     14  1.1.1.1.2.2  riz use Mdoc qw(hs ns pp mapwords son soff stoggle gen_encloser);
     15  1.1.1.1.2.2  riz 
     16  1.1.1.1.2.2  riz ########
     17  1.1.1.1.2.2  riz ## Basic
     18  1.1.1.1.2.2  riz ########
     19  1.1.1.1.2.2  riz 
     20  1.1.1.1.2.2  riz Mdoc::def_macro( '.Sh', sub { '.SH', hs, @_ }, raw => 1);
     21  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ss', sub { '.SS', hs, @_ }, raw => 1);
     22  1.1.1.1.2.2  riz Mdoc::def_macro( '.Pp', sub { ".sp \\n(Ppu\n.ne 2\n" } );
     23  1.1.1.1.2.2  riz Mdoc::def_macro( '.Nd', sub { "\\- @_" } );
     24  1.1.1.1.2.2  riz 
     25  1.1.1.1.2.2  riz # Macros that enclose things
     26  1.1.1.1.2.2  riz Mdoc::def_macro( '.Brq', gen_encloser(qw({ }))          , greedy => 1 );
     27  1.1.1.1.2.2  riz Mdoc::def_macro( '.Op' , gen_encloser(qw([ ]))          , greedy => 1 );
     28  1.1.1.1.2.2  riz Mdoc::def_macro( '.Qq' , gen_encloser(qw(" "))          , greedy => 1 );
     29  1.1.1.1.2.2  riz Mdoc::def_macro( '.Dq' , gen_encloser(qw(\*[Lq] \*[Rq])), greedy => 1 );
     30  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ql' , gen_encloser(qw(\[oq] \[cq]))  , greedy => 1 );
     31  1.1.1.1.2.2  riz Mdoc::def_macro( '.Sq' , gen_encloser(qw(\[oq] \[cq]))  , greedy => 1 );
     32  1.1.1.1.2.2  riz Mdoc::def_macro( '.Pq' , gen_encloser(qw/( )/)          , greedy => 1 );
     33  1.1.1.1.2.2  riz Mdoc::def_macro( '.D1' , sub { ".in +4\n", ns, @_ , ns , "\n.in -4" } , greedy => 1);
     34  1.1.1.1.2.2  riz 
     35  1.1.1.1.2.2  riz Mdoc::def_macro( 'Oo',  sub { '[', @_ } );
     36  1.1.1.1.2.2  riz Mdoc::def_macro( 'Oc',  sub { ']', @_ } );
     37  1.1.1.1.2.2  riz 
     38  1.1.1.1.2.2  riz Mdoc::def_macro( 'Po',  sub { '(', @_} );
     39  1.1.1.1.2.2  riz Mdoc::def_macro( 'Pc',  sub { ')', @_ } );
     40  1.1.1.1.2.2  riz 
     41  1.1.1.1.2.2  riz Mdoc::def_macro( 'Bro', sub { '{', ns, @_ } );
     42  1.1.1.1.2.2  riz Mdoc::def_macro( 'Brc', sub { '}', @_ } );
     43  1.1.1.1.2.2  riz 
     44  1.1.1.1.2.2  riz Mdoc::def_macro( '.Oo',  gen_encloser(qw([ ])), concat_until => '.Oc' );
     45  1.1.1.1.2.2  riz Mdoc::def_macro( '.Bro', gen_encloser(qw({ })), concat_until => '.Brc' );
     46  1.1.1.1.2.2  riz Mdoc::def_macro( '.Po',  gen_encloser(qw/( )/), concat_until => '.Pc' );
     47  1.1.1.1.2.2  riz 
     48  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ev', sub { @_ } );
     49  1.1.1.1.2.2  riz Mdoc::def_macro( '.An', sub { ".NOP ", @_, "\n.br" }, raw => 1 );
     50  1.1.1.1.2.2  riz Mdoc::def_macro( '.Li', sub { mapwords {"\\f[C]$_\\f[]"} @_ } );
     51  1.1.1.1.2.2  riz Mdoc::def_macro( '.Cm', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } );
     52  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ic', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } );
     53  1.1.1.1.2.2  riz Mdoc::def_macro( '.Fl', sub { mapwords {"\\f\\*[B-Font]\\-$_\\f[]"} @_ } );
     54  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ar', sub { mapwords {"\\f\\*[I-Font]$_\\f[]"} @_ } );
     55  1.1.1.1.2.2  riz Mdoc::def_macro( '.Em', sub { mapwords {"\\fI$_\\f[]"} @_ } );
     56  1.1.1.1.2.2  riz Mdoc::def_macro( '.Va', sub { mapwords {"\\fI$_\\f[]"} @_ } );
     57  1.1.1.1.2.2  riz Mdoc::def_macro( '.Sx', sub { mapwords {"\\fI$_\\f[]"} @_ } );
     58  1.1.1.1.2.2  riz Mdoc::def_macro( '.Xr', sub { "\\fC".(shift)."\\fR(".(shift).")\\f[]", @_ } );
     59  1.1.1.1.2.2  riz Mdoc::def_macro( '.Fn', sub { "\\f\\*[B-Font]".(shift)."\\fR()\\f[]" } );
     60  1.1.1.1.2.2  riz Mdoc::def_macro( '.Fn', sub { "\\fB".(shift)."\\fR()\\f[]" } );
     61  1.1.1.1.2.2  riz Mdoc::def_macro( '.Fx', sub { "FreeBSD", @_ } );
     62  1.1.1.1.2.2  riz Mdoc::def_macro( '.Ux', sub { "UNIX", @_ } );
     63  1.1.1.1.2.2  riz 
     64  1.1.1.1.2.2  riz Mdoc::def_macro( '.No', sub { ".NOP", map { ($_, ns) } @_ } );
     65  1.1.1.1.2.2  riz Mdoc::def_macro( '.Pa', sub { mapwords {"\\fI$_\\f[]"} @_; } );
     66  1.1.1.1.2.2  riz {
     67  1.1.1.1.2.2  riz     my $name;
     68  1.1.1.1.2.2  riz     Mdoc::def_macro('.Nm', sub {
     69  1.1.1.1.2.2  riz         $name = shift if (!$name);
     70  1.1.1.1.2.2  riz         "\\f\\*[B-Font]$name\\fP", @_
     71  1.1.1.1.2.2  riz     } );
     72  1.1.1.1.2.2  riz }
     73  1.1.1.1.2.2  riz 
     74  1.1.1.1.2.2  riz ########
     75  1.1.1.1.2.2  riz ## lists
     76  1.1.1.1.2.2  riz ########
     77  1.1.1.1.2.2  riz 
     78  1.1.1.1.2.2  riz my %lists = (
     79  1.1.1.1.2.2  riz     bullet => sub {
     80  1.1.1.1.2.2  riz         Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' });
     81  1.1.1.1.2.2  riz     },
     82  1.1.1.1.2.2  riz 
     83  1.1.1.1.2.2  riz     column => sub {
     84  1.1.1.1.2.2  riz         Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' });
     85  1.1.1.1.2.2  riz     },
     86  1.1.1.1.2.2  riz 
     87  1.1.1.1.2.2  riz     tag    => sub {
     88  1.1.1.1.2.2  riz         my (%opts) = @_;
     89  1.1.1.1.2.2  riz 
     90  1.1.1.1.2.2  riz         my $width = '';
     91  1.1.1.1.2.2  riz 
     92  1.1.1.1.2.2  riz         if (exists $opts{width}) {
     93  1.1.1.1.2.2  riz             $width = ' '.((length $opts{width})+1);
     94  1.1.1.1.2.2  riz         }
     95  1.1.1.1.2.2  riz 
     96  1.1.1.1.2.2  riz         if (exists $opts{compact}) {
     97  1.1.1.1.2.2  riz             my $dobrns = 0;
     98  1.1.1.1.2.2  riz             Mdoc::def_macro('.It', sub {
     99  1.1.1.1.2.2  riz                     my @ret = (".TP$width\n.NOP", hs);
    100  1.1.1.1.2.2  riz                     if ($dobrns) {
    101  1.1.1.1.2.2  riz                         ".br\n.ns\n", ns, @ret, @_;
    102  1.1.1.1.2.2  riz                     }
    103  1.1.1.1.2.2  riz                     else {
    104  1.1.1.1.2.2  riz                         $dobrns = 1;
    105  1.1.1.1.2.2  riz                         @ret, @_;
    106  1.1.1.1.2.2  riz                     }
    107  1.1.1.1.2.2  riz                 }, raw => 1);
    108  1.1.1.1.2.2  riz         }
    109  1.1.1.1.2.2  riz         else {
    110  1.1.1.1.2.2  riz             Mdoc::def_macro('.It', sub {
    111  1.1.1.1.2.2  riz                     ".TP$width\n.NOP", hs, @_
    112  1.1.1.1.2.2  riz                 }, raw => 1);
    113  1.1.1.1.2.2  riz         }
    114  1.1.1.1.2.2  riz     },
    115  1.1.1.1.2.2  riz );
    116  1.1.1.1.2.2  riz 
    117  1.1.1.1.2.2  riz Mdoc::set_Bl_callback(do { my $nested = 0; sub {
    118  1.1.1.1.2.2  riz     my $type = shift;
    119  1.1.1.1.2.2  riz     my %opts = Mdoc::parse_opts(@_);
    120  1.1.1.1.2.2  riz     if (defined $type && $type =~ /-(\w+)/ && exists $lists{$1}) {
    121  1.1.1.1.2.2  riz 
    122  1.1.1.1.2.2  riz         # Wrap nested lists with .RS and .RE
    123  1.1.1.1.2.2  riz         Mdoc::set_El_callback(sub { 
    124  1.1.1.1.2.2  riz                 return '.RE' if $nested-- > 1;
    125  1.1.1.1.2.2  riz                 return '.PP';
    126  1.1.1.1.2.2  riz             });
    127  1.1.1.1.2.2  riz 
    128  1.1.1.1.2.2  riz         $lists{$1}->(%opts);
    129  1.1.1.1.2.2  riz 
    130  1.1.1.1.2.2  riz         if ($nested++) {
    131  1.1.1.1.2.2  riz             return ".RS";
    132  1.1.1.1.2.2  riz         }
    133  1.1.1.1.2.2  riz         else {
    134  1.1.1.1.2.2  riz             return ();
    135  1.1.1.1.2.2  riz         }
    136  1.1.1.1.2.2  riz     }
    137  1.1.1.1.2.2  riz     else {
    138  1.1.1.1.2.2  riz         die "Invalid list type <$type>";
    139  1.1.1.1.2.2  riz     }
    140  1.1.1.1.2.2  riz }}, raw => 1);
    141  1.1.1.1.2.2  riz 
    142  1.1.1.1.2.2  riz # don't bother with arguments for now and do what mdoc2man'.sh' did
    143  1.1.1.1.2.2  riz 
    144  1.1.1.1.2.2  riz Mdoc::def_macro('.Bd', sub { ".br\n.in +4\n.nf" } );
    145  1.1.1.1.2.2  riz Mdoc::def_macro('.Ed', sub { ".in -4\n.fi" } );
    146  1.1.1.1.2.2  riz 
    147  1.1.1.1.2.2  riz Mdoc::set_Re_callback(sub { 
    148  1.1.1.1.2.2  riz         my ($reference) = @_;
    149  1.1.1.1.2.2  riz         <<"REF";
    150  1.1.1.1.2.2  riz $reference->{authors},
    151  1.1.1.1.2.2  riz \\fI$reference->{title}\\fR,
    152  1.1.1.1.2.2  riz $reference->{optional}\n.PP
    153  1.1.1.1.2.2  riz REF
    154  1.1.1.1.2.2  riz });
    155  1.1.1.1.2.2  riz 
    156  1.1.1.1.2.2  riz # Define all macros which have the same sub for inline and standalone macro
    157  1.1.1.1.2.2  riz for (qw(Xr Em Ar Fl Ic Cm Qq Op Nm Pa Sq Li Va Brq Pq Fx Ux)) {
    158  1.1.1.1.2.2  riz     my $m = Mdoc::get_macro(".$_");
    159  1.1.1.1.2.2  riz     Mdoc::def_macro($_, delete $m->{run}, %$m);
    160  1.1.1.1.2.2  riz }
    161  1.1.1.1.2.2  riz 
    162  1.1.1.1.2.2  riz sub print_line {
    163  1.1.1.1.2.2  riz     print shift;
    164  1.1.1.1.2.2  riz     print "\n";
    165  1.1.1.1.2.2  riz }
    166  1.1.1.1.2.2  riz 
    167  1.1.1.1.2.2  riz sub run {
    168  1.1.1.1.2.2  riz     print <<'DEFS';
    169  1.1.1.1.2.2  riz .de1 NOP
    170  1.1.1.1.2.2  riz .  it 1 an-trap
    171  1.1.1.1.2.2  riz .  if \\n[.$] \,\\$*\/
    172  1.1.1.1.2.2  riz ..
    173  1.1.1.1.2.2  riz .ie t \
    174  1.1.1.1.2.2  riz .ds B-Font [CB]
    175  1.1.1.1.2.2  riz .ds I-Font [CI]
    176  1.1.1.1.2.2  riz .ds R-Font [CR]
    177  1.1.1.1.2.2  riz .el \
    178  1.1.1.1.2.2  riz .ds B-Font B
    179  1.1.1.1.2.2  riz .ds I-Font I
    180  1.1.1.1.2.2  riz .ds R-Font R
    181  1.1.1.1.2.2  riz DEFS
    182  1.1.1.1.2.2  riz 
    183  1.1.1.1.2.2  riz     while (my ($macro, @args) = Mdoc::parse_line(\*STDIN, \&print_line)) {
    184  1.1.1.1.2.2  riz         my @ret = Mdoc::call_macro($macro, @args);
    185  1.1.1.1.2.2  riz         print_line(Mdoc::to_string(@ret)) if @ret;
    186  1.1.1.1.2.2  riz     }
    187  1.1.1.1.2.2  riz     return 0;
    188  1.1.1.1.2.2  riz }
    189  1.1.1.1.2.2  riz 
    190  1.1.1.1.2.2  riz exit run(@ARGV) unless caller;
    191  1.1.1.1.2.2  riz 
    192  1.1.1.1.2.2  riz 1;
    193  1.1.1.1.2.2  riz __END__
    194