#!@perl@ # # Output extended help corresponding to a given GP command. By default, # extract relevant information from from the PARI manual, run TeX, then open # an xdvi display. # # The manual can be compressed. # # Usage: gphelp keyword # # Command line options: # -k: apropos (list of relevant GP functions) # -detex (-d): don't use TeX + xdvi (implicit when DISPLAY is not set). # -color_help (-ch) : use color "number" (same scheme as in GP) # -color_bold (-cb) : display bold in color "number" # -color_underline (-cu) : display underlined text in color "number" # # -raw use internal format for output with @x markers, -detex is implicit # (for the TeX-to-pod converter) # # -to_pod file convert file to POD (should be the only args) # # Granted environment variables (override): # GPTMPDIR: where temporary files will go (/tmp by default). # GPDOCDIR: where is manual (by default, where make install will put it). # GPXDVI: which 'xdvi' program to call (xdvi by default) # $version= "@version@"; $docdir = $ENV{GPDOCDIR} || $ENV{GPHELP_DOCDIR} || "@miscdir@"; # no expanded material (@key@) below $xdvi = $ENV{GPXDVI} || "xdvi"; $gzip = "gzip"; $zcat = "$gzip -dc"; &to_pod() if @ARGV == 2 && $ARGV[0] eq '-to_pod'; &options(); &init(); if ($#ARGV < 0) { &treat($_); exit 0; } &pretex() if (!$detex); for (@ARGV) { &treat($_); } if ($apropos) { &apropos_final_print(); exit 0; } if (!$found) { &clean if (!$detex); exit 0; } &posttex() if (!$detex); print $gpmsg if (!$detex && $fromgp); exit 0; # # Procedures # sub help { print "Usage: $0 [-k] [-detex] [-ch c1] [-cb c2] [-cu c3] keyword\n"; print "where c1,c2,c3 denote background, bold and underline color\n"; exit(1); } sub options { while ($_ = $ARGV[0]) { last if (! /^-[a-z]/); shift(@ARGV); if ($_ eq "-fromgp") { $fromgp = 1; } elsif ($_ eq "-k") { $apropos = 1; } elsif ($_ eq "-detex" || $_ eq "-d") { $detex = 1; } elsif ($_ eq "-raw") { $raw = $detex = 1; } elsif ($_ eq "-color_help" || $_ eq "-ch") { $ch = &color(shift(@ARGV)); } elsif ($_ eq "-color_bold" || $_ eq "-cb") { $cb = &color(shift(@ARGV)); } elsif ($_ eq "-color_underline" || $_ eq "-cu") { $cu = &color(shift(@ARGV)); } else { &help(); } } $detex = 1 if (!$detex && !$ENV{DISPLAY}); } sub init { $gpmsg = "ugly_kludge_done\n"; $notfound = "not found !\n"; &inittr(); $indent = " "; chdir($docdir); $docfile = "usersch3.tex"; $tmpdir = $ENV{GPTMPDIR} || $ENV{TMPDIR} || $ENV{GPHELP_TMPDIR} || "/tmp"; $texfile = "$tmpdir/gp.help$$"; open(IN,"translations") || die("Could not find translation file"); while() { chop; @_ = split(/ *\@ */); $key = shift(@_); $transl{$key} = join('@',@_); } close(IN); } sub choose_chap { while (s/\@([0-9])$//) { $docfile = "usersch$1.tex"; } if (-r $docfile) { $pipe = ""; } else { die "Cannot find $docfile" if (! -r "$docfile.z" && ! -r "$docfile.gz" && ! -r "$docfile.Z"); $pipe = $zcat; } } sub open_dvi_then_quit { local($dvifile) = $_[0]; $dvifile = "$docdir/$dvifile" if (! -f "$dvifile"); die "could not find $dvifile" if (! -f "$dvifile"); (!$ENV{DISPLAY} && !$ENV{GPXDVI}) && die "xdvi needs X-Windows"; system("$xdvi $dvifile 2>/dev/null >/dev/null&"); exit 0; } sub treat { $_ = $_[0]; s/^ *"(.*)"([^"]*) *$/$1$2/; if (s/\@$//) { $found = 0; $searchall = 1; $help = $_; while () { if (/usersch(.*)\.tex/) { &treat("$help\@$1"); if ($apropos && $#list > 0 || $#sentence_list > 0) { print "\nChapter $1:\n"; print "==========\n"; &apropos_final_print(); } } } if (!$found && !$apropos) { print "$help $notfound"; return } $searchall = 0; $apropos = 0; return; } &choose_chap; if (!$apropos) { open_dvi_then_quit("users.dvi") if (/^$/); open_dvi_then_quit("tutorial.dvi") if (/^tutorial$/); open_dvi_then_quit("refcard.dvi") if (/^refcard$/); } if (!$apropos && $transl{$_}) { $_ = $transl{$_}; &choose_chap; } s/(\W)/\\$1/g; ($pipe && open(DOC,"$pipe $docfile |")) || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!"; return &apropos($_) if ($apropos); if (/^\\[<>=!]=?|[|&]{1,2}$/) { $_ = 'Comparison and boolean operators'; } $help = $_; while () { if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){$help}/) { $first = $_; last; } } if (eof(DOC) && !$searchall) { print "$help $notfound"; return } $found = 1; if (!$detex) { &tex(); return; } &detex(); print "\n" if (!$fromgp); close(DOC); } # # A propos # sub apropos_print_list { $current = ""; @_ = sort(@_); for (@_) { next if ($_ eq $current); $current = $_; print "$indent$_\n"; } } sub apropos_raw_print { $indent = ""; &apropos_print_list(@sentence_list); &apropos_print_list(@list); } sub apropos_final_print { local($maxlen) = 0; local($i,$nbcol,$current); local($cols) = ($ENV{'COLUMNS'} || 80) - 1; if ($raw) { &apropos_raw_print(); return; } @list = sort(@list); for (@list) { $i= length($_); $maxlen = $i if ($i > $maxlen); } $maxlen++; $nbcol = $cols / $maxlen; $nbcol =~ s/\..*//; $nbcol-- if ($nbcol * $maxlen == $cols); $nbcol = 1 if (!$nbcol); $current = ""; $i = 0; for (@list) { next if ($_ eq $current); $current = $_; print($_); $i++; if ($i >= $nbcol) { $i=0; print "\n"; next; } print " " x ($maxlen - length($_)); } print "\n" if ($i); if ($#sentence_list > 0) { print "\nSee also:\n" if ($#list > 0); $indent = " "; apropos_print_list(@sentence_list); } } sub apropos_check { local($_) = $line; s/\n/ /g; return if (! /$help/); $_ = $current; s/\{\}//g; s/\}.*//; s/\\pow/^/; s/\\%/%/; s/\\bs/\\/; s/\\\#/\#/g; s,\+\$/\$-,+/-,; if (/ /) { push(@sentence_list,$_); } else { push(@list,$_); } } sub apropos { local($line,$current,$new); $help = $_[0]; $help='\\\\pow' if ($help eq '\^'); $help='\\\\til' if ($help eq '\~'); @sentence_list = @list = ""; while () { if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){(.*)}/) { $new = $2; &apropos_check(); $current = $new; $line = ""; } $line .= $_; } &apropos_check(); } # # Tex Part # sub pretex { open(TEX,">$texfile.tex") || die "Couldn't open $texfile.tex"; print TEX << "EOT"; \\def\\fromgphelp\{\} \\input $docdir/parimacro.tex EOT } sub tex { print TEX "$first";; while () { last if /^\\(section|sub[sub]*sec)/i; print TEX; } close(DOC); } sub posttex { print TEX "\\vfill\\eject\\bye"; close(TEX); chdir($tmpdir); system("tex $texfile.tex 2>/dev/null > /dev/null < /dev/null") == 0 || die "could not process $texfile.dvi" if (! -f "$texfile.dvi"); system("($xdvi $texfile.dvi 2>/dev/null >/dev/null; rm -f $texfile.tex $texfile.dvi $texfile.log)&"); &handler(1); } sub clean { unlink("$texfile.tex","$texfile.dvi","$texfile.log"); } sub handler { &clean if (!$_[0]); $SIG{'INT'} = 'DEFAULT'; $SIG{'QUIT'} = 'DEFAULT'; } # # Detex Part # sub fit_loop { return if ($miss > 9); while ($miss > 0) { # print "1:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;])$/$1 /); return if ($miss == 0); } # print "2:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;]) $/$1 /); return if ($miss == 0); } # print "3:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([\),])$/$1 /); return if ($miss == 0); } # print "4:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/^\(/ (/); return if ($miss == 0); } # print "5:$miss "; print @_;print "\n"; for (@_) { $miss--; s/$/ /; return if ($miss == 0); } } } sub fit_line { local($wi, @a); local($l) = -1; local($rem) = $_[0]; for (@l) { $l2 = $l; $l += ($_ + 1); last if ($l > $rem); $wi++; } $miss = $rem - $l2; splice(@l, 0, $wi); @a = splice(@w, 0, $wi-1); &fit_loop(@a); push(@a, shift(@w)); return join(' ', @a); } sub format_text { local($last_void) = 0; local($cols) = ($ENV{'COLUMNS'} || 80) - 1; local($first) = $cols - length($indent); for (@text) { if (s/^\@9//) { push(@f_text, "\n$indent" . &fit_line($first)) if (!$last_void); push(@f_text, "") if (/^\@\[startbold\]/); push(@f_text, "$indent$_"); $last_void=1; } elsif (/^[\t ]*$/ || /^[\t ]*@\[\w+\][\t ]*$/) { next if ($last_void); $last_void=1; push(@f_text, "\n\@[endbold]$indent" . &fit_line($first)) if (@w); while (@w) { push(@f_text, &fit_line($cols)); } } else { $last_void = 0 ; @_ = split(/ /, $_); for (@_) { s/\Q$tr{nbrk}/ /g; push(@w, $_); s/\@\[\w+\]//g; push(@l, length($_)); } } } } sub detex { s/^\\[a-z][^\{]*\{//; &presubst(); if (/([^\}]*)\.*\}\.*([^:\n]*)[ :.]*/) { if ($raw) { print("\@[startbold]$1\@[endbold]$2: "); } else { &TeXprint("\@[startbold]$1\@[endbold]$2:"); } $_ = $'; } push(@text, $_); while () { last if /^\\(section|sub[sub]*sec)/i; &presubst(); push(@text, $_); } if ($raw) { print join("\n", @text); return; } &format_text(); for (@f_text) { &TeXprint("$_"); } } # We use the special char @ to transmit special sequences sub inittr { @ou = qw( dollar nbrk startbold endbold startcode endcode startpodcode endpodcode startbcode endbcode startbi endbi startit endit startword endword startlword endlword pm empty gt lt podleader ); @tr{@ou} = map "\@[$_]", @ou; $tr{dollar} = '$' if $to_pod; %pr = ( dollar => '', nbrk => 'S< >', startbold => 'B<', endbold => '>', startcode => 'C<', endcode => '>', startpodcode => 'C<', endpodcode => '>', startbcode => 'B '>>', startbi => 'B '>>', startit => 'I<', endit => '>', startword => 'F<', endword => '>', startlword => ' F<', endlword => '> ', pm => 'F<+->', gt => 'E', lt => 'E', empty => 'Z<>', podleader => '=', ); } sub presubst { chop unless $to_pod; s/\\\\(?=[a-zA-Z])/\\bs /g; s/\\\\/\\bs/g; s/(\'\'|\`\`)/"/g unless $to_pod; # " # asymptotic or equivalent (~) s/(^|[^\\]) +~/$1~/; s/~ */~/; s/(^|[^\\])~/$1$tr{nbrk}/g; s/\\(simeq|sim|approx|equiv)(?![a-zA-Z])/ ~ /g; s/(^|[^\\])%.*/$1/g; # comments s/\$\\bf(\b|(?=[\d_]))\s*([^\$]+)\$/\$$tr{startbcode}$1$tr{endbcode}\$/g; s/\$/$tr{dollar}/g; # math mode s/\t/ /g; s/\\,//g; s/\\[ ;]/ /g;# various spaces s/\\til(?![a-zA-Z])/~/g; # ~ s/\\~/~/g; s/\\tilde/~/g; s/\\\///g; # italic correction s/([^\\])&+/$1/g; # tab marks s/\\TeX\{\}/TeX/g; s/\\TeX(\W)/TeX$1/g; s/ *\\circ\b */ o /g; # \def\synt#1#2{\syn{#1}{\tt #2}} # \def\syn#1#2{\synx{#1}{#2}{#1}} s/\\synt?\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\synx{$1}{$2}{$1}/g; # \def\synx#1#2#3{\sidx{#3}The library syntax is $\key{#1}({#2})$} # Often used with embedded {}. s/\\synx\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{((?:[^{}]|\{[^{}]*\})*)\}/\\sidx{$3}The library syntax is $tr{startbold}$1$tr{endbold}$tr{startpodcode}($2)$tr{endpodcode}/; # May be used with an empty arg s/\\typ\{([^\}]*)\}/$tr{startcode}t_$1$tr{endcode}/g; s/\{ *\}//g; # empty args s/(\\string)?\\_/_/g; s/\\([#\$&%|])/$1/g; s/\\(hat(?![a-zA-Z])|\^)({\\?\s*})?/^/g; s/ *\\pow(?![a-zA-z]) */^/g; s/\\neq?(?![a-zA-Z])/ != /g; s/\\enspace(?![a-zA-Z])/ /g; s/\\times(?![a-zA-Z]) */ x /g; s/\\infty(?![a-zA-Z]) */oo /g; s/ *\\(bmod|mod) */ mod /g; s/ *\\pmod(?![a-zA-Z]) *\{\s*((?:[^{}]|\{[^{}]*\})*)\}/ (mod $1)/g; s/ *\\cdot(?![a-zA-Z]) */./g; # Maybe " . "? s/ *\\[lc]?dots(?![a-zA-Z]) */.../g; s/\\(log|sin|cos|lim|tan|mod|sqrt|exp|ln|det|Re|Im|deg|wp)(?![a-zA-Z])/$tr{startlword}$1$tr{endlword}/g; s/\\pi(?![a-zA-Z])/$tr{startword}Pi$tr{endword}/g; s/\\(Alpha | Beta | Chi | Delta | Epsilon | Phi | Gamma | Eta | Iota | vartheta | Kappa | Lambda | Mu | Nu | Omicron | Pi | Theta | Rho | Sigma | Tau | Ypsilon | varsigma | Omega | Xi | Psi | Zeta | alpha | beta | chi | delta | varepsilon | phi | gamma | eta | iota | varphi | kappa | lambda | mu | nu | omicron | pi | theta | rho | sigma | tau | ypsilon | varpi | omega | xi | psi | zeta | int | expr | seq | args | gcd | sum | prod | Re | infty ) (?![a-zA-Z])/$tr{startword}$1$tr{endword}/xg; s/ *\\in(?![a-zA-Z]) */ belongs to /g; s/\\pm(?![a-zA-Z])/$tr{pm}/g; s/ *\\mid(?![a-zA-Z]) */ | /g; s/^\\def\\.*\{\n.*\n\}//gm; s/\\def\\.*//; s/\\idxtyp\{[^\}]*\}//g; s/\\ref\{[^\}]*\}/$tr{startbold}??$tr{endbold}/g unless $to_pod; s/\\secref\{[^\}]*\}/Section ($tr{startbold}??$tr{endbold})/g unless $to_pod; s/\\label\{[^\}]*\}//g unless $to_pod; s/\\(text|hbox)//g; s/\\rightarrow(?![a-zA-Z])/C<--E>/g; s/\\longleftrightarrow(?![a-zA-Z])/C-----E>/g; s/\\(noindent|medskip|bigskip|smallskip|left|right)(?![a-zA-Z])[ \t]*//g; s/\\vfill *\\eject//g; s/\\(q|quad)(?![a-zA-Z])/ /g; s/\\qquad(?![a-zA-Z])/ /g; s/\\centerline\b/ /g; s/\\big\b//g; s/\\settabs.*//; s/\\\+//g; s/\\cr(?![a-zA-Z])//g; s/ *\\leq?(?![a-zA-Z]) *([^ ])/<=$1/g; s/ *\\geq?(?![a-zA-Z]) *([^ ])/>=$1/g; s/ *([=><]) */ $1 /g; s/ *< *([=<]) */ <$1 /g; s/ *> *([=>]) */ >$1 /g; s/ *= *= */ == /g; s/\\(vers|PARIversion)(?![a-zA-Z])/$tr{startbold}$version$tr{endbold}/; s/\\([QRCFZNapdf])(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g; s/\\([QRCFZN])\1(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g; s/\\Bbb\b\s*(\w)/$tr{startbi}$1$tr{endbi}/g; s/\\obr/{/g; s/\\cbr/}/g; s/\\quo(?![a-zA-Z])/\"/g; s/(^|\s)\{(\w+)\}/$1$2/g; s/\\p(?![a-zA-Z])/$tr{startbold}p$tr{endbold}$1/g; s/\\point\{([^\}]*)\}/$tr{startbold}* $1$tr{endbold}/g; s/\\bullet/$tr{startbold}*$tr{endbold}/g; s/\\misctitle\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g; s/\\subsec\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g unless $to_pod; s/\\teb\{([^\}]*)\}/\\sidx{$1}$tr{startbold}$1$tr{endbold}/g; s/\\tet\{([^\}]*)\}/\\sidx{$1}$tr{startcode}$1$tr{endcode}/g; s/\\tec\{\s*([^{}]*)\}\{\s*([^{}]*)\}/\\sidx{$1}$1$tr{startcode}$2$tr{endcode}/g; s/\\kbd\{((?:[^{}]|\{[^{}]*\})*)\}/$tr{startcode}$1$tr{endcode}/g; s/\\key\{([^\}]*)\}/$tr{startbold}$1$tr{endbold}/g; s/\\var\{([^\}]*)\}/$tr{startit}$1$tr{endit}/g; s/\\fl(?![a-zA-Z])/$tr{startit}flag$tr{endit}/g; s/\\b{([^}]*)}/$tr{startcode}\\$1$tr{endcode}/g; s/\\sidx\{[^\}]*\}//g unless $to_pod; s/\\[a-zA-Z]*idx\{([^\}]*)\}/$1/g unless $to_pod; s/\{ *\\(it|sl) *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startit}$2$tr{endit}/g; s/\{ *\\bf *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startbold}$1$tr{endbold}/g; s/\{ *\\tt *(([^{}]+(?=[{}])|\{[^{}]+\})*)\}/$tr{startpodcode}$1$tr{endpodcode}/g; $seek=1 if (s/\{ *\\it */$tr{startit}/g); if ($seek) { $seek=0 if (s/\}/$tr{endit}/) } s/\\(backslash|bs)\{(\w)\}/\\$2/g; s/\\(backslash|bs)(?![a-zA-Z]) */\\/g; return if $to_pod; $in_prog = 0 if (s/\\eprog/$tr{endbold}/g); if ($in_prog || s/\\bprog(tabs.*)?//g) { $in_prog++; s/^/\@9$tr{startbold}/ if ($in_prog==2); s/^/\@9/ if ($in_prog>2); } } sub wrap_code { my $in = shift; $in =~ s/^[ \t]+$//mg; # if ($in =~ /[A-Z]$1/mg; # } else { $in =~ s/^(.)/ $1/mg; # } $in } sub rewrap_code { # This code got some escapes inside... my $in = shift; $in =~ s/((^|\n\n)[ \t]+(.|\n(?!\n))*[A-Z]<(.|\n(?!\n))*)/rewrap_lines($1)/e; $in } sub rewrap_lines { # This code got some escapes inside... my $in = shift; $in =~ s/^([ \t]+)(.*)/\nS<$1>$2\n/mg; $in } sub indexify { my $in = shift; $in =~ s/(^|and\s+)(\w+)(\$?\()/$1\\idx{$2}$3/g; $in; } sub TeXprint_topod { s/\A\s+//; s/^\\def\\.*\{\n.*\n\}//gm; s/\\def\\.*//; # Repeated in presubst # \def\sectype#1#2{\subsec{Type \typ{#1} (#2s):}\sidx{#2}} # \def\sectypeindex#1#2#3{\subsec{Type \typ{#1} (#2):}\sidx{#3}} # \def\sectypes#1#2#3{\subsec{Types \typ{#1} and \typ{#2} (#3s):}\sidx{#3}} # \n is below to prevent splitting on ' ' # We also remove ':' s/\\sectype\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$2}/g; s/\\sectypeindex\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$3}/g; s/\\sectypes\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} and \\typ{$1} (${3}s)}\n\\sidx{$3}/g; # Try to guard \label/\sidx (removing possible '.') s/(\\(?:section|subsec(?:ref|idx|op)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/; # last if /\\subsec[\\{}ref]*[\\\${]$help[}\\\$]/o; s/\\chapter\s*{((?:[^{}]|\{[^{}]*\})*)}/\n\n$tr{podleader}head1 NAME\n\nlibPARI - $1\n\n$tr{podleader}head1 DESCRIPTION\n\n/; s/\\section\s*{((?:[^{}]|\{[^{}]*\})*)}/"\n\n$tr{podleader}head1 " . indexify($1) . "\n\n"/e; # Try to delimit by : s/\\subsec(?:ref|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^\n:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec(?:ref|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}item " . indexify("$1$3") . "\n\n"/e; # Try to delimit by ' ' s/\\subsec(?:ref|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsec(?:ref|title|idx|op)?\s*{(([^{}]+(?=[{}])|{[^{}]*})+)}:?\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e; # This is to skip preface in refcard: /\Q$tr{podleader}\Ehead1|\\title(?![a-zA-Z])\s*\{/ and $seen_start = 1 or $seen_start or return; # Skip now! s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?/$tr{podleader}head1 NAME\n\n$1 - $3. $5\n\n/ and $seen_title++ unless $seen_title; s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?/\n\n/; s/\\parskip.*/\n/g; # Up to end of the line #s/([A-Z])\>/g; # s/\\p(\b|(?=[\d_]))/B

/g; #s/\$\\bf\b\s*([^\$]+)\$/C>/g; @lines = split /^$/m, $_; for (@lines) { s/>/\@[gt]/g unless /^\s/; s/C<$1>\n\n/gs; s/\$([^\$]+)\$/C<$1>/g; s/\\d?frac{\s*((?:[^{}]|\{[^{}]*\})*)}{\s*((?:[^{}]|\{[^{}]*\})*)}/($1)\/($2)/g; s/\\s(?:ref|idx){\s*([^{}]*)}/X<$1>/g; # s/\\(?:ref|idx){\s*([^{}]*)}/X<$1>$1/g; # s/\\(backslash|bs)\s*(\b|(?=[\d_]|C\<))/\\Z<>/g; # s/\\bmod\b/ mod /g; #s/\\pm(\b|(?=[\d_]))/F<+->/g; #s/\\noindent(\b|(?=[\d_]))/ /g; # Conflict between different versions of PARI and refcard: s/\\(?:key|li)(?![a-zA-Z])\s*{(.*)}\s*{(.+)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg; s/\\(?:key|li)(?![a-zA-Z])\s*{(.*)}\s*{}[ \t]*\n/\n\n=back\n\n$1\n\n=over\n\n/mg; s/\\(key|var)(?![a-zA-Z])\s*{(\w+)}/C<$2>/mg; s/\\var(?![a-zA-Z])\s*{X<(\w+)>(\w+)}/X<$1>C<$2>/mg; s/\\var(?![a-zA-Z])\s*{f{}lag}/C/mg; s/\\metax(?![a-zA-Z])\s*{(.*)}\s*{\s*(\w+)(?=C\<)(.*)}[ \t]*\n/\n\n=item C$3>\n\n$1\n\n/mg; s/\\metax(?![a-zA-Z])\s*{(.*)}\s*{(.*)}[ \t]*\n/\n\n=item C<$2>\n\n$1\n\n/mg; s/C\<\{\}=/C\<=/g; s/\\fl(?![a-zA-Z])/I/g; s/\\file(?![a-zA-Z])/F/g; s/\\label\s*\{([\w:.-]*)\}/X