diff options
| author | mstsirkin <mstsirkin@0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652> | 2013-11-25 12:25:46 +0000 | 
|---|---|---|
| committer | mstsirkin <mstsirkin@0c8fb4dd-22a2-4bb5-bc14-6c75a5f43652> | 2013-11-25 12:25:46 +0000 | 
| commit | 678610624cbcef303b9dd5ebe134135030449474 (patch) | |
| tree | 931efde6d040d858ce940d35c344346bcc06f72b | |
| parent | 37797d7ad6edc0ce9a46be9ea582bd681c498cbd (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
| -rwxr-xr-x | txt2latex.pl | 182 | 
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; +} + +  | 
