summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/sty2dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-01-28 23:23:36 +0000
committerKarl Berry <karl@freefriends.org>2011-01-28 23:23:36 +0000
commiteb9f81c6f8ed959b7b4543e0d4e28721394512e0 (patch)
treea6e9c495f0674ad1b8a2153b6c1ebd71c6d80380 /Master/texmf-dist/scripts/sty2dtx
parent602979c95a6c85a4dc3a3e1899da6af89ed603c2 (diff)
new package and script sty2dtx 1.0 (29jan11)
git-svn-id: svn://tug.org/texlive/trunk@21215 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/sty2dtx')
-rwxr-xr-xMaster/texmf-dist/scripts/sty2dtx/sty2dtx.pl160
1 files changed, 160 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/sty2dtx/sty2dtx.pl b/Master/texmf-dist/scripts/sty2dtx/sty2dtx.pl
new file mode 100755
index 00000000000..1823a84e811
--- /dev/null
+++ b/Master/texmf-dist/scripts/sty2dtx/sty2dtx.pl
@@ -0,0 +1,160 @@
+#!/usr/bin/env perl
+################################################################################
+# Copyright (c) 2010-2011 Martin Scharrer <martin@scharrer-online.de>
+# This is open source software under the GPL v3 or later.
+#
+# Converts a .sty file (LaTeX package) to .dtx format (documented LaTeX source),
+# by surrounding macro definitions with 'macro' and 'macrocode' environments.
+# The macro name is automatically inserted as an argument to the 'macro'
+# environemnt.
+# Code lines outside macro definitions are wrapped only in 'macrocode'
+# environments. Empty lines are removed.
+# The script is not thought to be fool proof and 100% accurate but rather
+# as a good start to convert undocumented style file to .dtx files.
+#
+# Usage:
+# perl sty2dtx.pl infile [infile ...] outfile
+# or
+# perl sty2dtx.pl < file.sty > file.dtx
+#
+#
+# The following macro definitions are detected when they are at the start of a
+# line (can be prefixed by \global, \long, \protected and/or \outer):
+# \def \edef \gdef \xdef
+# \newcommand{\name} \newcommand*{\name}
+# \newcommand\name \newcommand*\name
+# \renewcommand{\name} \renewcommand*{\name}
+# \renewcommand\name \renewcommand*\name
+# \providecommand{\name} \providecommand*{\name}
+# \providecommand\name \providecommand*\name
+# \@namedef{\name} \@namedef\name
+#
+# The macro definition must either end at the same line or with a '}' on its own
+# on a line.
+#
+# $Id: sty2dtx.pl 2091 2011-01-28 01:25:44Z martin $
+################################################################################
+use strict;
+use warnings;
+
+# Used as format string of printf so that the '%' must be doubled:
+my $macrostart = <<'EOT';
+%% \begin{macro}{\%s}
+%% \begin{macrocode}
+EOT
+
+# Printed normally:
+my $macrostop = <<'EOT';
+% \end{macrocode}
+% \end{macro}
+%
+EOT
+
+my $macrocodestart = <<'EOT';
+% \begin{macrocode}
+EOT
+
+my $macrocodestop = <<'EOT';
+% \end{macrocode}
+%
+EOT
+
+my $mode = 0;
+
+# 0 = outside of macro or macrocode environments
+# 1 = inside macro environment
+# 2 = inside macrocode environment
+
+# RegExs for macro names and defintion:
+my $macroname = qr/[a-zA-Z\@:]+/; # Add ':' for LaTeX3 style macros
+my $definition = qr/
+ ^ # Begin of line (no whitespaces!)
+ (
+ (?:(?:\\global|\\long|\\protected|\\outer)\s*)* # Prefixes (maybe with whitespace between them)
+ )
+ \\(
+ [gex]?def \s* \\ # TeX definitions
+ | (?:new|renew|provide)command\s* \*? \s* {? \s* \\ # LaTeX definitions
+ | \@namedef{? # Definition by name only
+ )
+ ($macroname) # Macro name without backslash
+ (.*) # Rest of line
+ /xms;
+
+# Last (but not only) argument is output file, except if it is '-' (=STDOUT)
+if (@ARGV > 1) {
+ my $outfile = pop;
+ if ($outfile ne '-') {
+ open (OUTPUT, '>', $outfile) or die ("Could not open output file '$outfile'!");
+ select OUTPUT;
+ }
+}
+
+while (<>) {
+ # Test for macro definition command
+ if (/$definition/) {
+ my $pre = $1 || ""; # before command
+ my $cmd = $2; # definition command
+ my $name = $3; # macro name
+ my $rest = $4; # rest of line
+ if ( $cmd =~ /command\*?{/ ) {
+ $rest =~ s/^}//; # handle '\newcommand{\name}
+ }
+
+ # Print end of environment, if one is open
+ if ( $mode == 1 ) {
+ # Happens only if closing brace is not on a line by its own.
+ print $macrostop;
+ }
+ elsif ( $mode == 2 ) {
+ print $macrocodestop;
+ }
+
+ # Print 'macro' environment with current line.
+ printf $macrostart, $name;
+ print $_;
+
+ # Inside macro mode
+ $mode = 1;
+
+ # Test for one line definitions.
+ # $pre is tested to handle '{\somecatcodechange\gdef\name{short}}' lines
+ my $prenrest = $pre . $rest;
+ if ( $prenrest =~ tr/{/{/ == $prenrest =~ tr/}/}/ ) {
+ print $macrostop;
+ # Outside mode
+ $mode = 0;
+ }
+ }
+ # A single '}' on a line ends a 'macro' environment
+ elsif ($mode == 1 && /^}\s*$/) {
+ print $_, $macrostop;
+ $mode = 0;
+ }
+ # Remove empty lines (mostly between macros)
+ elsif (/^$/) {
+ }
+ else {
+ # If inside an environment
+ if ($mode) {
+ print;
+ }
+ else {
+ # Start macrocode environment
+ print $macrocodestart, $_;
+ $mode = 2;
+ }
+ }
+}
+
+# Print end of environment, if one is open
+if ( $mode == 1 ) {
+ # Happens only if closing brace is not on a line by its own.
+ print $macrostop;
+}
+elsif ( $mode == 2 ) {
+ print $macrocodestop;
+}
+
+__END__
+