summaryrefslogtreecommitdiff
path: root/txt2latex.pl
diff options
context:
space:
mode:
authormstsirkin <mstsirkin@0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652>2013-11-25 12:25:46 +0000
committermstsirkin <mstsirkin@0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652>2013-11-25 12:25:46 +0000
commit678610624cbcef303b9dd5ebe134135030449474 (patch)
tree931efde6d040d858ce940d35c344346bcc06f72b /txt2latex.pl
parent37797d7ad6edc0ce9a46be9ea582bd681c498cbd (diff)
txt2latex.pl: script to convert text to latex
The result compiles and looks kind of OK. This reverse-engineers our txt format to generate the initial latex file. Tables are included in verbatim sections. Code is included in listing sections. Math is escaped with $$. TODO (possibly manually): - remove extra sections at the beginning of the document - format tales using tabular or similar environment - format lists using itemize/enumerate/description - prevent hyphenation in the middle of identifiers Signed-off-by: Michael S. Tsirkin <mst@redhat.com> git-svn-id: https://tools.oasis-open.org/version-control/svn/virtio@111 0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652
Diffstat (limited to 'txt2latex.pl')
-rwxr-xr-xtxt2latex.pl182
1 files changed, 182 insertions, 0 deletions
diff --git a/txt2latex.pl b/txt2latex.pl
new file mode 100755
index 0000000..5e04ef1
--- /dev/null
+++ b/txt2latex.pl
@@ -0,0 +1,182 @@
+#!/usr/bin/perl
+
+use strict;
+
+my @depth2latex = (
+ '\chapter',
+ '\section',
+ '\subsection',
+ '\subsubsection',
+ '\paragraph',
+ '\subparagraph'
+);
+
+my $skip_depth = 1;
+
+sub find_footnotes {
+ my @text = @_;
+ my @notes = ();
+ my $found = 0;
+ my $l;
+
+ for ($l = 0; $l <= $#text; $l++) {
+ if ($text[$l] =~ m/^FOOTNOTES:$/) {
+ $found = 1;
+ }
+ next unless $found;
+ if ($text[$l] =~ m/^\[[0-9]+\]\s/) {
+ push @notes, $l;
+ }
+ }
+ return @notes;
+};
+
+sub find_sections {
+ my @text = @_;
+ my @sections = ();
+ my $l;
+
+ for ($l = 0; $l <= $#text - 1; $l++) {
+ next unless (($text[$l + 1] =~ m/^=======*$/) or
+ ($text[$l + 1] =~ m/^-------*$/));
+
+ next unless ($text[$l] =~ m/^(([0-9]+\.)+) /);
+
+ push @sections, $l;
+
+ }
+ return @sections;
+};
+
+my @text = ();
+while (<>) {
+ push @text, $_;
+}
+
+my @footnotes = find_footnotes(@text);
+my @sections = find_sections(@text);
+
+#Format footnotes
+my %footnote_by_number = ();
+my $f;
+for ($f = 0; $f <= $#footnotes; $f++) {
+ my $l = $footnotes[$f];
+ die unless ($text[$l] =~ m/^\[([0-9]+)\]\s+(.*)/);
+ my $footnote = $1;
+ my $text = $2;
+ die "duplicate footnote number $footnote" if defined($footnote_by_number{$footnote});
+ $footnote_by_number{$footnote} = "$text\n";
+ my $next;
+ if ($f < $#footnotes) {
+ $next = $footnotes[$f + 1];
+ } else {
+ $next = $#text + 1;
+ }
+ for ($l = $footnotes[$f] + 1; $l < $next; $l++) {
+ next if ($text[$l] =~ m/^$/);
+ $footnote_by_number{$footnote} .= $text[$l];
+ }
+}
+
+#Format sections
+my %label_by_section = ();
+my $s;
+
+my %latest_by_depth = ();
+
+for ($s = 0; $s <= $#sections; $s++) {
+ my $l = $sections[$s];
+ die unless ($text[$l] =~ m/^(([0-9]+\.)+)\s+(.+)\s*/);
+ my $section = $1;
+ my $name = $3;
+ my @path = split(/\./, $section);
+ my $depth = $#path - $skip_depth;
+ if ($depth < 0) {
+ $depth = 0;
+ }
+ if ($depth > $#depth2latex) {
+ $depth = $#depth2latex;
+ }
+ $latest_by_depth{$#path} = $name;
+ my $type = $depth2latex[$depth];
+ my $label = $name;
+ #Prepend hierarchical path to make name unique
+ for (my $i = 1; $i <= $#path - $skip_depth; $i++) {
+ last if (not defined $latest_by_depth{$#path - $i});
+ $label = "$latest_by_depth{$#path - $i} / $label";
+ }
+ $text[$l] = $type . "{$name}\\label{sec:$label}\n";
+ $label_by_section{$section} = $label;
+}
+
+my $ifndef = 0;
+my $listing = 0;
+my $table = 0;
+my $buffer = "";
+for my $line (@text) {
+ last if ($line =~ m/^FOOTNOTES:$/);
+ next if (($line =~ m/^=======*$/) or
+ ($line =~ m/^-------*$/));
+
+ if ($line =~ m/^#if/) {
+ print "\\begin{lstlisting}\n";
+ $ifndef++;
+ }
+ if ($ifndef) {
+ if ($line =~ m/^#endif/) {
+ $ifndef--;
+ }
+ $buffer .= $line;
+ if (not $ifndef) {
+ print $buffer;
+ print "\\end{lstlisting}\n";
+ $buffer = "";
+ }
+ next;
+ }
+ if (not $table and $line =~ m/^\+\-/) {
+ print "\\begin{verbatim}\n";
+ $table = 1;
+ }
+ if ($table and not $line =~ m/^(\+\-|\|)/) {
+ print "\\end{verbatim}\n";
+ $table = 0;
+ }
+ if (not $listing and $line =~ m/^\t/) {
+ print "\\begin{lstlisting}\n";
+ $listing = 1;
+ }
+ if ($listing and $line =~ m/^$/) {
+ $buffer .= $line;
+ next;
+ }
+ if ($listing and not $line =~ m/^\t/) {
+ print "\\end{lstlisting}\n";
+ $listing = 0;
+ }
+
+ if (not $table and not $listing) {
+ if ($line =~ m/\S+\s*\^\s*\S+/) {
+ $line =~ s/(\S+\s*\^\s*)(\S+)/\$$1\{$2\}\$/g;
+ } else {
+ $line =~ s/\^/\\^/go;
+ }
+ $line =~ s/#/\\#/go;
+ $line =~ s/&/\\&/go;
+ if ($line =~ m/\[[0-9]+\]/) { #premature optimization
+ for my $n (keys(%footnote_by_number)) {
+ my $txt = $footnote_by_number{$n};
+ $line =~ s/\[$n\]/\n\\footnote{$txt}/g;
+ }
+ }
+ }
+ if ($line =~ m/"(([0-9]+\.)+)[^"]*"/) {
+ my $section = $1;
+ $line =~ s/"(([0-9]+\.)+)[^"]*"/\\ref{sec:$label_by_section{$section}}~\\nameref{sec:$label_by_section{$section}}/g;
+ }
+ print $buffer;
+ $buffer = "";
+ print $line;
+}
+
+