module Language.LaTeX.Builder ( (!$), (!$?), ($?), HaveC(..), HaveL(..), HaveR(..), Spaces(..), -- * Injecting declarations decl, decls, parDecls, parDecl, -- * Others _AA, _AE, _H, _Huge, _L, _LARGE, _LaTeX, _Large, _O, _OE, _P, _S, _TeX, _l, XChar, a4paper, aa, acute, addvspace, ae, allTexDecls, appendix, article, author, authors, bf, bfseries, bigskip, bibliography, bibliographystyle, book, boxedminipage, caption, caption', cedil, cell, cells, center, chapter, chapter', check, circ, cite, cite', cleardoublepage, clearpage, cline, comment, compressSpaces, copyright, corrspace, dag, dash1, dash2, dash3, date, ddag, description, displaymath, document, documentclass, dot, dotfill, dquote, em, emph, enumerate, fbox, figure, flushleft, footnote, footnotesize, framebox, fussy, grave, group, hat, hchar, hfill, hline, hr, href, hrulefill, space, hspace, hspace', hspaces, hstring, huge, hyphen, hyphenation, hyphenationPar, i, institute, it, item, item', itemize, itshape, j, label, large, ldots, letter, linebreak, linebr, lq, ldq, makebox, maketitle, math, mbox, mdseries, medskip, minipage, nbsp, negthinspace, newline, rawNewline, newpage, nocite, noindent, nolinebreak, nopagebreak, normalfont, normalmarginpar, normalsize, num, o, oe, overbar, overdot, pagebreak, pageref, pagestyle, para, paragraph, paragraph', parbox, part, part', person, phantom, pounds, protect, protector, quotation, quote, raisebox, raisebox', rat, ref, report, reversemarginpar, ring, rm, rmfamily, rq, rdq, rtext, rule, rule', samepage, savebox, sbox, sc, scriptsize, scshape, section, section', sep, setlength, addtolength, settowidth, sf, sffamily, sl, sloppy, sloppypar, slshape, small, smallskip, spaceProtector, ss, subparagraph, subparagraph', subsection, subsection', subsubsection, subsubsection', subtitle, table, tableofcontents, tabular, textbf, textdegree, textit, textmd, textnormal, textrm, textsc, textsf, textsl, texttt, textup, textsuperscript, textsubscript, textunderscore, thinspace, thispagestyle, tieafter, tilde, tiny, title, titlepage, tt, ttchar, ttfamily, uml, underbar, unwords, upshape, usebox, verb, verse, vfill, vline, vphantom, vspace, vspace', (★), vbox, vtop, hbox, here, top, bot, bottom, page, normal, centered, flushLeft, flushRight, stretch, -- * Input Encodings (inputenc package) utf8,latin1,inputenc,fromEncoding, ) where import Prelude hiding (sqrt, min, max, lcm, gcd, log, mod, tanh, cosh, tan, sinh, sin, cos, succ, sum, pi, mapM, unwords) import Data.List hiding (sum, and, group, unwords) import qualified Data.List as L import Data.Ratio import Data.Monoid import Data.Char import Data.Maybe import Data.Foldable (foldMap) import Data.Traversable import Data.String (IsString(..)) import Control.Applicative hiding (optional) import Control.Monad hiding (mapM) import Control.Monad.Error (throwError) import Control.Monad.Writer (Writer, execWriter, tell) import Control.Arrow import Language.LaTeX.Types import Language.LaTeX.Builder.Internal import qualified Language.LaTeX.Length as L import Language.LaTeX.Builder.MonoidUtils {- import Prelude (writeFile, id, Monad(..), fst) import Language.Haskell.TH -} -- references: http://dmr.ath.cx/notes/tex.html (★) :: Star (★) = Star group :: LatexItem -> LatexItem group = liftM TexGroup infixr 0 !$ infixr 0 $? infixr 0 !$? (!$) :: Monoid b => (a -> b) -> a -> Writer b () (!$) f x = tell $ f x ($?) :: (a -> b) -> Writer a () -> b ($?) f m = f $ execWriter m -- NOTE: This combinator seems pretty promising... (!$?) :: Monoid b => (a -> b) -> Writer a () -> Writer b () (!$?) f m = tell $ f $ execWriter m math :: MathItem -> LatexItem math = latexCast . mathItem displaymath :: MathItem -> ParItem displaymath = parCast . mathItem decls :: [TexDecl] -> LatexItem -> LatexItem decls ds x = group (rawDecls ds ⊕ x) decl :: TexDecl -> LatexItem -> LatexItem decl = decls . pure parDecls :: [TexDecl] -> ParItem parDecls = para . rawDecls parDecl :: TexDecl -> ParItem parDecl = parDecls . pure document :: DocumentClass -> PreambleItem -> ParItem -> LatexM Document document = liftM3 Document dash1, dash2, dash3, nbsp :: LatexItem dash1 = rawTex "{-}" dash2 = rawTex "{--}" dash3 = rawTex "{---}" nbsp = rawTex "{~}" -- Do we want to treat '\160' as an nbsp too? -- | 'sep' is like '{}' in LaTeX, it allows to force letters to be treaten separately, -- for instance to separate the two 'f's in shelfful. sep :: LatexItem sep = group ø {- GHC bug with OverloadedStrings f "" = 1 f ('a':_) = 2 f _ = 3 -} newtype Spaces = Spaces { countSpaces :: Int } hspaces :: Spaces -> LatexItem hspaces = mbox . hspace . L.em . (1%2 *) . fromIntegral . countSpaces compressSpaces :: String -> [Either Char Spaces] compressSpaces [] = [] compressSpaces (' ':xs) = uncurry (:) . (Right . Spaces . (+1) . length *** compressSpaces) . span (==' ') $ xs compressSpaces (x:xs) = Left x : compressSpaces xs type XChar = Char -> LatexItem spaceProtector :: XChar -> String -> LatexItem spaceProtector xchar = foldMap (either xchar hspaces) . compressSpaces protector :: XChar -> String -> LatexItem protector = spaceProtector . nlchar protect :: String -> LatexItem protect = protector hchar -- Turns @'\n'@ into 'newline' and others with the given translator. nlchar :: XChar -> XChar nlchar _ '\n' = rawNewline ø nlchar xchar ch = xchar ch hchar :: XChar hchar = rawTex . rawhchar ttchar :: XChar ttchar ch | isAscii ch && isPrint ch && not (isAlphaNum ch) = rawTex $ "{\\char `\\" ++ ch : "}" | isAscii ch && not (isPrint ch) = verb . show $ ch | otherwise = rawTex [ch] verb :: String -> LatexItem verb = texttt . protector ttchar -- A comment put in the generated LaTeX document comment :: String -> LatexItem comment s = latexNote (MkKey "comment") (stringNote s) ø href :: LatexItem -> LatexItem -> LatexItem href x y = latexCmdArgs "href" [mandatory x,mandatory y] person :: String -> String -> LatexItem person name email = href (hstring ("mailto:"++email)) (hstring name) -- simulate the
html tag hr :: LatexItem hr = group $ noindent ⊕ rule L.linewidth (L.pt 1.5) hstring :: String -> LatexItem hstring = fromString tableofcontents :: ParItem tableofcontents = parCmdArgs "tableofcontents" [] maketitle :: ParItem maketitle = parCmdArgs "maketitle" [] -- par = texCmdNoArg "par" noindent :: LatexItem noindent = texCmdNoArg "noindent" -- Marginal Notes reversemarginpar :: TexDecl reversemarginpar = texDecl "reversemarginpar" normalmarginpar :: TexDecl normalmarginpar = texDecl "normalmarginpar" -- The tabbing Environment -- TODO -- Spaces -- robust -- http://www.personal.ceu.hu/tex/spacebox.htm#hspace hspace' :: Star -> LatexLength -> LatexItem hspace' s = latexCmdAnyArg (starize "hspace" s) . texLength -- robust -- http://www.personal.ceu.hu/tex/spacebox.htm#hspace hspace :: LatexLength -> LatexItem hspace = hspace' ø -- fragile -- they says that's a command however putting braces around disable -- its effect. We expose it as a ParItem since this is its main usage. -- http://www.personal.ceu.hu/tex/spacebox.htm#vspace vspace' :: Star -> LatexLength -> ParItem vspace' s = parCmdArg (starize "vspace" s) . texLength -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#vspace vspace :: LatexLength -> ParItem vspace = vspace' ø -- http://www.personal.ceu.hu/tex/spacebox.htm#vfill vfill :: ParItem vfill = parCmdArgs "vfill" [] -- = vspace fill -- http://www.personal.ceu.hu/tex/spacebox.htm#hfill hfill :: LatexItem hfill = texCmdNoArg "hfill" -- = hspace fill dotfill :: LatexItem dotfill = texCmdNoArg "dotfill" hrulefill :: LatexItem hrulefill = texCmdNoArg "hrulefill" thinspace :: LatexItem thinspace = texCmdNoArg "thinspace" negthinspace :: LatexItem negthinspace = texCmdNoArg "!" -- The italic correction space (\/ in LaTeX) corrspace :: LatexItem corrspace = texCmdNoArg "/" -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#bskip bigskip :: ParItem bigskip = parCmdArgs "bigskip" [] -- = vspace bigskipamount -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#bskip medskip :: ParItem medskip = parCmdArgs "medskip" [] -- = vspace medskipamount -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#bskip smallskip :: ParItem smallskip = parCmdArgs "smallskip" [] -- = vspace smallskipamount -- http://www.personal.ceu.hu/tex/spacebox.htm#addvspace addvspace :: LatexLength -> ParItem addvspace = parCmdArg "addvspace" . texLength unwords :: [LatexItem] -> LatexItem unwords = mconcat . intersperse space -- TODO -- unlines: -- * does it makes sense? -- * given that newline can be forbidden at some places is it safe? -- * Why not just a minipage ? . mconcat -- Fonts -- some ref used: http://www.cl.cam.ac.uk/~rf10/pstex/latexcommands.htm -- Font sizes -- those could be seen as taking an argument tiny, scriptsize, footnotesize, small, normalsize, large, _LARGE, _Large, huge, _Huge, mdseries, bfseries, itshape, slshape, scshape, upshape, rmfamily, sffamily, ttfamily, normalfont :: TexDecl tiny = texDecl "tiny" scriptsize = texDecl "scriptsize" footnotesize = texDecl "footnotesize" small = texDecl "small" normalsize = texDecl "normalsize" large = texDecl "large" _LARGE = texDecl "LARGE" _Large = texDecl "Large" huge = texDecl "huge" _Huge = texDecl "Huge" bfseries = texDecl "bfseries" mdseries = texDecl "mdseries" rmfamily = texDecl "rmfamily" sffamily = texDecl "sffamily" ttfamily = texDecl "ttfamily" upshape = texDecl "upshape" itshape = texDecl "itshape" slshape = texDecl "slshape" scshape = texDecl "scshape" normalfont = texDecl "normalfont" emph, textrm, textsf, texttt, textmd, textbf, textup, textit, textsl, textsc, textnormal, textsuperscript, textsubscript :: LatexItem -> LatexItem -- textXYZ commands should work in math too (use a typeclass) emph = latexCmdArg "emph" textrm = latexCmdArg "textrm" textsf = latexCmdArg "textsf" texttt = latexCmdArg "texttt" textmd = latexCmdArg "textmd" textbf = latexCmdArg "textbf" textup = latexCmdArg "textup" textit = latexCmdArg "textit" textsl = latexCmdArg "textsl" textsc = latexCmdArg "textsc" textnormal = latexCmdArg "textnormal" -- http://en.wikibooks.org/wiki/LaTeX/Formatting#Text_mode_superscript_and_subscript textsuperscript = latexCmdArg "textsuperscript" -- http://en.wikibooks.org/wiki/LaTeX/Formatting#Text_mode_superscript_and_subscript -- fixltxe2 is not the only package providing textsubscript textsubscript x = latexCmdArgs "textsubscript" [packageDependency (pkgName "fixltxe2") ,mandatory x] -- Litteral underscore in text mode textunderscore :: LatexItem textunderscore = texCmdNoArg "textunderscore" -- Line and page breaking -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#linebreak linebreak :: Maybe Int -> TexDecl linebreak = (texDecl' "linebreak" =<<) . check0to4 "linebreak" -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#nolinebreak nolinebreak :: Maybe Int -> TexDecl nolinebreak = (texDecl' "nolinebreak" =<<) . check0to4 "nolinebreak" -- http://www.personal.ceu.hu/tex/breaking.htm#linebr linebr :: Star -> Maybe LatexLength -> LatexItem linebr s extraSpace = latexCmdAnyArgs "\\" [starToArg s ,maybe noArg optTexLength extraSpace ,rawArg "%\n"] -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#newline rawNewline :: Maybe LatexLength -> LatexItem rawNewline mlen = latexCmdAnyArgs "newline" [maybe noArg optTexLength mlen ,rawArg "%\n"] -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#newline -- see rawNewline for a more permissive dangerous version of newline newline :: Maybe LatexLength -> ParItem newline = para . rawNewline -- robust -- http://www.personal.ceu.hu/tex/breaking.htm#hyph hyphen :: LatexItem hyphen = rawTex "{\\-}" -- TODO: check if {...} does not cause trouble here -- otherwise this may be considered a legit -- ``concatenation effect''. -- robust -- http://www.personal.ceu.hu/tex/breaking.htm#hyphw hyphenation :: [String] -> PreambleItem hyphenation = preambleCmdArg "hyphenation" . rawAnyTex . L.unwords -- rawAnyTex is a bit rough here hyphenationPar :: [String] -> ParItem hyphenationPar = parCmdArg "hyphenation" . rawAnyTex . L.unwords -- rawAnyTex is a bit rough here sloppy, fussy :: TexDecl sloppy = texDecl "sloppy" fussy = texDecl "fussy" sloppypar :: ParItem -> ParItem sloppypar = parEnvironmentPar "sloppypar" [] -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#pagebreak pagebreak :: Maybe Int -> TexDecl pagebreak = (texDecl' "pagebreak" =<<) . check0to4 "pagebreak" -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#nopagebreak nopagebreak :: Maybe Int -> TexDecl nopagebreak = (texDecl' "nopagebreak" =<<) . check0to4 "nopagebreak" -- fragile samepage :: TexDecl samepage = texDecl "samepage" -- robust -- http://www.personal.ceu.hu/tex/breaking.htm#newpage newpage :: ParItem newpage = parCmdArgs "newpage" [] -- robust -- http://www.personal.ceu.hu/tex/breaking.htm#clrpage clearpage :: ParItem clearpage = parCmdArgs "clearpage" [] -- fragile -- http://www.personal.ceu.hu/tex/breaking.htm#clrdblpage cleardoublepage :: ParItem cleardoublepage = parCmdArgs "cleardoublepage" [] --- Boxes -- TeX level -- http://dmr.ath.cx/notes/tex.html#entry25 hbox :: LatexItem -> LatexItem hbox = latexCmdArg "hbox" -- TeX level -- http://dmr.ath.cx/notes/tex.html#entry25 vbox :: ParItem -> LatexItem vbox = latexParModeArgs "vbox" [] -- TeX level -- http://dmr.ath.cx/notes/tex.html#entry25 vtop :: ParItem -> LatexItem vtop = latexParModeArgs "vtop" [] -- TODO -- vbox_to :: LatexLength -> ParItem -> LatexItem -- vbox_to width = latexParModeArgs "vbox" [to $ texLength width] {- class Mbox a where -- robust mbox :: LatexItem -> a -- fragile makebox :: LatexLength -> LatexLength -> LatexItem -> a instance Mbox MathItem where mbox = MathToLR Nothing Nothing makebox = mmakebox instance Mbox LatexItem where mbox = id instance Mbox ParItem where -} -- robust -- http://www.personal.ceu.hu/tex/spacebox.htm#makebox mbox :: LatexItem -> LatexItem mbox = latexCmdArg "mbox" posArg :: Pos -> Arg AnyItem posArg = optional . rawAnyTex . pure . charPos -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#makebox makebox :: LatexLength -> Pos -> LatexItem -> LatexItem makebox width pos txt = latexCmdAnyArgs "makebox" [optTexLength width ,posArg pos ,mandatoryLatexItem txt] -- robust fbox :: LatexItem -> LatexItem fbox = latexCmdArg "fbox" -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#framebox framebox :: LatexLength -> Pos -> LatexItem -> LatexItem framebox width pos txt = latexCmdAnyArgs "framebox" [optTexLength width ,posArg pos ,mandatoryLatexItem txt] phantom :: LatexItem -> LatexItem phantom = latexCmdArg "phantom" vphantom :: LatexItem -> LatexItem vphantom = latexCmdArg "vphantom" -- robust sbox :: SaveBin -> LatexItem -> LatexItem sbox bin txt = latexCmdAnyArgs "sbox" [mandatory $ latexSaveBin bin, mandatoryLatexItem txt] -- fragile savebox :: SaveBin -> Maybe LatexLength -> Maybe (Either () ()) -> LatexItem -> LatexItem savebox bin width dir txt = latexCmdAnyArgs "savebox" [mandatory $ latexSaveBin bin ,maybe noArg optTexLength width ,maybe noArg (optionalLatexItem . either ll rr) dir ,mandatoryLatexItem txt] where ll _ = rawTex "l" rr _ = rawTex "r" -- robust usebox :: SaveBin -> LatexItem usebox bin = latexCmdAnyArgs "usebox" [mandatory $ latexSaveBin bin] -- vertical position for parbox and minipage data VPos = Normal | Top | Bot vposArg :: VPos -> Arg AnyItem vposArg Normal = noArg vposArg Top = optional . rawAnyTex $ "t" vposArg Bot = optional . rawAnyTex $ "b" -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#parbox parbox :: VPos -> LatexLength -> LatexItem -> LatexItem parbox pos width txt = latexCmdAnyArgs "parbox" [vposArg pos, mandatory $ texLength width, mandatoryLatexItem txt] minipage :: VPos -> LatexLength -> ParItem -> LatexItem minipage pos width = latexEnvironmentPar "minipage" [vposArg pos, mandatory $ texLength width] -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#rule rule :: LatexLength -> LatexLength -> LatexItem rule width height = latexCmdAnyArgs "rule" [mandatory $ texLength width ,mandatory $ texLength height] -- fragile rule' :: LatexLength -> LatexLength -> LatexLength -> LatexItem rule' raise_len width height = latexCmdAnyArgs "rule" [optTexLength raise_len ,mandatory $ texLength width ,mandatory $ texLength height] -- fragile -- http://www.personal.ceu.hu/tex/spacebox.htm#raisebox raisebox :: LatexLength -> LatexItem -> LatexItem raisebox raise_len txt = latexCmdAnyArgs "raisebox" [mandatory $ texLength raise_len ,mandatoryLatexItem txt] -- fragile raisebox' :: LatexLength -> LatexLength -> LatexLength -> LatexItem -> LatexItem raisebox' raise_len height depth txt = latexCmdAnyArgs "raisebox" [mandatory $ texLength raise_len ,optTexLength height ,optTexLength depth ,mandatoryLatexItem txt] footnote :: LatexItem -> LatexItem footnote = latexCmdArg "footnote" caption :: LatexItem -> LatexItem caption txt = latexCmdArgs "caption" [mandatory txt] caption' :: String -> LatexItem -> LatexItem caption' lstentry txt = latexCmdArgs "caption" [optional $ checkentry lstentry, mandatory txt] where checkentry x | all isAlphaNum x = rawTex x | otherwise = throwError "caption': restriction to alphanumeric characters for the lstentry" label :: Key -> LatexItem label = latexCmdAnyArg "label" . latexKey ref :: Key -> LatexItem ref = latexCmdAnyArg "ref" . latexKey pageref :: Key -> LatexItem pageref = latexCmdAnyArg "pageref" . latexKey -- fragile cite :: [Key] -> LatexItem cite = latexCmdAnyArgs "cite" . pure . latexKeysArg cite' :: LatexItem -> [Key] -> LatexItem cite' txt keys = latexCmdAnyArgs "cite" [optionalLatexItem txt, latexKeysArg keys] -- fragile nocite :: [Key] -> LatexItem nocite = latexCmdAnyArgs "nocite" . pure . latexKeysArg -- sectioning part, chapter, section, subsection, subsubsection, paragraph, subparagraph :: LatexItem -> ParItem part', chapter', section', subsection', subsubsection', paragraph', subparagraph' :: Star -> Maybe LatexItem -> LatexItem -> ParItem (part, part') = sectioning "part" (chapter, chapter') = sectioning "chapter" (section, section') = sectioning "section" (subsection, subsection') = sectioning "subsection" (subsubsection, subsubsection') = sectioning "subsubsection" (paragraph, paragraph') = sectioning "paragraph" (subparagraph , subparagraph') = sectioning "subparagraph" -- | Don't confuse 'paragraph' with 'para', 'para' is to make a paragraph, -- 'paragraph' is to name a set of paragraphs. para :: LatexItem -> ParItem para = parCast . latexItem bibliography :: LatexItem -> ParItem bibliography = parCmdArg "bibliography" . latexItem bibliographystyle :: LatexItem -> ParItem bibliographystyle = parCmdArg "bibliographystyle" . latexItem thispagestyle :: LatexItem -> ParItem thispagestyle = parCmdArg "thispagestyle" . latexItem pagestyle :: LatexItem -> ParItem pagestyle = parCmdArg "pagestyle" . latexItem appendix :: ParItem appendix = parCmdArgs "appendix" [] -- http://www.personal.ceu.hu/tex/length.htm setlength :: LatexLength -> LatexLength -> ParItem setlength lengthName newLength | isJust (lengthCst lengthName) = throwError "setlength: the first argument should be a length name not a constant" | otherwise = parCmdArgs "setlength" [mandatory (texLength lengthName) ,mandatory (texLength newLength)] -- http://www.personal.ceu.hu/tex/length.htm addtolength :: LatexLength -> LatexLength -> ParItem addtolength lengthName newLength | isJust (lengthCst lengthName) = throwError "addtolength: the first argument should be a length name not a constant" | otherwise = parCmdArgs "addtolength" [mandatory (texLength lengthName) ,mandatory (texLength newLength)] -- http://www.personal.ceu.hu/tex/length.htm settowidth :: LatexLength -> LatexItem -> ParItem settowidth lengthName text | isJust (lengthCst lengthName) = throwError "settowidth: the first argument should be a length name not a constant" | otherwise = parCmdArgs "settowidth" [mandatory (texLength lengthName) ,mandatoryLatexItem text] item :: ParItem -> ListItem item = liftM $ ListItm [] item' :: LatexItem -> ParItem -> ListItem item' a = liftM2 ListItm (pure . optional <$> a) itemize :: Maybe LatexItem -> [ListItem] -> ParItem itemize = listLikeEnv "itemize" . pure . maybe noArg optional -- enumerate counters are enumi, enumii, enumiii, enumiv enumerate :: Maybe LatexItem -> [ListItem] -> ParItem enumerate = listLikeEnv "enumerate" . pure . maybe noArg optional description :: Maybe LatexItem -> [ListItem] -> ParItem description = listLikeEnv "description" . pure . maybe noArg optional figure, table :: Star -> [LocSpec] -> ParItem -> ParItem figure = figureLike "figure" table = figureLike "table" -- Accents -- | Add a cedila to a letter (\c{...} in LaTeX) cedil :: LatexItem -> LatexItem cedil = latexCmdArg "c" grave :: LatexItem -> LatexItem grave = latexCmdArg "`" acute :: LatexItem -> LatexItem acute = latexCmdArg "'" uml :: LatexItem -> LatexItem uml = latexCmdArg "\"" circ :: LatexItem -> LatexItem circ = latexCmdArg "^" -- alias of 'circ' hat :: LatexItem -> LatexItem hat = latexCmdArg "^" check :: LatexItem -> LatexItem check = latexCmdArg "v" i :: LatexItem i = texCmdNoArg "i" j :: LatexItem j = texCmdNoArg "j" tilde :: LatexItem -> LatexItem tilde = latexCmdArg "~" dot :: LatexItem -> LatexItem dot = latexCmdArg "d" ring :: LatexItem -> LatexItem ring = latexCmdArg "r" -- TODO find a name _H :: LatexItem -> LatexItem _H = latexCmdArg "H" -- Produces a dot accent over the following (\.{x} in LaTeX) overdot :: LatexItem -> LatexItem overdot = latexCmdArg "." -- Produces a macron (overbar) accent over the following overbar :: LatexItem -> LatexItem overbar = latexCmdArg "=" -- Produces a macron (overbar) accent over the following underbar :: LatexItem -> LatexItem underbar = latexCmdArg "b" -- Produces a tie-after accent, as in `oo[' (\t in LaTeX). tieafter :: LatexItem -> LatexItem tieafter = latexCmdArg "t" -- Some non-English characters -- The 'å' letter (like @ring "a"@) aa :: LatexItem aa = texCmdNoArg "aa" -- The 'Å' letter (like @ring "A"@) _AA :: LatexItem _AA = texCmdNoArg "AA" -- The 'æ' letter ae :: LatexItem ae = texCmdNoArg "ae" -- The 'Æ' letter _AE :: LatexItem _AE = texCmdNoArg "AE" -- The 'œ' letter oe :: LatexItem oe = texCmdNoArg "oe" -- The 'Œ' letter _OE :: LatexItem _OE = texCmdNoArg "OE" -- The 'ß' letter ss :: LatexItem ss = texCmdNoArg "ss" -- The '/l' letter _l :: LatexItem _l = texCmdNoArg "l" -- The '/L' letter _L :: LatexItem _L = texCmdNoArg "L" -- The 'ø' letter o :: LatexItem o = texCmdNoArg "o" -- The 'Ø' letter _O :: LatexItem _O = texCmdNoArg "O" -- Text symbols -- | The copyright symbol, ©. copyright :: LatexItem copyright = texCmdNoArg "copyright" -- | The dagger symbol (in text). dag :: LatexItem dag = texCmdNoArg "dag" -- | The double dagger symbol (in text). ddag :: LatexItem ddag = texCmdNoArg "ddag" -- | The LaTeX logo. _LaTeX :: LatexItem _LaTeX = texCmdNoArg "LaTeX" -- | The TeX logo. _TeX :: LatexItem _TeX = texCmdNoArg "TeX" -- | An ellipsis (three dots at the baseline): `...'. This command also works in math mode. ldots :: LatexItem ldots = texCmdNoArg "ldots" -- | Left (opening) quote: `. lq :: LatexItem lq = texCmdNoArg "lq" -- | Right (closing) quote: '. rq :: LatexItem rq = texCmdNoArg "rq" -- | Left (opening) double quotes: ``. ldq :: LatexItem ldq = rawTex "{``}" -- | Right (opening) double quotes: ''. rdq :: LatexItem rdq = rawTex "{''}" -- | Double quote a LaTeX item. dquote :: LatexItem -> LatexItem dquote x = ldq ⊕ x ⊕ rdq -- | Paragraph sign (pilcrow). _P :: LatexItem _P = texCmdNoArg "P" -- | English pounds sterling. pounds :: LatexItem pounds = texCmdNoArg "pounds" -- | Section symbol. _S :: LatexItem _S = texCmdNoArg "S" textdegree :: LatexItem textdegree = latexCmdArgs "textdegree" [packageDependency (pkgName "textcomp"), mandatory ø] -- check options titlepage, flushleft, center, boxedminipage, quotation, verse :: ParItem -> ParItem titlepage = parEnvironmentPar "titlepage" [] flushleft = parEnvironmentPar "flushleft" [] center = parEnvironmentPar "center" [] boxedminipage = parEnvironmentPar "boxedminipage" [] quotation = parEnvironmentPar "quotation" [] verse = parEnvironmentPar "verse" [] quote :: LatexItem -> ParItem quote = liftM $ ParEnv "quote" [] . LatexItm -- The array and tablular Environments tabular :: [RowSpec LatexItem] -> [Row LatexItem] -> ParItem tabular = tabularLike Tabular cells :: [a] -> Row a cells = Cells cell :: a -> Row a cell = Cells . pure hline :: Row a hline = Hline cline :: Int -> Int -> Row a cline = Cline -- this is more the '|' than the \vline of LaTeX, -- one may want to support both using a HaveVline type class. vline :: RowSpec a vline = Rvline rtext :: a -> RowSpec a rtext = Rtext class HaveC a where c :: a class HaveL a where l :: a class HaveR a where r :: a instance HaveC (RowSpec a) where c = Rc instance HaveL (RowSpec a) where l = Rl instance HaveR (RowSpec a) where r = Rr class HaveTop a where top :: a instance HaveTop LocSpec where top = Lt instance HaveTop VPos where top = Top class HaveBot a where bot :: a instance HaveBot LocSpec where bot = Lb instance HaveBot VPos where bot = Bot class HaveNormal a where normal :: a instance HaveNormal VPos where normal = Normal bottom :: HaveBot a => a bottom = bot here, page :: LocSpec here = Lh page = Lp centered, flushLeft, flushRight, stretch :: Pos centered = Centered flushLeft = FlushLeft flushRight = FlushRight stretch = Stretch -- eqnarraystar = a4paper :: LatexPaperSize a4paper = A4paper documentclass :: DocumentClassKind -> [AnyItem] -> DocumentClass documentclass dc = (DocClass dc <$>) . mapM anyItmM article :: Maybe LatexLength -> Maybe LatexPaperSize -> [AnyItem] -> DocumentClass article msize mpaper args = documentclass Article $ maybeToList (latexPaper <$> mpaper) ++ maybeToList (texLength <$> msize) ++ args -- TODO improve options letter :: [AnyItem] -> DocumentClass letter = documentclass Letter book :: Maybe LatexLength -> Maybe LatexPaperSize -> [AnyItem] -> DocumentClass book msize mpaper args = documentclass Book $ maybeToList (latexPaper <$> mpaper) ++ maybeToList (texLength <$> msize) ++ args -- TODO improve options report :: [AnyItem] -> DocumentClass report = documentclass Report {- $( let mathCmdsArg, allTexDecls, mathDecls :: [String] mathCmds :: [(String, String)] mathCmds = [("lbrace", "{") ,("rbrace", "}") ,("space", " ") ,("at", "@") ,("in_", "in") ,("forall_", "forall") ,("thinspace", ",") ,("negthinspace", "!") ,("mediumspace", ":") ,("thickspace", ";") ,("msup", "sup") ] ++ map (id &&& id) [-- Greek letters "alpha","beta","chi","delta","Delta","epsilon","varepsilon","eta","gamma" ,"Gamma","iota","kappa","lambda","Lambda","mu","nu","omega","Omega","phi" ,"varphi","Phi","pi","Pi","psi","rho","sigma","Sigma","tau","theta" ,"vartheta","Theta","upsilon","xi","Xi","zeta" -- Operation symbols ,"backslash","times","divide","circ","oplus","otimes","sum","prod","wedge" ,"bigwedge","vee","bigvee","cup","bigcup","cap","bigcap" -- Relation symbols ,"ne","le","leq","ge","geq","prec","succ","notin","subset","supset" ,"subseteq","supseteq","equiv","cong","approx","propto" -- Logical symbols ,"neg","implies","iff","exists","bot","top","vdash","models" -- Grouping brackets ,"langle","rangle" -- Miscellaneous symbols ,"int","oint","partial","nabla","pm","emptyset","infty","aleph","ldots" ,"cdots","vdots","ddots","quad","diamond","square","lfloor","rfloor","lceiling","rceiling" -- Standard functions ,"sin","cos","tan","csc","sec","cot","sinh","cosh","tanh","log" ,"ln","det","dim","lim","mod","gcd","lcm","liminf","inf","limsup" ,"max","min","Pr" -- Arrows ,"uparrow","downarrow","rightarrow","to","leftarrow" ,"leftrightarrow","Rightarrow","Leftarrow","Leftrightarrow" ] mathCmdsArg = [-- Font commands "mathbf","mathbb","mathcal","mathtt","mathfrak" ------- ,"pmod" -- Putting one thing above another ,"tilde", "hat", "check", "breve", "acute", "grave", "bar", "vec" , "dot", "ddot", "overbrace", "underbrace" ,"overline","underline","widehat","widetilde","imath","jmath" ] typeStyles :: [String] typeStyles = ["em","bf","sf","sl","sc","it","tt"] allTexDecls = typeStyles mathDecls = ["displaystyle", "textstyle", "scriptstyle", "scriptscriptstyle" ,"mit","cal" ] lowerName :: String -> Name lowerName name | isLower (head name) = mkName name | otherwise = mkName $ '_':name mkMathCmd (name, cmd) = let lname = lowerName name in [sigD lname [t| MathItem |] , valD (varP lname) (normalB [| mathCmd $(stringE cmd) |]) [] ] mkMathCmdArg name = let lname = lowerName name in [sigD lname [t| MathItem -> MathItem |] , valD (varP lname) (normalB [| mathCmdArg $(stringE name) |]) [] ] mkTexDecl name = let lname = lowerName name in [sigD lname [t| LatexItem |] , valD (varP lname) (normalB [| texDecl $(stringE name) [] |]) [] ] mkMathDecl name = let lname = lowerName name in [sigD lname [t| MathItem |] , valD (varP lname) (normalB [| mathDecl $(stringE name) [] |]) [] ] mkList name ty names = [sigD name ty ,valD (varP name) (normalB (listE $ map (varE . lowerName) names)) []] d = sequence $ concat $ concat [ map mkMathCmd mathCmds , map mkMathCmdArg mathCmdsArg , map mkTexDecl allTexDecls , map mkMathDecl mathDecls , [mkList (mkName "mathItems") [t| [MathItem] |] $ (map fst mathCmds ++ mathDecls)] , [mkList (mkName "mathCmdsArg") [t| [MathItem -> MathItem] |] mathCmdsArg] , [mkList (mkName "allTexDecls") [t| [LatexItem] |] allTexDecls] ] in do dd <- d runIO $ writeFile "/tmp/a.hs" $ pprint dd return [] ) -} {- This chunk was generated by the previous TH splice. The lists of all commands are manually maintained though. -} author, title, subtitle, date, institute :: LatexItem -> PreambleItem title = preambleCmdArg "title" . latexItem subtitle = preambleCmdArg "subtitle" . latexItem date = preambleCmdArg "date" . latexItem author = preambleCmdArg "author" . latexItem -- Institute is defined in beamer but not in article. -- Should we move these definitions into sub modules? -- For instance Language.LaTeX.Article.date institute = preambleCmdArg "institute" . latexItem authors :: [LatexItem] -> PreambleItem authors = author . mconcat . intersperse (rawTex " & ") utf8 :: Encoding utf8 = rawEncoding "utf8" latin1 :: Encoding latin1 = rawEncoding "latin1" inputenc :: Encoding -> PreambleItem inputenc (Encoding enc) = usepackage [latexItem $ fromString enc] (pkgName "inputenc") {-# DEPRECATED em "Use emph instead" #-} em :: TexDecl em = texDecl "em" {-# DEPRECATED rm "Use textrm or rmfamily instead" #-} rm :: TexDecl rm = texDecl "rm" {-# DEPRECATED bf "Use textbf or bfseries instead" #-} bf :: TexDecl bf = texDecl "bf" {-# DEPRECATED sf "Use textsf or sffamily instead" #-} sf :: TexDecl sf = texDecl "sf" {-# DEPRECATED sl "Use textsl or slshape instead" #-} sl :: TexDecl sl = texDecl "sl" {-# DEPRECATED sc "Use textsc or scshape instead" #-} sc :: TexDecl sc = texDecl "sc" {-# DEPRECATED it "Use textit or itshape instead" #-} it :: TexDecl it = texDecl "it" {-# DEPRECATED tt "Use texttt or ttfamily instead" #-} tt :: TexDecl tt = texDecl "tt" -- \up ? allTexDecls :: [TexDecl] allTexDecls = [rm, em, bf, sf, sl, sc, it, tt ,rmfamily, bfseries, sffamily, slshape ,scshape, itshape, ttfamily, upshape, normalfont ,reversemarginpar,normalmarginpar ,sloppy, fussy,samepage ,tiny, scriptsize, footnotesize, small, normalsize, large ,_LARGE, _Large, huge, _Huge] -- Local definitions check0to4 :: String -> Maybe Int -> LatexM [Arg AnyItem] check0to4 _ Nothing = return [] check0to4 s (Just n) | n >= 0 && n <= 4 = return [optional $ num n] | otherwise = throwError $ s ++ ": option must be between 0 and 4 not " ++ show i