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