From e881000941ea96b6b6f0010f929c5c5c789522f0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 10 Aug 2007 10:40:21 +0000 Subject: [PATCH] initial add from my private repo, 'roffit' was internal revision 1.17 --- CHANGES | 56 +++++++ release.pl | 22 +++ roffit | 467 +++++++++++++++++++++++++++++++++++++++++++++++++++++ roffit.1 | 58 +++++++ 4 files changed, 603 insertions(+) create mode 100644 CHANGES create mode 100755 release.pl create mode 100755 roffit create mode 100644 roffit.1 diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..a29ef66 --- /dev/null +++ b/CHANGES @@ -0,0 +1,56 @@ +* (Jan 2, 2005) +- Steve Benson made roffit translate all '\-' sequenes to just '-'. + +* (April 5, 2005) +- Make a bare .BR do a "
" +- Make .pp start a new paragraph +- Ignore the weird '\" comment latex2man adds +- Ignore de, ft and "..". I *believe* they are use to set a "macro". + +* (March 15, 2005) +- Added comments about .nf and .fi based on + http://www.rfc-editor.org/nroff.html + +* (June 21, 2004) +- make .fi properly end a .nf section + +* (April 12, 2004) +- convert <> properly within the .BR data as well + +* (March 5, 2004) +- make links for ftp:// as well +- strip \& completely instead of making "&zerosp;" (which isn't good html) + +0.6 (February 27, 2004) + - added --mandir and --hrefdir + - made it convert http:// URLs to links + - added --version + +0.5 (February 3, 2004) + - Added support for more &-combos + - Better treatment of .nf to make
 sections, and we now do newlines
+   better within such a 
 section
+ - .IR is now treated equally as .I
+ - keywords and their data can be tab-separated
+ - .SS is now treated as .SH
+
+0.4 (December 5, 2003)
+ - Andrew Dixon filed a bug report with a man page generated with the
+   help2man tool. roffit now deals with \fR as well as \fP as an end
+   marker for special word formatting.
+ - I moved the changelog into this file
+ - Wrote a first basic man page for roffit
+
+0.3 (November 14, 2003)
+ Daniel Fandrich brought:
+ - deals with .lp lines
+ - .TH needs no section portion anymore
+ - added generator meta tag in the header
+
+0.2 (November 7, 2003)
+ - fixed the  name for the SH section
+ - added  links from all words within \fIthis\fP or \fBthis\fP
+   that has the same text as a .SH or .IP.
+
+0.1 (November 5, 2003)
+ - Initial public release
diff --git a/release.pl b/release.pl
new file mode 100755
index 0000000..70ad098
--- /dev/null
+++ b/release.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+my @files=('CHANGES', 'roffit', 'roffit.1');
+
+my $version=$ARGV[0];
+
+if(!$version) {
+    print "Usage: release.pl \n";
+    exit;
+}
+
+my $dir = "roffit-$version";
+
+mkdir $dir;
+
+for(@files) {
+    `cp $_ $dir`;
+}
+
+`tar czf roffit-${version}.tar.gz $dir`;
+
+`rm -rf $dir`;
diff --git a/roffit b/roffit
new file mode 100755
index 0000000..3e78d3c
--- /dev/null
+++ b/roffit
@@ -0,0 +1,467 @@
+#!/usr/bin/env perl 
+#
+# roffit: convert man page source files to HTML
+#
+# Read an nroff file. Output a HTML file.
+#
+# This is a very simple script, but I use it on very simple man pages as I've
+# found no decent script that makes really nice web pages.
+#
+# $Id: roffit,v 1.1 2007/08/10 10:40:22 bagder Exp $
+#
+my $version = "0.7";
+# Author:  Daniel Stenberg 
+# Please mail me improvements.
+#
+
+use strict;
+#use warnings;
+
+my $InFH = \*STDIN;
+my $OutFH = \*STDOUT;
+my $debugFH = \*STDERR;
+
+my %manpage;
+my @out;
+
+my $indentlevel=0; # logical levels, not columns
+my @p;
+my $within_tp;
+my $standalone=1; # by default we make stand-alone HTML pages
+my $pre;
+my %anchor; # hash with all anchors
+
+my $mandir;
+my $hrefdir=".";
+
+while($ARGV[0]) {
+    if($ARGV[0] eq "--bare") {
+        # don't include headers and stuff
+        $standalone=0;
+        shift @ARGV;
+    }
+    elsif($ARGV[0] eq "--version") {
+        print "roffit $version (http://daniel.haxx.se/projects/roffit/)\n";
+        exit;
+    }
+    elsif($ARGV[0] =~ /^--mandir=(.*)/) {
+        # check for other HTMLized man pages in this given dir
+        $mandir=$1;
+        shift @ARGV;
+    }
+    elsif($ARGV[0] =~ /^--hrefdir=(.*)/) {
+        # if another manpage is found in the --mandir, this is the dir we
+        # prefix the HTML file name with in the output HTML
+        $hrefdir=$1;
+        shift @ARGV;
+    }
+    else {
+        printf $debugFH "unknown option: %s\n", $ARGV[0] if($ARGV[0] ne "-h");
+        print $debugFH "Usage: roffit [options] < infile > outfile\n",
+        "Options:\n",
+        " --version       display roffit version and exit\n",
+        " --bare          do not put in HTML, HEAD, BODY tags\n",
+        " --mandir=  check for other HTMLized man pages in this dir\n",
+        " --hrefdir= if a manpage is found in the --mandir, this is the\n",
+        "                 dir we prefix the HTML file name with in the output\n";
+        exit;
+    }
+}
+
+sub showp {
+    my @p = @_;
+    push @out, "\n" if(!$pre);
+    push @out, "

", @p; +} + +sub defaultcss { + print $OutFH < +P.level0 { + padding-left: 2em; +} + +P.level1 { + padding-left: 4em; +} + +P.level2 { + padding-left: 6em; +} + +span.emphasis { + font-style: italic; +} + +span.bold { + font-weight: bold; +} + +span.manpage { + font-weight: bold; +} + +h2.nroffsh { + background-color: #e0e0e0; +} + +span.nroffip { + font-weight: bold; + font-size: 120%; + font-family: monospace; +} + +p.roffit { + text-align: center; + font-size: 80%; +} + +ENDOFCSS + ; +} + +sub text2name { + my ($text) = @_; + $text =~ s/^ *([^ ]*).*/$1/g; + $text =~ s/[^a-zA-Z0-9-]//g; + return $text; +} + +# scan through the file and check for sections we should convert +# to proper links +sub linkfile { + my @new; + for(@out) { + my $line=$_; + my $l; + while($line =~ s/([^<]*)<\/span>/[]/) { + my ($style, $name)=($1, $2); + + $l = text2name($name); + + #printf $debugFH "$style - $name - %s - %d\n", + #$l, $anchor{$l}; + + my $link; + if($anchor{$l}) { + $link="$name"; + } + else { + if(($name =~ /^ *(\w*) *\( *(\d*) *\) *$/) && ($mandir)) { + + # this looks like a reference to another man page, and we + # have asked for this feature! We check for the specified + # nroff file and not the HTML version, to avoid depending + # on which order the set of files are converted to HTML! + my ($symbol, $section)=($1, $2); + my $file = "$mandir/$symbol.$section"; + + if(-r $file) { + my $html = "$hrefdir/$symbol.html"; + # there is such a HTML file present, produce a link + # to it! + $link="$name"; + } + } + if(!$link) { + $link="$name"; + } + } + $line =~ s/\[\]/$link/; + } + # convert lowercase ftp:// or http:// links to links + $line =~ s/((http|ftp):\/\/([a-z0-9.\/_%-]*[a-z\/]))/$1<\/a>/g; + push @new, $line; + } + return @new; +} + +sub parsefile { + my $lineno; + while(<$InFH>) { + $lineno++; + my $in = $_; + my $out; + # print $debugFH "DEBUG IN: $_"; + + $in =~ s/[\r\n]//g if(!$pre); # tear off newlines + + $in =~ s/\r//g; # remote carriage return always + + # substitue all '\-' sequences with '-'. + # '\-' might be in the source file to specify a literal + # '-' rather than a hyphen. + $in =~ s/\\-/-/g; + + if($in =~ /^\'\\\"/) { + # ignore this kind of weird comment + $out =""; + } + elsif($in =~ /^\.([^ \t\n]*)(.*)/) { + # this is a line starting with a dot, that means it is special + my ($keyword, $rest) = ($1, $2); + $out = ""; + + # cut off initial spaces + $rest =~ s/^ +//g; + + if($keyword eq "\\\"") { + # this is a comment, skip this line + } + elsif($keyword =~ /^TH$/i) { + # man page header: + # curl 1 "22 Oct 2003" "Curl 7.10.8" "Curl Manual" + # NAME SECTION DATE VERSION MANUAL + if($rest =~ /([^ ]*) (\d+) \"([^\"]*)\" \"([^\"]*)\"(\"([^\"]*)\")?/) { + # strict matching only so far + $manpage{'name'} = $1; + $manpage{'section'} = $2; + $manpage{'date'} = $3; + $manpage{'version'} = $4; + $manpage{'manual'} = $6; + } + } + elsif($keyword =~ /^S[HS]$/i) { + # SS is treated the same as SH + # Section Header + showp(@p); + @p=""; + if($pre) { + push @out, "

\n"; + $pre = 0; + } + + my $name = text2name($rest); + $anchor{$name}=1; + + $rest =~ s/\"//g; # cut off quotes + $rest =~ s//>/g; + $out = "

$rest

"; + $indentlevel=0; + $within_tp=0; + } + elsif(($keyword =~ /^B$/i) || ($keyword =~ /^BI$/i)) { + # Make B and BI the same for simplicity + $rest =~ s/\"//g; # cut off quotes + $rest =~ s//>/g; + + # This is pretty lame, but since a .B section and itself + # contain a \fI[blabla]\fP section, we cut off all the \f + # occurances within the .B text to make it easier for ourself. + $rest =~ s/\\f[IPR]//g; + + push @p, "$rest "; + if($pre) { + push @p, "\n"; + } + } + elsif(($keyword =~ /^I$/i) || ($keyword =~ /^IR$/i)) { + $rest =~ s/\"//g; # cut off quotes + $rest =~ s//>/g; + push @p, "$rest "; + } + elsif($keyword =~ /^RS$/i) { + # the start of another indent-level. for inlined tables + # within an "IP" + showp(@p); + @p=""; + $indentlevel++; + } + elsif($keyword =~ /^RE$/i) { + # end of the RS section + showp(@p); + @p=""; + $indentlevel--; + } + elsif($keyword =~ /^NF$/i) { + # We let nf start a
 section .nf = no-fill, you use for
+                # graphs or text that you don't want spaces to be ignored
+
+                showp(@p);
+                @p="";
+                push @out, "
\n";
+                $pre=1
+            }
+            elsif($keyword =~ /^TP$/i) {
+                # Used within an "RS" section to make a new line. The first
+                # TP as a column indicator, but we decide to do that
+                # controlling in the CSS instead.
+                $within_tp=1;
+                showp(@p);
+                @p="";                
+            }
+            elsif($keyword =~ /^IP$/i) {
+                # start of a new paragraph coming up
+                showp(@p);
+                @p="";
+
+                my $name= text2name($rest);
+                $anchor{$name}=1;
+
+                $rest =~ s/\"//g; # cut off quotes
+                $rest =~ s//>/g;
+                
+                $indentlevel-- if ($indentlevel);
+                push @p, "$rest ";
+                # make this a single-line title
+                showp(@p);
+                @p="";
+                $indentlevel++;
+                $within_tp=0;
+            }
+            elsif($keyword =~ /^ad$/i) {
+                showp(@p);
+                @p="";
+            }
+            elsif($keyword =~ /^sp$/i) {
+                showp(@p);
+                @p="";
+            }
+            elsif($keyword =~ /^lp$/i) {
+                # marks end of a paragraph
+                showp(@p);
+                @p="";
+            }
+            elsif($keyword =~ /^pp$/i) {
+                # PP ends a TP section, but some TP sections don't use it
+                # Often used to separate paragraphs
+                $within_tp=0;
+                showp(@p);
+                @p="";
+            }
+            elsif($keyword =~ /^fi$/i) {
+                # .fi = fill-in, extra space will be ignored and text that is
+                # entered like this, the fill-in command will continue until
+                # you enter a .nf command and vice-versa
+
+                showp(@p);
+                @p="";
+                if($pre) {
+                    # if this is the end of a .nf (
) section
+                    push @out, "
\n"; + $pre=0; # disable pre again + } + + } + elsif($keyword =~ /^(de|ft|\.)$/i) { + # no idea what these do! + } + elsif($keyword =~ /^so$/i) { + # This keyword refers to a different man page, named in the + # $rest. + # We don't support this + push @out, "See the $rest man page.\n"; + } + elsif($keyword =~ /^BR$/i) { + # I'm not sure what this does exactly, but this is commonly + # used to include pointers to other man pages. Let's assume + # it only does that for now. + # blabla (3) + # or "blabla (3)" + # or strcmp "(3), " strcasecmp "(3)" + # etc + + $rest =~ s/\"//g; # cut off quotes + $rest =~ s//>/g; + + if(!$rest) { + # A stand-alone .br will become a line break + #print $debugFH "ALERT: bare BR\n"; + push @p, "
"; + } + else { + my @all = split /,/, $rest; + for(@all) { + if(/([^ ]*) *\((\d+)\)/) { + # TODO: this looks like a man page, check if + # there's a HTML file for it and if so make a link + # to it + } + + push @p, "$_ "; + } + } + } + else { + showp(@p); + @p=""; + print $debugFH "ALERT: unknown keyword \"$keyword\" on line $lineno\n"; + } + } + else { + # text line, decode \-stuff + my $txt = $in; + + $txt =~ s//>\;/g; + $txt =~ s/\\&//g; + $txt =~ s/\\-/-/g; + $txt =~ s/\\ / \;/g; + $txt =~ s/\\\'/´\;/g; + $txt =~ s/\\\(co/©\;/g; + $txt =~ s/\\fI//g; + $txt =~ s/\\fB//g; + $txt =~ s/\\f[PR]/<\/span>/g; + + # replace backslash [something] with just [something] + $txt =~ s/\\(.)/$1/g; + + if($txt =~ /^[ \t\r\n]*$/) { + # no contents, marks end of a paragraph + showp(@p); + @p=""; + } + else { + $txt =~ s/^ /\ \;/g; + push @p, "$txt "; + } + $out =""; + } + + if($out) { + push @out, $out; + # print $debugFH "DEBUG OUT: $out\n"; + } + else { + # print $debugFH "DEBUG OUT: [withheld]\n"; + } + } + showp(@p); +} + +parsefile(); + +my @conv = linkfile(); + +my $title=sprintf("%s man page", + $manpage{'name'}?$manpage{'name'}:"secret"); + +if($standalone) { + print $OutFH < +$title + +MOO + ; + defaultcss(); + print "\n"; +} +else { + print "\n"; +} + +print $OutFH @conv; +print $OutFH < + This HTML page was made with roffit. +ROFFIT + ; + +if($standalone) { + print "\n"; +} diff --git a/roffit.1 b/roffit.1 new file mode 100644 index 0000000..291886b --- /dev/null +++ b/roffit.1 @@ -0,0 +1,58 @@ +.\" You can view this file with: +.\" nroff -man roffit.1 +.\" Written by Daniel Stenberg +.\" +.TH roffit 1 "27 Feb 2004" "roffit 0.6" "roffit Manual" +.SH NAME +roffit \- convert nroff to HTML +.SH SYNOPSIS +.B roffit [options] < inputfile > outputfile +.SH DESCRIPTION +.B roffit +converts the \fIinputfile\fP to \fIoutputfile\fP. The \fIinputfile\fP must be +an nroff formatted man page, and the \fIoutputfile\fP will be an HTML +document. +.SH OPTIONS +.IP --bare +The output HTML will not include any HTML, HEAD or BODY tags. Also not that +when this is selected, there will be no inlined CSS but you will have to +define the necessary classes yourself. +.IP --version +Display version number and exit +.IP --mandir= +Set a directory in which \fIroffit\fP will check for other man pages (in nroff +[name].[num] format) that this one refers to. If found, a link will +be made to that page with a html extension instead of the number. The file +name in the generated link will be prefixed by the dir given with +\fI--hrefdir\fP. + +This works for references specified as \fImanpage(3)\fP (within the emhpasis +foformatting) and in a plain \.BR section (often used in the SEE ALSO +section). +.IP --hrefdir= +Specify a directory to prefix generated href links created with the --mandir +option. This defaults to ".". +.SH "CSS CLASSES" +.IP h2.nroffsh +The nroff ".SH" section. These are normally the "headlines" before each sub +section within the man page. +.IP p.nroffip +The nroff ".IP" section. These are normally the bullet kind used to list each +option out of several in a list. Usually followed by a \fIp.level0\fP +containining the descriptive text. +.IP p.level0 +Normal text at the first level. Normally not indented. +.IP p.level1 +Text at next logical indent level. Normally indented one level right. +.IP p.level2 +Text at the second logical indent level. Normally indented two levels right. +.IP span.bold +Text marked to be bold. +.IP span.manpage +Text marked as a reference to another man page. +.IP span.emphasis +Text marked to be emphasized. +.IP p.roffit +Used for the advertising final paragraph. +.SH WWW +http://daniel.haxx.se/projects/roffit