(* :Title: TeX Tools *) (* :Context: TeXTools` *) (* :Author: Eric Rowland *) (* http://math.rutgers.edu/~erowland *) (* :Date: {2009, 5, 16} *) (* :Package Version: 1.15 *) (* :Mathematica Version: 7.0 *) (* :Discussion: This package is a collection of tools to assist writing papers in LaTeX. *) BeginPackage["TeXTools`"] $FiguresDirectory::usage = "$FiguresDirectory gives the current directory where graphics files are exported by default." $SourceDirectory::usage = "$SourceDirectory gives the current directory where LaTeX source files are read by default." ExportFigure::usage = "ExportFigure[\"file\", graphics] exports graphics as both \"file.eps\" and \"file.pdf\" in the directory given by $SourceDirectory." MisspelledWords::usage = "MisspelledWords[\"file\"] gives a list of misspelled words, along with the corresponding line numbers, in a file. MisspelledWords[] finds misspelled words in \"paper.tex\"." SymbolReplace::usage = "SymbolReplace[\"file\", \"newfile\", symbol \[Rule] newsymbol] renames a variable in all math environments in a TeX source file, and exports the result to a new file. SymbolReplace[\"file\", symbol \[Rule] newsymbol] exports the result to the original file after making a copy." TeXCompile::usage = "TeXCompile[\"file\", \"ext\"] compiles the source file \"file.tex\" to \"file.ext\". TeXCompile[\"file\"] compiles \"file.tex\" to \"file.dvi\". TeXTeXCompile[] compiles \"paper.tex\" to \"paper.dvi\"." TeXOpen::usage = "TeXOpen[\"file\"] opens the files \"file.tex\" and \"file.dvi\", as well as a command prompt for compiling the source. TeXOpen[] opens \"paper.tex\" and \"paper.dvi\"." TeXTableForm::usage = "TeXTableForm[array] gives the TeX format of a two\[Hyphen]dimensional table \*StyleBox[\"array\", \"TI\"]. The options Alignment and TableHeadings can be given." Unprotect["TeXTools`*"] Begin["`Private`"] $AbbreviationDictionary = { "NKS", "NSF" } $LatinDictionary = { "etc", "mutandis", "priori", "versa" } $MathDictionary = { "additivity", "adic", "adically", "advisor", "ansatz", "ansatzes", "antiderivative", "associahedron", "autocorrelation", "autocorrelations", "automata", "bijection", "bijections", "bijective", "bijectively", "bijectivity", "combinatorially", "combinatorics", "componentwise", "conjecturally", "coprime", "equinumerous", "formulae", "holonomic", "homotopic", "hypergeometric", "modulo", "monic", "multiset", "nestedness", "nondecreasing", "nonnegative", "nonperiodic", "parameterized", "polytope", "preprint", "proven", "subgraph", "subpatterns", "subsequence", "subsequences", "substring", "substrings", "subword", "subwords", "summand", "summands", "superfactorial", "totient", "tuple", "vertices" } $PeopleDictionary = { "Allouche", "Amdeberhan", "Benoit", "Borwein", "Bruijn", "Bumby", "Callan", "Cayley", "Cloitre", "Collatz", "Deutsch", "Doron", "Dyck", "Elkies", "Emeric", "Flajolet", "Gessel", "Golomb", "Goulden", "Harary", "Kimberling", "Koblitz", "Kolakoski", "Kupin", "Lehmer", "MacMahon", "Matiyasevich", "Mazur", "Mordell", "Motzkin", "Noonan", "Ostrowski", "Phillipe", "Pitman", "Plouffe", "Poorten", "Prins", "Pudwell", "Ribenboim", "Sedgewick", "Shallit", "Silverman", "Sipala", "Steyaert", "Tewodros", "Tutte", "Vandermonde", "Wilf", "Zeilberger" } $PlaceDictionary = { "Champaign", "Piscataway" } If[!ValueQ[$SourceDirectory], $SourceDirectory = Quiet[NotebookDirectory[], NotebookDirectory::nosv] /. $Failed -> $InitialDirectory ] If[!ValueQ[$FiguresDirectory], $FiguresDirectory := FileNameJoin[{$SourceDirectory, "figures"}]] filename[file_, extension_ : "tex", OptionsPattern[]] := If[StringMatchQ[file, ___ ~~ $PathnameSeparator ~~ ___], file, FileNameJoin[{ If[TrueQ[OptionValue[Graphics]], $FiguresDirectory, $SourceDirectory], file <> If[ StringMatchQ[file, ___ ~~ "." <> extension], "", "." <> extension ] }] ] Options[filename] = {Graphics -> False} MatchPairs[string_String, openpattern_, closepattern_] := Module[{openpositions, closepositions, positions = {}, stack = {}}, openpositions = StringPosition[string, openpattern]; closepositions = StringPosition[string, closepattern]; Function[p, If[stack == {}, If[MemberQ[openpositions, p], AppendTo[stack, p], AppendTo[positions, {Null, p}] ], If[MemberQ[closepositions, p], AppendTo[positions, {Last[stack], p}]; stack = Most[stack], AppendTo[stack, p] ] ] ] /@ Union[openpositions, closepositions]; Join[ positions, {#, Null} & /@ stack ] ] StringReplaceRepeated[ s_String, rules : _Rule | _RuleDelayed | {(_Rule | _RuleDelayed) ...} ] := FixedPoint[StringReplace[#, rules] &, s] ExportFigure[file_String, graphics_] := { Export[filename[file, "eps", Graphics -> True], graphics], Export[filename[file, "pdf", Graphics -> True], graphics] } SyntaxInformation[ExportFigure] = {"ArgumentsPattern" -> {_, _}} MisspelledWords[file_String : "paper"] := Module[{text = StringReplace[Import[filename[file], "Text"], "~" -> " "], misspelledwords}, misspelledwords = Select[ DeleteDuplicates[Select[ StringReplace[#, StringExpression[ StartOfString, prefix : (Except[LetterCharacter] ...), word : (LetterCharacter ..), suffix : (Except[LetterCharacter] ...), EndOfString ] :> If[StringMatchQ[prefix, ___ ~~ "\\"], "", word] ] & /@ StringSplit[text], StringMatchQ[#, LetterCharacter ..] & ]], StringLength[#] > 2 && DictionaryLookup[#, IgnoreCase -> True] == {} && !MemberQ[$MathDictionary, ToLowerCase[#]] && !MemberQ[Join[$AbbreviationDictionary, $LatinDictionary, $PeopleDictionary, $PlaceDictionary], #] & ]; {#[[1, 1]], Last /@ #} & /@ GatherBy[Flatten[Thread /@ DeleteCases[ MapIndexed[ Function[{line, index}, { StringCases[ line, StringExpression[ StartOfString | Except[LetterCharacter], word : Alternatives @@ misspelledwords, EndOfString | Except[LetterCharacter] ] :> word, Overlaps -> True ], First[index] }], StringSplit[text, "\n"] ], {{}, _} ], 1], First] ] SyntaxInformation[MisspelledWords] = {"ArgumentsPattern" -> {_.}} SymbolReplace[f_String, rule : (_String -> _String)] := With[{file = filename[f]}, Quiet[DeleteFile[file <> "~"], DeleteFile::nffil]; CopyFile[file, file <> "~"]; SymbolReplace[file, file, rule] ] SymbolReplace[file_String, newfile_String, symbol_String -> newsymbol_String] := Module[{string = Import[filename[file], "Text"], pairs}, pairs = {#[[1, 1]], #[[2, 2]]} & /@ MatchPairs[ string, (* TODO add multline, multline*, etc. *) "\\begin{math}" | "\\(" | "$" | "\\begin{displaymath}" | "\\[" | "$$" | "\\begin{equation}" | (*"\\begin{equation*}" |*) "\\begin{align}" | "\\begin{align*}" | "\\begin{eqnarray}" (*| "\\begin{eqnarray*}"*), "\\end{math}" | "\\)" | "$" | "\\end{displaymath}" | "\\]" | "$$" | "\\end{equation}" | (*"\\end{equation*}" |*) "\\end{align}" | "\\end{align*}" | "\\end{eqnarray}" (*| "\\end{eqnarray*}"*) ]; Export[ filename[newfile], StringReplacePart[ string, StringReplaceRepeated[ StringTake[string, #], a : Except[LetterCharacter] ~~ symbol ~~ z : Except[LetterCharacter] :> a <> newsymbol <> z ] & /@ pairs, pairs ], "Text" ] ] SyntaxInformation[SymbolReplace] = {"ArgumentsPattern" -> {_, _, _.}} TeXCompile[file_String : "paper"] := TeXCompile[file, "dvi"] TeXCompile[file_String, "dvi"] := ( Run[ "cd", "\"" <> $SourceDirectory <> "\"", "&&", "latex", "\"" <> filename[file] <> "\"" ]; ) TeXCompile[file_String, "pdf"] := ( Run[ "cd", "\"" <> $SourceDirectory <> "\"", "&&", "pdflatex", "\"" <> filename[file] <> "\"" ]; ) TeXCompile[file_String, "ps"] := ( TeXCompile[file, "dvi"]; Run[ "cd", "\"" <> $SourceDirectory <> "\"", "&&", "dvips", "\"" <> filename[file, "dvi"] <> "\"" ]; ) SyntaxInformation[TeXCompile] = {"ArgumentsPattern" -> {_., _.}} TeXOpen[file_String : "paper"] := ( SystemOpen[filename[file]]; Pause[.05]; Run["start cmd /k cd", $SourceDirectory]; SystemOpen[filename[file, "dvi"]]; ) SyntaxInformation[TeXOpen] = {"ArgumentsPattern" -> {_.}} TeXTableForm[list : {___List}, OptionsPattern[]] := Module[{table = list, columnalignments, rowheadings, columnheadings, columncount}, {rowheadings, columnheadings} = Replace[ OptionValue[TableHeadings], {labels : {_, _} :> labels, {r_} :> {r, None}, _ -> {None, None}} ]; If[ListQ[rowheadings], table = Join @@@ Transpose[{List /@ PadRight[rowheadings, Length[table], Null], table}] ]; columncount = Max[Length /@ table]; If[ListQ[columnheadings], PrependTo[table, PadRight[Join[If[ListQ[rowheadings], {Null}, {}], columnheadings], columncount, Null]] ]; columnalignments = StringJoin[Replace[ Replace[ OptionValue[Alignment], { {h_List, ___} :> PadRight[Join[If[ListQ[rowheadings], {Center}, {}], h], columncount, Center], h : Except[_List] :> ConstantArray[h, columncount], _ :> ConstantArray[Center, columncount] } ], {Left -> "l", Right -> "r", _ -> "c"}, {1} ]]; If[ListQ[rowheadings], columnalignments = StringInsert[columnalignments, "|", 2]]; table = Riffle[ StringJoin[Riffle[#, " & "]] & /@ Map[ToString[Replace[#, Null -> ""], TeXForm] &, table, {2}], " \\\\\n" ]; If[ListQ[columnheadings], table = ReplacePart[table, 2 -> " \\\\ \\hline\n"]]; StringJoin[ "\<", "\\[\n\\begin{array}{", columnalignments, "}\n", table, "\n\\end{array}\n\\]", "\>" ] ] Options[TeXTableForm] = {Alignment -> Center, TableHeadings -> None} SyntaxInformation[TeXTableForm] = {"ArgumentsPattern" -> {{__}, OptionsPattern[]}} End[] Protect["TeXTools`*"] Unprotect[$FiguresDirectory, $SourceDirectory] EndPackage[]