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