{-# LANGUAGE OverloadedStrings #-} -- | This module is the /Prelude/ of LaTeX functions. -- It includes commands, environments, and some other -- useful abstractions, that don't require you to -- import additional LaTeX packages. module Text.LaTeX.Base.Commands ( -- * Basic functions raw , between , comment , (%:) -- * Preamble commands , title , author , date , institute , thanks , documentclass , usepackage , linespread -- ** Classes -- *** Document classes , article , proc , report , minimal , book , slides -- *** Class options , ClassOption (..) , customopt , draft , titlepage , notitlepage , onecolumn , twocolumn , oneside , twoside , landscape , openright , openany , fleqn , leqno -- ** Paper sizes , PaperType (..) , a0paper , a1paper , a2paper , a3paper , a4paper , a5paper , a6paper , b0paper , b1paper , b2paper , b3paper , b4paper , b5paper , b6paper , letterpaper , executivepaper , legalpaper -- ** Page styles , pagestyle , thispagestyle , plain , headings , empty , myheadings , markboth , markright -- * Body commands , document , maketitle -- ** Document structure , tableofcontents , abstract , appendix -- *** Sections , part , chapter , section , subsection , subsubsection , paragraph , subparagraph -- ** Logos & symbols , today , thePage , tex , latex , laTeX2 , laTeXe , ldots , vdots , ddots -- *** HaTeX specific , hatex , hatex3 , version , hatex_version -- ** Document layout , par , newline , lnbk , lnbk_ , newpage , cleardoublepage , clearpage , linebreak , nolinebreak , pagebreak , nopagebreak , hspace , hspace_ , vspace , hfill , vfill , stretch , smallskip , bigskip , baselineskip , indent , noindent -- *** Document measures , textwidth , textheight , linewidth -- ** Formatting text , verbatim , verb -- *** Fonts -- -- Different font styles. , textbf , textit , texttt , textrm , textsf , textmd , textup , textsl , textsc , textnormal , underline , emph -- *** Sizes -- -- | Sizes are sorted from smallest to biggest. , tiny , scriptsize , footnotesize , small , normalsize , large , large2 , large3 , huge , huge2 -- ** Environments -- | Math environments, such as @equation@, defined in "Text.LaTeX.Packages.AMSMath". , enumerate , itemize , item , flushleft , flushright , center , quote , verse , cite , description , minipage , figure -- ** Page numbering , pagenumbering , arabic , roman , roman_ , alph , alph_ -- ** Boxes , mbox , fbox , parbox , framebox , makebox , raisebox , rule -- ** Cross references , caption , label , ref , pageref -- ** Tables , tabular , array , (&) , hline , cline , multicolumn -- *** Special tables , matrixTabular -- ** Others , footnote , protect , hyphenation , hyp , qts -- * External files , input , include ) where import Data.String import Data.Maybe (isNothing, catMaybes) import Data.Text (toLower) import qualified Data.Text as T import Text.LaTeX.Base.Syntax import Text.LaTeX.Base.Class import Text.LaTeX.Base.Render import Text.LaTeX.Base.Types import Text.LaTeX.Base.Texy import Data.Version import Data.List (find, intercalate,intersperse) import Data.Matrix (Matrix,nrows,ncols,(!)) -- import Paths_HaTeX -- | Insert a raw piece of 'Text'. -- This functions doesn't escape @LaTeX@ reserved characters, -- it insert the text just as it is received. -- -- /Warning:/ This function is /unsafe/, in the sense that it does -- not check that the input text is a valid LaTeX /block/. -- Make sure any braces, commands or environments are properly closed. raw :: LaTeXC l => Text -> l raw = fromLaTeX . TeXRaw -- | Calling 'between' @c l1 l2@ puts @c@ between @l1@ and @l2@ and -- appends them. -- -- > between c l1 l2 = l1 <> c <> l2 between :: Monoid m => m -> m -> m -> m between c l1 l2 = l1 <> c <> l2 -- | Create a comment. comment :: LaTeXC l => Text -> l comment = fromLaTeX . TeXComment -- | This operator appends a comment after a expression. -- For example: -- -- > textbf "I'm just an example." %: "Insert a few words here." -- -- The implementation is -- -- > (%:) l = (l <>) . comment -- -- Since you are writing in Haskell, you may not need to output comments -- as you can add them in the Haskell source. I added this feature -- for completeness. It may be useful for debugging the output as well. (%:) :: LaTeXC l => l -> Text -> l (%:) l = (l <>) . comment -- | Generate the title. It normally contains the 'title' name -- of your document, the 'author'(s) and 'date'. maketitle :: LaTeXC l => l maketitle = comm0 "maketitle" -- | Set the title of your document. title :: LaTeXC l => l -> l title = comm1 "title" -- | Set a date for your document. date :: LaTeXC l => l -> l date = comm1 "date" -- | Set the author(s) of the document. author :: LaTeXC l => l -> l author = comm1 "author" -- | Set either an institute or an organization -- for the document. It does /not/ work for -- a document of the 'article' class. institute :: LaTeXC l => Maybe l -> l -> l institute Nothing = liftL $ \l -> TeXComm "institute" [FixArg l] institute (Just s) = liftL2 (\l1 l2 -> TeXComm "institute" [OptArg l1,FixArg l2]) s thanks :: LaTeXC l => l -> l thanks = comm1 "thanks" -- | Import a package. First argument is a list of options for -- the package named in the second argument. usepackage :: LaTeXC l => [l] -> PackageName -> l usepackage ls pn = liftListL (\ls_ -> TeXComm "usepackage" [MOptArg ls_ ,FixArg $ fromString pn]) ls -- | The @LaTeX@ logo. latex :: LaTeXC l => l latex = comm0 "LaTeX" -- | Start a new paragraph par :: LaTeXC l => l par = comm0 "par" -- | Start a new line. newline :: LaTeXC l => l newline = comm0 "newline" part :: LaTeXC l => l -> l part = comm1 "part" -- | Start a new chapter with the given title. chapter :: LaTeXC l => l -> l chapter = comm1 "chapter" -- | Start a new section with a given title. section :: LaTeXC l => l -> l section = comm1 "section" -- | Start a new subsection. subsection :: LaTeXC l => l -> l subsection = comm1 "subsection" -- | Start a new sub/sub/section. subsubsection :: LaTeXC l => l -> l subsubsection = comm1 "subsubsection" -- | Start a paragraph. paragraph :: LaTeXC l => l -> l paragraph = comm1 "paragraph" -- | Start a subparagraph (minimal level of sectioning). subparagraph :: LaTeXC l => l -> l subparagraph = comm1 "subparagraph" -- | Create the table of contents, automatically generated -- from your 'section's, 'subsection's, and related functions. tableofcontents :: LaTeXC l => l tableofcontents = comm0 "tableofcontents" appendix :: LaTeXC l => l appendix = comm0 "appendix" -- | An item of a list (see 'enumerate' or 'itemize'). -- The optional argument sets the design of the item. item :: LaTeXC l => Maybe l -> l item Nothing = commS "item " item (Just opt) = liftL (\opt_ -> TeXComm "item" [OptArg opt_]) opt -- | Environment of ordered lists. Use 'item' to start each list -- item. enumerate :: LaTeXC l => l -> l enumerate = liftL $ TeXEnv "enumerate" [] -- | Environment of unordered lists. Use 'item' to start each list -- item. itemize :: LaTeXC l => l -> l itemize = liftL $ TeXEnv "itemize" [] description :: LaTeXC l => l -> l description = liftL $ TeXEnv "description" [] -- | Left-justify the argument. flushleft :: LaTeXC l => l -> l flushleft = liftL $ TeXEnv "flushleft" [] -- | Right-justify the argument. flushright :: LaTeXC l => l -> l flushright = liftL $ TeXEnv "flushright" [] -- | Center-justify the argument. center :: LaTeXC l => l -> l center = liftL $ TeXEnv "center" [] quote :: LaTeXC l => l -> l quote = liftL $ TeXEnv "quote" [] verse :: LaTeXC l => l -> l verse = liftL $ TeXEnv "verse" [] -- | Minipage environment. minipage :: LaTeXC l => Maybe Pos -- ^ Optional position -> l -- ^ Width -> l -- ^ Minipage content -> l minipage Nothing = liftL2 $ \ts -> TeXEnv "minipage" [ FixArg ts ] minipage (Just p) = liftL2 $ \ts -> TeXEnv "minipage" [ OptArg $ rendertex p , FixArg ts ] -- | Figure environment. figure :: LaTeXC l => Maybe Pos -- ^ Optional position -> l -- ^ Figure content -> l figure Nothing = liftL $ TeXEnv "figure" [] figure (Just p) = liftL $ TeXEnv "figure" [ OptArg $ TeXRaw $ render p ] -- | Abstract section. abstract :: LaTeXC l => l -> l abstract = liftL $ TeXEnv "abstract" [] cite :: LaTeXC l => l -> l cite = liftL $ \l -> TeXComm "cite" [FixArg l] -- Document class -- | A class option to be passed to the 'documentclass' function. data ClassOption = Draft | TitlePage | NoTitlePage | OneColumn | TwoColumn | OneSide | TwoSide | Landscape | OpenRight | OpenAny | Fleqn | Leqno | FontSize Measure | Paper PaperType | CustomOption String deriving Show instance Render ClassOption where render (FontSize m) = render m render (Paper pt) = toLower (render pt) <> "paper" render (CustomOption str) = fromString str render co = toLower $ fromString $ show co customopt :: String -> ClassOption customopt = CustomOption instance IsString ClassOption where fromString = customopt -- | LaTeX available paper types. data PaperType = A0 | A1 | A2 | A3 | A4 | A5 | A6 | B0 | B1 | B2 | B3 | B4 | B5 | B6 | Letter | Executive | Legal deriving Show instance Render PaperType where -- | Set the document class. Needed in all documents. documentclass :: LaTeXC l => [ClassOption] -- ^ Class options -> ClassName -- ^ Class name -> l documentclass opts cn = fromLaTeX $ TeXComm "documentclass" [MOptArg $ fmap rendertex opts , FixArg $ fromString cn] article :: ClassName article = "article" proc :: ClassName proc = "proc" minimal :: ClassName minimal = "minimal" report :: ClassName report = "report" book :: ClassName book = "book" slides :: ClassName slides = "slides" a0paper :: ClassOption a0paper = Paper A0 a1paper :: ClassOption a1paper = Paper A1 a2paper :: ClassOption a2paper = Paper A2 a3paper :: ClassOption a3paper = Paper A3 a4paper :: ClassOption a4paper = Paper A4 a5paper :: ClassOption a5paper = Paper A5 a6paper :: ClassOption a6paper = Paper A6 b0paper :: ClassOption b0paper = Paper B0 b1paper :: ClassOption b1paper = Paper B1 b2paper :: ClassOption b2paper = Paper B2 b3paper :: ClassOption b3paper = Paper B3 b4paper :: ClassOption b4paper = Paper B4 b5paper :: ClassOption b5paper = Paper B5 b6paper :: ClassOption b6paper = Paper B6 letterpaper :: ClassOption letterpaper = Paper Letter executivepaper :: ClassOption executivepaper = Paper Executive legalpaper :: ClassOption legalpaper = Paper Legal draft :: ClassOption draft = Draft -- | Typesets displayed formulae left-aligned instead of centred. fleqn :: ClassOption fleqn = Fleqn -- | Places the numbering of formulae on the left hand side instead of the right. leqno :: ClassOption leqno = Leqno titlepage :: ClassOption titlepage = TitlePage notitlepage :: ClassOption notitlepage = NoTitlePage onecolumn :: ClassOption onecolumn = OneColumn twocolumn :: ClassOption twocolumn = TwoColumn oneside :: ClassOption oneside = OneSide twoside :: ClassOption twoside = TwoSide -- | Changes the layout of the document to print in landscape mode landscape :: ClassOption landscape = Landscape -- | Makes chapters begin either only on right hand pages openright :: ClassOption openright = OpenRight -- | Makes chapters begin on the next page available. openany :: ClassOption openany = OpenAny -- | The 'document' environment contains the body of the document. document :: LaTeXC l => l -> l document = liftL $ TeXEnv "document" [] pagenumbering :: LaTeXC l => l -> l pagenumbering = liftL $ \l -> TeXComm "pagenumbering" [FixArg l] -- | Arabic numerals. arabic :: LaTeXC l => l arabic = fromLaTeX "arabic" -- | Lowercase roman numerals. roman :: LaTeXC l => l roman = fromLaTeX "roman" -- | Uppercase roman numerals. roman_ :: LaTeXC l => l roman_ = fromLaTeX "Roman" -- | Lowercase letters. alph :: LaTeXC l => l alph = fromLaTeX "alph" -- | Uppercase letters. alph_ :: LaTeXC l => l alph_ = fromLaTeX "Alph" -- Page styles pagestyle :: LaTeXC l => PageStyle -> l pagestyle ps = fromLaTeX $ TeXComm "pagestyle" [FixArg $ fromString ps] thispagestyle :: LaTeXC l => PageStyle -> l thispagestyle ps = fromLaTeX $ TeXComm "thispagestyle" [FixArg $ fromString ps] plain :: PageStyle plain = "plain" headings :: PageStyle headings = "headings" empty :: PageStyle empty = "empty" myheadings :: PageStyle myheadings = "myheadings" -- | Used in conjunction with 'myheadings' for setting both the left and the right heading. markboth :: LaTeXC l => l -> l -> l markboth = liftL2 $ \l1 l2 -> TeXComm "markboth" [FixArg l1 , FixArg l2] -- | Used in conjunction with 'myheadings' for setting the right heading. markright :: LaTeXC l => l -> l markright = liftL $ \l -> TeXComm "markright" [FixArg l] -- | Start a new line. In a 'tabular', it starts a new row, so use 'newline' instead. lnbk :: LaTeXC l => l lnbk = fromLaTeX $ TeXLineBreak Nothing False lnbk_ :: LaTeXC l => l lnbk_ = fromLaTeX $ TeXLineBreak Nothing True hyp :: LaTeXC l => l hyp = fromLaTeX $ TeXCommS "-" cleardoublepage :: LaTeXC l => l cleardoublepage = comm0 "cleardoublepage" clearpage :: LaTeXC l => l clearpage = comm0 "clearpage" newpage :: LaTeXC l => l newpage = comm0 "newpage" linebreak :: LaTeXC l => l -> l linebreak = liftL $ \l -> TeXComm "linebreak" [OptArg l] nolinebreak :: LaTeXC l => l -> l nolinebreak = liftL $ \l -> TeXComm "nolinebreak" [OptArg l] nopagebreak :: LaTeXC l => l -> l nopagebreak = liftL $ \l -> TeXComm "nopagebreak" [OptArg l] pagebreak :: LaTeXC l => l -> l pagebreak = liftL $ \l -> TeXComm "pagebreak" [OptArg l] hyphenation :: LaTeXC l => l -> l hyphenation = liftL $ \l -> TeXComm "hyphenation" [FixArg l] mbox :: LaTeXC l => l -> l mbox = liftL $ \l -> TeXComm "mbox" [FixArg l] fbox :: LaTeXC l => l -> l fbox = liftL $ \l -> TeXComm "fbox" [FixArg l] -- | Render the date at compilation time. today :: LaTeXC l => l today = comm0 "today" -- | Render the current page. thePage :: LaTeXC l => l thePage = comm0 "thepage" -- | TeX logo. tex :: LaTeXC l => l tex = comm0 "TeX" -- | LaTeX logo. laTeX2 :: LaTeXC l => l laTeX2 = comm0 "LaTeX" laTeXe :: LaTeXC l => l laTeXe = comm0 "LaTeXe" -- | Horizontal dots. ldots :: LaTeXC l => l ldots = comm0 "ldots" -- | Vertical dots. vdots :: LaTeXC l => l vdots = comm0 "vdots" -- | Diagonal dots. ddots :: LaTeXC l => l ddots = comm0 "ddots" -- | Quotation marks. qts :: LaTeXC l => l -> l qts l = between l (raw "``") (raw "''") footnote :: LaTeXC l => l -> l footnote = liftL $ \l -> TeXComm "footnote" [FixArg l] linespread :: LaTeXC l => Float -> l linespread x = fromLaTeX $ TeXComm "linespread" [FixArg $ rendertex x] baselineskip :: LaTeXC l => l baselineskip = comm0 "baselineskip" indent :: LaTeXC l => l indent = comm0 "indent" noindent :: LaTeXC l => l noindent = comm0 "noindent" hspace :: LaTeXC l => Measure -> l hspace m = fromLaTeX $ TeXComm "hspace" [FixArg $ rendertex m] hspace_ :: LaTeXC l => Measure -> l hspace_ m = fromLaTeX $ TeXComm "hspace*" [FixArg $ rendertex m] stretch :: LaTeXC l => Int -> l stretch n = fromLaTeX $ TeXComm "stretch" [FixArg $ rendertex n] vspace :: LaTeXC l => Measure -> l vspace m = fromLaTeX $ TeXComm "vspace" [FixArg $ rendertex m] -- | Fill out all available horizontal space. hfill :: LaTeXC l => l hfill = comm0 "hfill" -- | Fill out all available vertical space. vfill :: LaTeXC l => l vfill = comm0 "vfill" protect :: LaTeXC l => l -> l protect l = commS "protect" <> l textwidth :: LaTeXC l => l textwidth = comm0 "textwidth" textheight :: LaTeXC l => l textheight = comm0 "textheight" linewidth :: LaTeXC l => l linewidth = comm0 "linewidth" -- | The point of 'verbatim' is to include text that will -- /not/ be parsed as LaTeX in any way at all, but should simply -- appear as given in the document, in a separate display -- in typewriter font. verbatim :: LaTeXC l => Text -> l verbatim = liftL (TeXEnv "verbatim" []) . raw -- | Include text, as given and in typewriter, but in-line. -- Note that, for LaTeX-specific technical reasons, verbatim -- text can generally only be used \"at the top level\", not -- in e.g. section titles or other command-arguments. -- -- Unlike 'verbatim', which LaTeX implements as an ordinary environment, -- its command 'verb' uses a syntax trick to avoid braking its parsing -- when the literal text contains a closing brace: rather than using braces -- at all, the first character after @\\verb@ will be the right delimiter as well. -- Translating this method to HaTeX wouldn't really make sense since Haskell -- has string literals with their own escaping possibilities; instead, we make -- it secure by automatically choosing a delimiter that does not turn up -- in the given string. verb :: LaTeXC l => Text -> l verb vbStr = case find (isNothing . (`T.find`vbStr) . (==)) $ "`'\"|=-~$#+/!^_;:,." ++ ['0'..'9'] ++ ['A'..'B'] ++ ['a'..'b'] of Just delim -> let d = T.singleton delim in raw $ T.concat [ "\\verb", d, vbStr, d ] Nothing -> let (lpart, rpart) = T.splitAt (T.length vbStr `quot` 2) vbStr in verb lpart <> verb rpart -- If all suitable delimiter characters are already used in the verbatim -- string (which really should never happen as this is intended for **short** -- in-line displays!) then split the verbatim string in two sections; at -- some point they will necessarily lack some of the characters. underline :: LaTeXC l => l -> l underline = liftL $ \l -> TeXComm "underline" [FixArg l] emph :: LaTeXC l => l -> l emph = liftL $ \l -> TeXComm "emph" [FixArg l] textrm :: LaTeXC l => l -> l textrm = liftL $ \l -> TeXComm "textrm" [FixArg l] textsf :: LaTeXC l => l -> l textsf = liftL $ \l -> TeXComm "textsf" [FixArg l] -- | Set the given argument to monospaced font. texttt :: LaTeXC l => l -> l texttt = liftL $ \l -> TeXComm "texttt" [FixArg l] textmd :: LaTeXC l => l -> l textmd = liftL $ \l -> TeXComm "textmd" [FixArg l] -- | Set the given argument to bold font face. textbf :: LaTeXC l => l -> l textbf = liftL $ \l -> TeXComm "textbf" [FixArg l] textup :: LaTeXC l => l -> l textup = liftL $ \l -> TeXComm "textup" [FixArg l] -- Set the given argument to italic font face. textit :: LaTeXC l => l -> l textit = liftL $ \l -> TeXComm "textit" [FixArg l] textsl :: LaTeXC l => l -> l textsl = liftL $ \l -> TeXComm "textsl" [FixArg l] -- | Set the given argument to small caps format. textsc :: LaTeXC l => l -> l textsc = liftL $ \l -> TeXComm "textsc" [FixArg l] textnormal :: LaTeXC l => l -> l textnormal = liftL $ \l -> TeXComm "textnormal" [FixArg l] -------------------- -- Standard sizes -- -------------------- sizecomm :: LaTeXC l => String -> l -> l sizecomm str = liftL $ \l -> TeXBraces $ comm0 str <> l tiny :: LaTeXC l => l -> l tiny = sizecomm "tiny" scriptsize :: LaTeXC l => l -> l scriptsize = sizecomm "scriptsize" footnotesize :: LaTeXC l => l -> l footnotesize = sizecomm "footnotesize" small :: LaTeXC l => l -> l small = sizecomm "small" normalsize :: LaTeXC l => l -> l normalsize = sizecomm "normalsize" large :: LaTeXC l => l -> l large = sizecomm "large" large2 :: LaTeXC l => l -> l large2 = sizecomm "Large" large3 :: LaTeXC l => l -> l large3 = sizecomm "LARGE" huge :: LaTeXC l => l -> l huge = sizecomm "huge" huge2 :: LaTeXC l => l -> l huge2 = sizecomm "Huge" -------------------- smallskip :: LaTeXC l => l smallskip = comm0 "smallskip" bigskip :: LaTeXC l => l bigskip = comm0 "bigskip" -- | The 'tabular' environment can be used to typeset tables with optional horizontal and vertical lines. tabular :: LaTeXC l => Maybe Pos -- ^ This optional parameter can be used to specify the vertical position of the table. -- Defaulted to 'Center'. -> [TableSpec] -- ^ Table specification of columns and vertical lines. -> l -- ^ Table content. See '&', 'lnbk', 'hline' and 'cline'. -> l -- ^ Resulting table syntax. tabular Nothing ts = liftL $ TeXEnv "tabular" [ FixArg $ TeXRaw $ renderAppend ts ] tabular (Just p) ts = liftL $ TeXEnv "tabular" [ OptArg $ TeXRaw $ render p , FixArg $ TeXRaw $ renderAppend ts ] -- | Like 'tabular' but in math mode by default array :: LaTeXC l => Maybe Pos -- ^ This optional parameter can be used to specify the vertical position of the table. -- Defaulted to 'Center'. -> [TableSpec] -- ^ Table specification of columns and vertical lines. -> l -- ^ Table content. See '&', 'lnbk', 'hline' and 'cline'. -> l -- ^ Resulting table syntax. array Nothing ts = liftL $ TeXEnv "array" [ FixArg $ TeXRaw $ renderAppend ts ] array (Just p) ts = liftL $ TeXEnv "array" [ OptArg $ TeXRaw $ render p , FixArg $ TeXRaw $ renderAppend ts ] -- | Column separator. (&) :: LaTeXC l => l -> l -> l (&) = between (raw "&") -- | Horizontal line. hline :: LaTeXC l => l hline = commS "hline " -- | Cell taking multiple columns. multicolumn :: LaTeXC l => Int -> [TableSpec] -> l -> l multicolumn n c = liftL $ \l -> TeXComm "multicolumn" [ FixArg $ rendertex n , FixArg . TeXRaw $ renderAppend c , FixArg l ] ----------------------------------------- -- Special Tables (Tabulars) -- | If you are able to arrange some data in matrix form, you -- might want to use this function to quickly generate a -- tabular with your data. Each element of the matrix is -- rendered using the 'Texy' instance of its type. If you -- want a custom instance for an already instantiated type, -- wrap that type using @newtype@, and then create your own -- instance. Since every element of a matrix must be of the -- same type, for mixed tables you might want to create an -- union type. For example, if your data matrix contains -- 'Int's and 'Double's: -- -- > data Number = R Double | I Int -- > -- > instance Texy Number where -- > texy (R x) = texy x -- > texy (I x) = texy x -- -- Now you can have a matrix of type @Matrix Number@ and use it -- to render your mixed data in a LaTeX table. -- -- The function 'matrixTabular' does not give you many options, -- so it is not as flexible as generating the table by yourself, -- but it uses a reasonable standard style. -- -- A very simple example: -- -- > matrixTabular (fmap textbf ["x","y","z"]) $ -- > fromList 3 3 [ (1 :: Int)..] -- -- This code generates the following table: -- -- <> -- -- For more examples see the file @Examples/tables.hs@, included -- in the source distribution. -- -- For more info about how to generate and manipulate matrices, -- see "Data.Matrix". -- matrixTabular :: (LaTeXC l, Texy a) => [l] -- ^ (Non-empty) List of column titles -> Matrix a -- ^ Matrix of data -> l -- ^ Data organized in a tabular environment matrixTabular ts m = let spec = VerticalLine : (intersperse VerticalLine $ replicate (ncols m) CenterColumn) ++ [VerticalLine] in tabular Nothing spec $ mconcat [ hline , foldl1 (&) ts , lnbk , hline , mconcat $ fmap ( \i -> mconcat [ foldl1 (&) $ fmap (\j -> texy (m ! (i,j))) [1 .. ncols m] , lnbk , hline ] ) [1 .. nrows m] ] ----------------------------------------- ----------------------------------------- -- | @cline i j@ writes a partial horizontal line beginning in column @i@ and ending in column @j@. cline :: LaTeXC l => Int -> Int -> l cline i j = fromLaTeX $ TeXComm "cline" [ FixArg $ TeXRaw $ render i <> "-" <> render j ] parbox :: LaTeXC l => Maybe Pos -> Measure -> l -> l parbox Nothing w = liftL $ \t -> TeXComm "parbox" [ FixArg $ rendertex w , FixArg t ] parbox (Just p) w = liftL $ \t -> TeXComm "parbox" [ OptArg $ TeXRaw $ render p , FixArg $ TeXRaw $ render w , FixArg t ] makebox :: LaTeXC l => Maybe Measure -> Maybe HPos -> l -> l makebox Nothing Nothing = liftL $ \t -> TeXComm "makebox" [ FixArg t ] makebox (Just w) Nothing = liftL $ \t -> TeXComm "makebox" [ OptArg $ TeXRaw $ render w , FixArg t ] makebox Nothing (Just p) = liftL $ \t -> TeXComm "makebox" [ OptArg $ TeXRaw $ render p , FixArg t ] makebox (Just w) (Just p) = liftL $ \t -> TeXComm "makebox" [ OptArg $ TeXRaw $ render w , OptArg $ TeXRaw $ render p , FixArg t ] framebox :: LaTeXC l => Maybe Measure -> Maybe HPos -> l -> l framebox Nothing Nothing = liftL $ \t -> TeXComm "framebox" [ FixArg t ] framebox (Just w) Nothing = liftL $ \t -> TeXComm "framebox" [ OptArg $ TeXRaw $ render w , FixArg t ] framebox Nothing (Just p) = liftL $ \t -> TeXComm "framebox" [ OptArg $ TeXRaw $ render p , FixArg t ] framebox (Just w) (Just p) = liftL $ \t -> TeXComm "framebox" [ OptArg $ TeXRaw $ render w , OptArg $ TeXRaw $ render p , FixArg t ] raisebox :: LaTeXC l => Measure -> Maybe Measure -> Maybe Measure -> l -> l raisebox m ma mb = liftL $ \l -> TeXComm "raisebox" $ [ FixArg $ rendertex m ] ++ fmap (OptArg . rendertex) (catMaybes [ma,mb]) ++ [ FixArg l ] -- | Produce a simple black box. rule :: LaTeXC l => Maybe Measure -- ^ Optional lifting. -> Measure -- ^ Width. -> Measure -- ^ Height. -> l rule Nothing w h = fromLaTeX $ TeXComm "rule" [ FixArg $ TeXRaw $ render w , FixArg $ TeXRaw $ render h ] rule (Just l) w h = fromLaTeX $ TeXComm "rule" [ OptArg $ TeXRaw $ render l , FixArg $ TeXRaw $ render w , FixArg $ TeXRaw $ render h ] -- HaTeX specific symbols -- | Print the HaTeX logo. hatex :: LaTeXC l => l hatex = mbox $ "H" <> hspace (Ex $ negate 0.3) <> textsc "a" <> hspace (Ex $ negate 0.3) <> tex -- | Print the HaTeX 3 logo. hatex3 :: LaTeXC l => l hatex3 = hatex <> emph (textbf "3") -- | Print the HaTeX logo, beside the complete version number. hatex_version :: LaTeXC l => l hatex_version = hatex <> emph (textbf $ rendertex x) <> hspace (Ex $ negate 0.3) <> emph ("." <> fromString (intercalate "." $ fmap show xs)) where (x:xs) = versionBranch version caption :: LaTeXC l => l -> l caption = liftL $ \l -> TeXComm "caption" [FixArg l] label :: LaTeXC l => l -> l label = liftL $ \l -> TeXComm "label" [FixArg $ TeXRaw $ render l] ref :: LaTeXC l => l -> l ref = liftL $ \l -> TeXComm "ref" [FixArg $ TeXRaw $ render l] pageref :: LaTeXC l => l -> l pageref = liftL $ \l -> TeXComm "pageref" [FixArg $ TeXRaw $ render l] -- Exteral files -- | Import an external file and insert its content /as it is/. input :: LaTeXC l => FilePath -> l input fp = fromLaTeX $ TeXComm "input" [FixArg $ TeXRaw $ fromString fp] -- | Similar to 'input', but forces a page break. -- -- /Note: the file you are including cannot include other files./ include :: LaTeXC l => FilePath -> l include fp = fromLaTeX $ TeXComm "include" [FixArg $ TeXRaw $ fromString fp]