hatex-guide (empty) → 1.0
raw patch · 16 files changed
+1066/−0 lines, 16 filesdep +HaTeXdep +basedep +directorybuild-type:Customsetup-changedbinary-added
Dependencies added: HaTeX, base, directory, filepath, parsec, text
Files
- README.md +61/−0
- Setup.hs +21/−0
- Text/LaTeX/Guide.hs +31/−0
- Text/LaTeX/Guide/Backend/LaTeX.hs +98/−0
- Text/LaTeX/Guide/Backend/Wiki.hs +99/−0
- Text/LaTeX/Guide/Info.hs +44/−0
- Text/LaTeX/Guide/Syntax.hs +216/−0
- hatex-guide.cabal +50/−0
- license +28/−0
- res/machine.png binary
- src/basics.htxg +179/−0
- src/class.htxg +16/−0
- src/epilogue.htxg +12/−0
- src/monad.htxg +143/−0
- src/packages.htxg +35/−0
- src/preface.htxg +33/−0
+ README.md view
@@ -0,0 +1,61 @@+# HaTeX User's Guide++_Welcome to the HaTeX User's Guide!_++A pdf version (created from the LaTeX output) can be downloaded from+[here](http://daniel-diaz.github.com/projects/hatex/hatex-guide.pdf).++# Building the guide++To build the guide, first you need to install the library.++## Installing from Hackage++Using _cabal-install_ you can install the library directly from Hackage.++ $ cabal install hatex-guide++The installed package includes a small library which exports a function+called `writeGuide`. This function has a parameter indicating the format+of the output. For example, `writeGuide LaTeX` will write the output in+the current directory in LaTeX format. Read the package documentation+to know about the supported formats.++Once the package is installed, run GHCi and run the following session.++ $ import Text.LaTeX.Guide+ $ writeGuide LaTeX++## Installing HEAD version++Run the following commands to download and install the HEAD version. _Requires git and cabal_.++ $ git clone git@github.com:Daniel-Diaz/hatex-guide.git+ $ cd hatex-guide+ $ cabal install++Once installed, import `Text.LaTeX.Guide` and use `writeGuide` to build the actual guide.+Depending on the argument used for `writeGuide`, the output will have a different format.+For example, `writeGuide LaTeX` will output in the current directory a `.tex` file of the guide.++# Contributing to the guide++There are several things to keep in mind to contribute to the guide.+If you contribute, do not forget to add your name to the `contributors` list to bound in the+`Text.LaTeX.Guide.Info` module.++## Sections++Each section of the guide is written in a different file. Every section is stored in the `src`+folder in the repository. The order in which each section appears in the guide is determined by the `sectionList`+constant defined in the `Text.LaTeX.Guide.Info` module.++## Syntax++The syntax used to write the guide is described in `Text.LaTeX.Guide.Syntax`.+The current content can also be helpful to understand it.++## Images++When including images, it is required to save them in the `res` directory, and include their file name in the+`otherResources` value defined in the `Text.LaTeX.Guide.Info` module.
+ Setup.hs view
@@ -0,0 +1,21 @@++import Distribution.Simple+import System.Directory+ ( copyFile+ , getAppUserDataDirectory+ , createDirectoryIfMissing+ )+import Text.LaTeX.Guide (sectionList)+import Text.LaTeX.Guide.Info (otherResources)+import System.FilePath ((</>),(<.>))++main :: IO ()+main = do+ d <- getAppUserDataDirectory "hatex-guide"+ createDirectoryIfMissing True $ d </> "src"+ createDirectoryIfMissing True $ d </> "res"+ mapM_ (\s -> let fp = "src" </> s <.> "htxg"+ in copyFile fp $ d </> fp) sectionList+ mapM_ (\r -> let fp = "res" </> r+ in copyFile fp $ d </> fp) otherResources+ defaultMain
+ Text/LaTeX/Guide.hs view
@@ -0,0 +1,31 @@++-- | The HaTeX User's Guide.+--+-- This module generates the HaTeX User's Guides from its+-- custom syntax to any available format.+-- This format is specified feeding the function 'writeGuide'+-- with a value of type 'Backend'.+--+-- More information about how this library works can be found+-- at the code repository on GitHub:+--+-- <https://github.com/Daniel-Diaz/hatex-guide>+--+module Text.LaTeX.Guide (+ -- * Backends+ Backend (..)+ , writeGuide+ -- * Info+ , sectionList+ , contributors+ ) where++import Text.LaTeX.Guide.Info+import qualified Text.LaTeX.Guide.Backend.LaTeX as LaTeX+import qualified Text.LaTeX.Guide.Backend.Wiki as Wiki++-- | Write in the current directory the LaTeX User's Guide using+-- a determined backend.+writeGuide :: Backend -> IO ()+writeGuide LaTeX = LaTeX.backend+writeGuide Wiki = Wiki.backend
+ Text/LaTeX/Guide/Backend/LaTeX.hs view
@@ -0,0 +1,98 @@++{-# LANGUAGE OverloadedStrings #-}++module Text.LaTeX.Guide.Backend.LaTeX (+ backend+ ) where++import Text.LaTeX.Guide.Syntax+import Text.LaTeX.Guide.Info hiding (LaTeX)+--+import Text.LaTeX+import Text.LaTeX.Packages.Color+import Text.LaTeX.Packages.Hyperref+import Text.LaTeX.Packages.Graphicx+import Text.LaTeX.Packages.Inputenc+import Text.LaTeX.Packages.AMSMath+import Text.LaTeX.Packages.Babel+import Data.Version (showVersion,versionBranch)+import Data.Text (unpack)+import Data.Text.IO+import Data.List (intersperse)+import System.FilePath ((</>))+import System.Directory (getAppUserDataDirectory)+import qualified Paths_hatex_guide as G++sectFromInt :: Int -> LaTeX -> LaTeX+sectFromInt 1 = section+sectFromInt 2 = subsection+sectFromInt 3 = subsubsection+sectFromInt 4 = paragraph+sectFromInt 5 = subparagraph+sectFromInt n = error $ "Subsection with hierarchy of " ++ show n ++ " is not available in the LaTeX backend."++hatexSyntax :: FilePath -> Syntax -> LaTeX+hatexSyntax _ (Raw t) = raw $ protectText t+hatexSyntax fp (Section n s) = sectFromInt n $ hatexSyntax fp s+hatexSyntax fp (Bold s) = textbf $ hatexSyntax fp s+hatexSyntax fp (Italic s) = textit $ hatexSyntax fp s+hatexSyntax _ (Code b t) = let f = if b then texttt . raw . protectText+ else quote . verbatim+ c = ModColor $ RGB255 50 50 255+ in color c <> f t <> normalcolor+hatexSyntax _ (URL t) = let u = createURL $ unpack t+ in url u+hatexSyntax fp (IMG t) = center $ includegraphics [] $ fp </> unpack t+hatexSyntax _ LaTeX = latex+hatexSyntax _ HaTeX = hatex+hatexSyntax _ (Math t) = math $ raw t+hatexSyntax fp (Footnote s) = footnote $ hatexSyntax fp s+hatexSyntax fp (Append s1 s2) = hatexSyntax fp s1 <> hatexSyntax fp s2+hatexSyntax _ Empty = mempty++thePreamble :: LaTeX+thePreamble =+ documentclass [a4paper] article+ <> uselanguage English+ <> usepackage [utf8] inputenc+ <> usepackage [] hyperref+ <> usepackage [] graphicx+ <> usepackage [] pcolor+ <> title ("The " <> hatex <> " User's Guide")+ <> author (raw "Daniel D\\'iaz")+ <> linespread 1.4++theTitle :: LaTeX+theTitle = let xs = versionBranch version in flushright (+ resizebox (Pt 300) (Pt 40) (textbf "HATEX " <> (rendertex $ head xs)) <> lnbk+ <> textit ("The User's Guide, version "+ <> fromString (showVersion G.version)+ <> " (using " <> hatex <> " " <> fromString (showVersion version) <> ")") <> lnbk+ <> rule (Just $ Pt 10) (CustomMeasure textwidth) (Pt 2) <> lnbk+ <> url (createURL "https://github.com/Daniel-Diaz/HaTeX") <> lnbk+ <> textit (textbf "Main author: " <> raw "Daniel D\\'iaz (" <> texttt "dhelta.diaz@gmail.com" <> ")" ) <> lnbk+ <> if null contributors then mempty else+ ("Contributors:" <> lnbk <> mconcat (fmap ((<> lnbk) . fromString) contributors))+ )+ <> raw "\\vfill{}"+ <> flushleft ("Date of creation: " <> today <> ".")++initial :: LaTeX+initial = + raw "\\setcounter{page}{-1}" <> thispagestyle empty <> theTitle <> newpage+ <> thispagestyle empty <> tableofcontents <> newpage++createManual :: IO LaTeX+createManual = do+ d <- getAppUserDataDirectory "hatex-guide"+ fmap (mappend thePreamble . document . mappend initial+ . mconcat . intersperse newpage . fmap (hatexSyntax $ d </> "res")) parseSections++backend :: IO ()+backend = do + Prelude.putStrLn "Creating guide..."+ m <- createManual+ Prelude.putStrLn "Writing guide file..."+ let fp = outputName ".tex"+ Data.Text.IO.writeFile fp $ render m+ Prelude.putStrLn $ "Guide written in " <> fp <> "."
+ Text/LaTeX/Guide/Backend/Wiki.hs view
@@ -0,0 +1,99 @@++{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}++module Text.LaTeX.Guide.Backend.Wiki (+ backend+ ) where++import Text.LaTeX.Guide.Syntax+import Text.LaTeX.Guide.Info hiding (Backend(..))+import Data.Monoid (Monoid (..))+import Data.Text+import Data.Text.IO+import Data.Functor+import Data.Function+import Prelude (Eq (..), Num (..),IO,Monad (..), Int, uncurry, Show (..))+import Data.Maybe+import Control.Arrow+import Text.LaTeX.Base (version)+import Data.Version (showVersion)+import Data.String (IsString (..))+import Data.Bool++(<>) :: Monoid m => m -> m -> m+(<>) = mappend++tag :: Text -> Text -> Text+tag t x = mconcat [ "<" , t , ">" , x , "</" , t , ">" ]++data Wiki = Wiki ( (Int,Int -> Text) -> (Int,Int -> Text,Text) )++instance Monoid Wiki where+ mempty = Wiki $ \(i,f) -> (i,f,mempty)+ mappend (Wiki g) (Wiki g') =+ Wiki $ \s -> let (i',f',t) = g s+ (i'',f'',t') = g' (i',f')+ in (i'',f'',mappend t t')++text :: Text -> Wiki+text t = Wiki $ \(i,f) -> (i,f,t)++syntaxWiki :: Syntax -> Wiki+syntaxWiki (Raw t) = text t+syntaxWiki (Section n s) =+ let m = 1 + n+ d = text $ replicate m "="+ in d <> syntaxWiki s <> d+syntaxWiki (Bold s) =+ let d = text "'''"+ in d <> syntaxWiki s <> d+syntaxWiki (Italic s) =+ let d = text "''"+ in d <> syntaxWiki s <> d+syntaxWiki (Code b t) =+ let f = tag $ if b then "hask" else "haskell"+ in text $ f t+syntaxWiki (URL t) = text t+-- Images no supported.+syntaxWiki (IMG t) = mempty+syntaxWiki LaTeX = text "LaTeX"+syntaxWiki HaTeX = text "HaTeX"+syntaxWiki (Math t) = text $ tag "math" t+syntaxWiki (Footnote s) =+ Wiki (\(i,f) ->+ let i0 = i + 1+ Wiki f' = syntaxWiki s+ (_,_,t) = f' (i0,f)+ g = \n -> if n == i0 then t else f n+ in (i+1,g, "[[#Footnotes|" <> tag "sup" (fromString $ show i0) <> "]]")+ )+syntaxWiki (Append s1 s2) = syntaxWiki s1 <> syntaxWiki s2+syntaxWiki Empty = mempty++initial :: Text+initial = mempty++ending :: Text+ending = mempty++renderWiki :: Wiki -> Text+renderWiki (Wiki f) = initial <> t <> foots <> ending+ where+ (last,footf,t) = f (0 , const mempty)+ foots = unlines $ "\n\n==Footnotes==\n" :+ fmap (\n -> tag "sup" (fromString $ show n) <> ": " <> strip (footf n) <> "\n") [ 1 .. last ]++backend :: IO ()+backend = fmap (strip . renderWiki . syntaxWiki . mconcat . fmap (syntLineBreaks . (Raw "\n\n" <>))) parseSections >>= writeFile (outputName ".wiki")++-- Line breaks++syntLineBreaks :: Syntax -> Syntax+syntLineBreaks (Raw t) = Raw $ nolineBreaks t+syntLineBreaks (Bold s) = Bold $ syntLineBreaks s+syntLineBreaks (Italic s) = Italic $ syntLineBreaks s+syntLineBreaks (Append s1 s2) = Append (syntLineBreaks s1) (syntLineBreaks s2)+syntLineBreaks s = s++nolineBreaks :: Text -> Text+nolineBreaks = intercalate "\n\n" . fmap (unwords . lines) . splitOn "\n\n"
+ Text/LaTeX/Guide/Info.hs view
@@ -0,0 +1,44 @@++module Text.LaTeX.Guide.Info (+ sectionList+ , contributors+ , Backend (..)+ , parseSections+ , outputName+ , otherResources) where++import Text.LaTeX.Guide.Syntax+import System.FilePath+import Data.Monoid+import System.Directory (getAppUserDataDirectory)++-- | Ordered list of sections.+sectionList :: [String]+sectionList = [+ "preface"+ , "basics"+ , "monad"+ , "class"+ , "packages"+ , "epilogue"+ ]++-- | List of contributors. Please, insert your name here if you have contributed+-- in some way to the guide.+contributors :: [String]+contributors = [ ]++-- | Available backends.+data Backend = LaTeX | Wiki++parseSections :: IO [Syntax]+parseSections = do+ d <- getAppUserDataDirectory "hatex-guide"+ mapM (parseFile . (<.> "htxg") . combine d . combine "src") sectionList++outputName :: String -> FilePath+outputName = mappend "hatex-guide"++-- |+otherResources :: [String]+otherResources = [ "machine.png" ]
+ Text/LaTeX/Guide/Syntax.hs view
@@ -0,0 +1,216 @@++{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}++module Text.LaTeX.Guide.Syntax (+ Syntax (..)+ , Text+ , printSyntax+ , parseSyntax+ , parseFile+ ) where++import Text.LaTeX.Base hiding (between)+import Text.Parsec hiding (Empty)+import Text.Parsec.Text ()+import Data.Text+import Data.Text.IO hiding (putStr)+import Data.Monoid+import Data.Int+import Data.Bool+import Prelude (Eq(..),Show(..),FilePath,Enum)+import Data.Function+import Control.Monad+import qualified Data.List as L+import Data.Char+import Data.Either+import Data.Maybe+import System.IO(IO,hFlush,stdout,putStr)+import Text.LaTeX.Packages.Hyperref+import Text.LaTeX.Packages.Graphicx+import Text.LaTeX.Packages.AMSMath+import Text.LaTeX.Packages.Color++{- Syntax table++-- Sections+ # ... # Section+## ... ## Subsection+and so on...++-- Styles+* ... * Bold+/ ... / Italic++-- Code+\{ ... \} Inline+\[ ... \] No-inline++-- Math+$ ... $ Math++-- Utils+< ... > URL+| ... | Image+\latex LaTeX logo+\hatex HaTeX logo+\f ... \f Footnote++To escape reserved characters, use the backslash (\).++-}++data Syntax =+ -- Plain text+ Raw Text+ -- Features+ | Section Int Syntax+ | Bold Syntax+ | Italic Syntax+ | Code Bool Text -- If True then inline.+ | URL Text+ | IMG Text+ | LaTeX+ | HaTeX+ | Math Text+ | Footnote Syntax+ -- Monoid constructors+ | Append Syntax Syntax+ | Empty+ deriving Show++instance Monoid Syntax where+ mappend Empty x = x+ mappend x Empty = x+ mappend x y = Append x y+ mempty = Empty++-- Printer++printSyntax :: Syntax -> Text+printSyntax (Raw t) = concatMap (\c -> if c `L.elem` resChars then "\\" <> singleton c else singleton c) t+printSyntax (Section n s) = let d = replicate n "#" in d <> printSyntax s <> d+printSyntax (Bold s) = "*" <> printSyntax s <> "*"+printSyntax (Italic s) = "/" <> printSyntax s <> "/"+printSyntax (Code b t) = let (d1,d2) = if b then ("\\{","\\}") else ("\\[","\\]")+ in d1 <> t <> d2+printSyntax (URL t) = "<" <> t <> ">"+printSyntax (IMG t) = "|" <> t <> "|"+printSyntax LaTeX = "\\LaTeX"+printSyntax HaTeX = "\\HaTeX"+printSyntax (Math t) = let d = "$" in d <> t <> d+printSyntax (Footnote s) = let d = "\\f" in d <> printSyntax s <> d+printSyntax (Append s1 s2) = printSyntax s1 <> printSyntax s2+printSyntax Empty = mempty++-- Parser++data ParseItem =+ PSection+ | PBold+ | PItalic+ | PFootnote+ deriving (Eq,Enum)++allParseItems :: [ParseItem]+allParseItems = [ PSection .. ]++parseItem :: ParseItem -> Parser Syntax+---------------------------------------+parseItem PSection = do+ xs <- many1 (char '#')+ let n = L.length xs+ s <- p_SyntaxWith PSection+ ys <- string $ L.replicate n '#'+ return $ Section n s+---------------------------------------+parseItem PBold = p_Chars Bold PBold '*' '*'+---------------------------------------+parseItem PItalic = p_Chars Italic PItalic '/' '/'+---------------------------------------+parseItem PFootnote = between (char 'f') (string "\\f") $ fmap Footnote $ p_SyntaxWith PFootnote++type Parser = Parsec Text (ParseItem -> Bool)++itemTo :: ParseItem -> Bool -> Parser ()+itemTo pi b = modifyState $ \f -> \x -> if x == pi then b else f x++p_SyntaxWith :: ParseItem -> Parser Syntax+p_SyntaxWith pi = between (pi `itemTo` False) (pi `itemTo` True) p_Syntax++p_Chars :: (Syntax -> a) -> ParseItem -> Char -> Char -> Parser a+p_Chars f pi c1 c2 = fmap f $ between (char c1) (char c2) $ p_SyntaxWith pi++p_Backslash :: Parser Syntax+p_Backslash = do+ char '\\'+ let ps = [ p_Code , p_LaTeX , p_HaTeX , fmap (Raw . fromString . (\c -> ['\\',c])) $ noneOf "f" ]+ f <- getState+ choice $ if f PFootnote then parseItem PFootnote : ps else ps++p_Code :: Parser Syntax+p_Code = do+ d <- char '{' <|> char '['+ let b = d == '{'+ xs <- manyTill anyChar $ try $ string ['\\',if b then '}' else ']']+ return $ Code b $ fromString xs++p_LaTeX :: Parser Syntax+p_LaTeX = string "latex" >> return LaTeX++p_HaTeX :: Parser Syntax+p_HaTeX = string "hatex" >> return HaTeX++p_URL :: Parser Syntax+p_URL = do+ char '<'+ xs <- many $ noneOf ">"+ char '>'+ return $ URL $ fromString xs++p_IMG :: Parser Syntax+p_IMG = do+ char '|'+ xs <- many $ noneOf "|"+ char '|'+ return $ IMG $ fromString xs++p_Math :: Parser Syntax+p_Math = do+ char '$'+ xs <- many $ noneOf "$"+ char '$'+ return $ Math $ fromString xs++p_Raw :: Parser Syntax+p_Raw = fmap (Raw . fromString) $ many1 $ noneOf resChars++resChars :: [Char]+resChars = "$/\\#<>|*"++p_Syntax :: Parser Syntax+p_Syntax = do+ f <- getState+ let xs = L.filter f allParseItems+ ts = [ p_URL , p_IMG , p_Math , p_Raw , try p_Backslash ]+ fmap mconcat $ many $ choice $ ts `mappend` fmap parseItem xs++parseSyntax :: FilePath -> Text -> Either ParseError Syntax+parseSyntax = runParser (withEOF p_Syntax) (const True)++withEOF :: (Stream s m t, Show t) => ParsecT s u m b -> ParsecT s u m b+withEOF = (>>= (eof >>) . return)++-- IO++putStr' :: String -> IO ()+putStr' = (>> hFlush stdout) . putStr++parseFile :: FilePath -> IO Syntax+parseFile fp = do+ putStr' $ mconcat [ "Reading file " , fp , "... " ]+ putStrLn "Done."+ t <- readFile fp+ putStr' $ mconcat [ "Parsing " , fp , "... " ]+ case parseSyntax fp t of+ Left e -> putStrLn "ParseFailed." >> fail (show e)+ Right s -> putStrLn "ParseOk." >> return s
+ hatex-guide.cabal view
@@ -0,0 +1,50 @@+Name: hatex-guide+Version: 1.0+Author: Daniel Díaz+Category: LaTeX+Build-type: Custom+License: BSD3+License-file: license+Maintainer: Daniel Díaz (dhelta `dot` diaz `at` gmail `dot` com)+Bug-reports: https://github.com/Daniel-Diaz/hatex-guide/issues+Synopsis: HaTeX User's Guide.+Description: The HaTeX User's Guide is a manual explaining the+ HaTeX library (<http://hackage.haskell.org/package/HaTeX>).+ This library can be used to output the guide in different formats.+ A compiled pdf version of the latex output can be found at+ <http://daniel-diaz.github.com/projects/hatex/hatex-guide.pdf>.+ See the README file (<https://github.com/Daniel-Diaz/hatex-guide/blob/master/README.md>)+ for more details.+Cabal-version: >= 1.6+Extra-source-files:+ -- README file+ README.md+ -- Source of the guide+ src/basics.htxg+ src/class.htxg+ src/epilogue.htxg+ src/monad.htxg+ src/packages.htxg+ src/preface.htxg+ -- Other resources (like images)+ res/machine.png++Source-repository head+ type: git+ location: git@github.com:Daniel-Diaz/hatex-guide.git++Library+ Build-depends: base == 4.*+ , HaTeX == 3.6.*+ , text == 0.11.*+ , filepath+ , parsec >= 3.1.2 && < 3.2+ , directory+ Exposed-modules:+ Text.LaTeX.Guide+ Other-modules:+ Paths_hatex_guide+ Text.LaTeX.Guide.Syntax+ Text.LaTeX.Guide.Info+ Text.LaTeX.Guide.Backend.LaTeX+ Text.LaTeX.Guide.Backend.Wiki
+ license view
@@ -0,0 +1,28 @@+Copyright (c)2013, Daniel Díaz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Daniel Díaz nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ res/machine.png view
binary file changed (absent → 94211 bytes)
+ src/basics.htxg view
@@ -0,0 +1,179 @@+#Basics#++Through this section you will learn the basics of \hatex. Essentially, /how/ it works.++##The Monoid class##++If you are already familiar with the \{Monoid\} class, jump to the next point.+The \{Monoid\} class is something that you must get used to in Haskell. But don't worry, it is quite simple+(in spite of the similarity in the name with the \{Monad\} class).+A /monoid/ in Mathematics is an algebraic structure consisting of a set of objects with+an operation between them, being this operation /associative/ and with a /neutral element/.+Phew! But what is the meaning of this? By /associative/ we mean that, if you have three elements+$a$, $b$ and $c$, then $a*(b*c) = (a*b)*c$. A /neutral element/ is the one that does not worth to operate with,+because it does nothing! To say, $e$ is a /neutral element/ if $e*a=a*e=a$, given any object $a$.+As an example, you may take the /real numbers/ as objects and the ordinary multiplication as operation.++Now that you know the math basics behind the \{Monoid\} class, let's see its definition:+\[+class Monoid m where+ mempty :: m+ mappend :: m -> m -> m+ mconcat :: [m] -> m+\]+See that \{mappend\} corresponds to the monoid operation and \{mempty\} to its neutral element.+The names of the methods may seem insuitable, but they correspond to an example of monoid:+the lists with the appending \{(++)\} operation. Who is the neutral element here? The empty list:+\[+xs ++ [] = [] ++ xs = xs+\]+This class plays a significant role in \hatex. Keep reading.++##LaTeX blocks##++Suppose we have a well-formed\f+With /well-formed/ we mean that all braces, environments, math expressions, ... are closed.+\f+piece of \latex code, call it $a$.+Now, let \{LaTeX\} be a Haskell type in which each element represents a well-formed+piece of \latex code. Then, $a$ can be seen as a Haskell expression \{a\} of type \{LaTeX\}.+We can say that \{a\} is a \{LaTeX\} *block*. What happens if we append, by juxtaposition,+two \{LaTeX\} blocks? As both are well-formed, so is the result. Thus, two blocks appended form+another block. This way, we can define an operation over the \{LaTeX\} blocks. If we consider that+a totally empty code is a well-formed piece of \latex code, we can speak about the empty block.+And, as the reader may notice, these blocks with its appending form a monoid. Namely, \{LaTeX\}+can be done an instance of the \{Monoid\} class.++Of course, our mission using \hatex is to create a \{LaTeX\} block that fits our purpose. The+way to achieve this is to create a multitude of \{LaTeX\} blocks and, then, use the \{Monoid\} operation+to collapse them all in a single block.++##Creating blocks##++We have now a universe of blocks forming a monoid. What we need now is a way to create these blocks.+As we said, a block is the representation of a well-formed piece of \latex code. Let \{a\} be the+block of the \latex expression \{\delta{}\}\f+Please, note that the \{LaTeX\} block is *not* the same that the \latex expression. The former+is a Haskell value, not the \latex code itself.+\f.+Since this is a constant expression, it has a constant value in Haskell, named \{delta\}. Calling+this value will generate the desired block.++Other \latex expressions depend on a given argument. For example \{\linespread{x}\}, where \{x\} is+a number. How we deal with this? As you expect, with functions. We can create blocks that depend on+values with functions that take these values as arguments, where these arguments can be+blocks as well. For instance, we have the function \{linespread\} with type:+\[+linespread :: Float -> LaTeX+\]+As you may know, a title in \latex can contain itself \latex code. So the type for the Haskell+function \{title\} is:+\[+title :: LaTeX -> LaTeX+\]+And this is, essentialy, the way to work with \hatex: *to create blocks and combine them*.+Once you have your final block ready, you will be able to create its corresponding \latex code+(we will see how later). Note that for every block there is a \latex code, but not for every code+there is a block, because a malformed (in the sense of the negation of our well-formed concept) code+has *not* a block in correspondence.+This fact has a practical consequence: *we cannot create malformed \latex code*. /And that's a good deal!/++###From strings###++Inserting text in a \latex document is a constant task. You can create a block with text given+an arbitrary \{String\} with the \{fromString\} function, method of the \{IsString\} class:+\[+class IsString a where+ fromString :: String -> a+\]+Since there is a set of characters reserved to create commands or another constructions,+\hatex takes care and avoids them replacing each reserved character with a command which+output looks like the original character. For example, the backslash \{\\} is replaced with+the \{\backslash{}\} command.++The function that avoids reserved characteres is exported with the name \{protectString\}.+Also, there is a variant for \{Text\} values called \{protectText\}.++The use of the \{IsString\} class is because the /Overloaded Strings/ extension.+This one is similar to the /Overloaded Numbers/ Haskell feature, which translates the number+\{4\} to \{fromInteger 4\}. In a similar way, with \{OverloadedStrings\} enabled, the string+\{"foo"\} is translated to \{fromString "foo"\}. If we now apply this to our blocks,+the string \{"foo"\} will be automatically translated to a \{latex\} block with /foo/ as content.+Quite handy! We will assume the \{OverloadedStrings\} extension enabled from now.++###More blocks###++There is a lot of functions for create blocks. In fact, we can say that this is the main purpose+of the library. \latex has a lot of commands, in order to set font attributes, create tables,+insert graphics, include mathematical symbols, etc. So \hatex have a function for each command+defined in \latex (to tell the truth, only for a small subset). Please, go to the API documentation+to read about particular functions. Build it locally or find it in Hackage: <http://hackage.haskell.org/package/HaTeX>.+You will find the class constraint \{LaTeXC l\} in every entity. \{LaTeX\} is an instance of this+class, so you can assume that \{l\} is the \{LaTeX\} datatype without any problem. More about+this in section about the \{LaTeXC\} class.++##Putting blocks together##++Once you have the blocks, as we said before, you need to append them. The \{mappend\}+method of the \{Monoid\} class does this work. If \{a\} and \{b\} are two blocks,+\{mappend a b\}, or \{a `mappend` b\}, or even \{a <> b\}\f+From *GHC 7.4*, \{(<>)\} is defined as a synonym for \{mappend\}. For previous+versions of GHC, \hatex exports the synonym.+\f, is the block with+\{a\} and \{b\} juxtaposed. For long lists of blocks, you can try it with \{mconcat\}+as follows:+\[+mconcat [ "I can see a " , textbf "rainbow"+ , " in the blue " , textit "sky" , "." ]+\]++##Rendering##++This is the last step in our \latex document creation. When we have our final+\latex block \{a\}, the function \{renderFile\} can output it into a file, in+the form of its correspondent \latex code.++Say we have the next definition:+\[+short =+ documentclass [] article+ <> title "A short message"+ <> author "John Short"+ <> document (maketitle <> "This is all.")+\]+Then, after call \{renderFile "short.tex" short\} it appears the following file+in the current working directory (line formatting added for easier visualization):+\[+\documentclass{article}+\title{A short message}+\author{John Short}+\begin{document}+\maketitle{}+This is all+\end{document}+\]+The function \{renderFile\} is not only for \{LaTeX\} values. Let's see its type:+\[+renderFile :: Render a => FilePath -> a -> IO ()+\]+The \{Render\} class that appears in the context is defined:+\[+class Render a where+ render :: a -> Text+\]+So, it is the class of types that can be rendered to a \{Text\} value. The+type \{LaTeX\} is an instance, but other types, like \{Int\} or \{Float\}, so are too.+These instances are useful for creating blocks from other values. With the function+\{rendertex\}, any value in the \{Render\} class can be transformed to a block. First,+the value is converted to \{Text\}, and then to \{LaTeX\} the same way we did with strings.+But, *be careful!* Because \{rendertex\} does *not* escape reserved characters.++##Try yourself##++As always, the best way to learn something well is to try it by yourself.+Since to see code examples can give you a great help, \hatex comes with several+examples where you can see by yourself how to get the work done.++The API reference is also a good point to keep in mind. Descriptions of functions+make you know how exactly they works. And, when they are not present, function names+with type signatures may be very helpful and descriptive.
+ src/class.htxg view
@@ -0,0 +1,16 @@+#The LaTeXC class#++\hatex has two different interfaces. One uses blocks as \{Monoid\} elements and the other+as \{Monad\} actions. If we want to keep both interfaces we have two choices: to duplicate+function definitions\f+This was the approach taken in \hatex 3 until the version 3.3, where the \{LaTeXC\} class was included.+\f+or to have a typeclass which unifies both interfaces. Since duplicate definitions is a hard work+and can arise problems\f+In fact, we had a problem with \hatex-meta, the program that automatically generated the duplicated functions.+The problem was described in a blog post: <http://deltadiaz.blogspot.com.es/2012/04/hatex-trees-and-problems.html>.+\f, we took the second alternative and defined the \{LaTeXC\} typeclass. Both \{LaTeX\} and \{LaTeXT m a\} are+instances of \{LaTeXC\} (the second one is a little tricky), so every function in \hatex is defined using the+typeclass. This way, we have both interfaces with a single import, without being worry about maintaining+duplicated code. The cost is to have class constraints in type signatures. But these constraints are only required+in the package. At the user level, you choose your interface and write type signatures in consequence.
+ src/epilogue.htxg view
@@ -0,0 +1,12 @@+#Epilogue#++##Notes about this guide##++*This guide is not static*. It will be changed, extended and improved with the time.+If you think there is something unclear, something hard to understand, please, report it.++##Notes from the author##++I would like to end this guide saying thanks to all the people that has been interested+in \hatex somehow, especially to those who contributed to it with patches, opinions+or bug reports. *Thanks*.
+ src/monad.htxg view
@@ -0,0 +1,143 @@+#LaTeX blocks and the Writer monad#++##The Writer Monad##+Fixed a monoid \{M\}, the \{M\}-writer monad is just all possible pairs of elements from \{M\}+and elements from other types. Thus, the Haskell declaration is as follows\f+Some authors write it using tuples, like this: \{data W m a = W (a,m)\}.\f:+\[+data W m a = W m a+\]+Note that to get the monad we need to fix the type \{m\} (kind of monads is \{* -> *\}). To inject+an arbitrary value into the monad (the Haskell \{return\} function) we use the neutral element (\{mempty\})+of the monoid.+\[+inject :: Monoid m => a -> W m a+inject a = W mempty a+\]+Think that no other element of \{m\} is possible to think: it is the only element we know of it!+Like any other monad, \{W m\} is also a \{Functor\}. We just apply the function to the value.+\[+instance Functor (W m) where+ fmap f (W m a) = W m (f a)+\]+Every \{Monad\} instance can be given by the two monad operations \{inject\} and \{join\}. We already+defined the \{inject\} function. The other one deletes one monad type constructor.+\[+join :: Monoid m => W m (W m a) -> W m a+join (W m (W m' a)) = W (mappend m m') a+\]+In this function we use the other \{Monoid\} method to combine both values. It is important to+note that in both monad operations \{inject\} and \{join\} we used \{mempty\} and \{mappend\}+respectively. In practice, this is because they act equal. Indeed, they are equal if we forget the+\{a\} value. Now, we are ready to define the \{Monad\} instance:+\[+instance Monoid m => Monad (W m) where+ return = inject+ w >>= f = join (fmap f w)+\]+There is nothing to say about this instance. It is and standard definition valid to any monad.++What we have done here is to hide in a monad a monoid with all its operations. We have created a+machine that operates monoid values. To insert a value into the machine we need the \{tell\}+function:+\[+tell :: m -> W m ()+tell m = W m ()+\]+When we execute the machine, it returns to us the result of operate all the values we have put on it.+\[+execute :: W m a -> m+execute (W m a) = m+\]+Let's see the machine working. For example, the \{Int\} type with addition forms a \{Monoid\}.+\[+instance Monoid Int where+ mempty = 0+ mappend = (+)++example :: Int+example = execute $ do+ tell 1+ tell 2+ tell 3+ tell 4+\]+When we evaluate \{example\} we get \{10\}, as expected. Using \{mapM_\} we can rewrite \{example\}.+\[+example :: Int+example = execute $ mapM_ tell [ 1 .. 4 ]+\]+|machine.png|++##The LaTeX Monad##++Let's go back to the \{LaTeX\} type. Since \{LaTeX\} is an instance of \{Monoid\} we can construct+its correspondent \{Writer\} monad.+\[+type LaTeXW = W LaTeX+\]+The \{W\} machine is waiting now for \{LaTeX\} values.+\[+example :: LaTeX+example = execute $ do+ tell $ documentclass [] article+ tell $ author "Monads lover"+ tell $ title "LaTeX and the Writer Monad"+\]+We put all that blocks in the machine, and it returns the concatenated block. We saved a lot of+\{mappend\}'s, but we now have a lot of \{tell\}'s. No problem. Just redefine each function of+blocks with \{tell\} and \{execute\}.+\[+author' :: LaTeXW a -> LaTeXW ()+author' = tell . author . execute+\]+If it is done in a similar way with \{documentclass\} and \{title\}, every \{tell\} in \{example\}+disappears.+\[+example :: LaTeX+example = execute $ do+ documentclass' [] article+ author' "Monads lover"+ title' "LaTeX and the Writer Monad"+\]+And we can now use the \{LaTeX\} machine more comfortably. However, we have all functions duplicated.+This is why the \{LaTeXC\} class exists. We are going to talk about it later.++##Composing monads##++To add flexibility to \hatex, the writer monad explained above is defined as a monad transformer,+named \{LaTeXT\}. The way to use it is the same, there are just a few changes.++The first change is in type signatures. We need to carry an inner monad in every type.+\[+foo :: Monad m => LaTeXT m a+\]+However, in practice, we can avoid it. Say we going to use an specific monad \{M\}.+\[+type LaTeXW = LaTeXT M++foo :: LaTeXW a+\]+Now, type signatures remain unchanged.++The other change is a new feature: the \{lift\} function. With it we can do any computation+of our inner monad at any time. For example, suppose we want to output some code we have in+the file /foo.hs/. Instead of copy all its content, or read and carry it as an argument along the code,+you can simply read that file using \{lift\} wherever you want.+\[+type LaTeXIO = LaTeXT IO++readCode :: FilePath -> LaTeXIO ()+readCode fp = lift (readFileTex fp) >>= verbatim . raw++example :: LaTeXIO ()+example = do+ "This is the code I wrote this morning:"+ readCode "foo.hs"+ "It was a funny exercise."+\]+Different monads will give different features. In the case we are not interested in any of+these features, it is enough to use the Identity monad.+\[+type LaTeXW = LaTeXT Identity+\]
+ src/packages.htxg view
@@ -0,0 +1,35 @@+#Packages#++\latex, in addition to its predefined commands, has a big number of packages+that increase its power. \hatex functions for some of these packages are defined+in separated modules, one module per package. This way, you can import only those+functions you actually need. Some of these modules are below explained.++##Inputenc##++This package is of vital importance if you use non-ASCII characters in your document.+For example, if my name is /Ángela/, the /Á/ character will not appear correctly in the+output. To solve this problem, use the \{Inputenc\} module.+\[+import Text.LaTeX.Base+import Text.LaTeX.Packages.Inputenc++thePreamble :: LaTeX+thePreamble =+ documentclass [] article+ <> usepackage [utf8] inputenc+ <> author "Ángela"+ <> title "Issues with non-ASCII characters"+\]+Don't forget to set to UTF-8 encoding your Haskell source too.++##Graphicx##++With the \{Graphicx\} package you can insert images in your document and do some+other transformations. In order to insert an image use the \{includegraphics\}+function.+\[+includegraphics :: LaTeXC l => [IGOption] -> FilePath -> l+\]+The list of \{IGOption\}'s allows you to set some properties of the image, like width,+height, scaling or rotation. See the API documentation for details.
+ src/preface.htxg view
@@ -0,0 +1,33 @@+#Preface#++##Introduction##++If you are here because you want to learn more about \hatex, or just feel+curious, you are in the right place. First of all, note that this guide is addressed to that+people that already knows the basics of both Haskell and \latex. Otherwise, try to learn first+a bit of these languages (both are quite useful learnings). To learn Haskell, though I guess+you already learned it since you are reading these lines, go to the Haskell web [<http://haskell.org>]+and search for some tutorials or books. To learn \latex, you can start with+/The not so short introduction to \latex/ [<http://tobi.oetiker.ch/lshort/lshort.pdf>].++The \hatex library aspires to be the tool that Haskellers could want to make their+\latex things without exit of their language (we understand that is difficult to leave+Haskell after the first date), trying to be the most comprehensive and well done as possible.+Do you think, anyway, that something could be done better? Perhaps something is lacked? Go+then to the \hatex mailing list [<http://projects.haskell.org/cgi-bin/mailman/listinfo/hatex>]+and leave your complain without mercy! Or, in the case you are a GitHub user, say your word+in the issue list [<https://github.com/Daniel-Diaz/HaTeX/issues>] or, to be awesome,+make yourself a patch and send a pull request. This is the great thing about open source projects!++##What is HaTeX?##++Before we explain /how/ \hatex works, it is convenient to say /what/ actually \hatex is.++/\hatex is a Haskell library that provides functions to create, manipulate and parse \latex code./++People often says that /\hatex is a \latex DSL/. With it you can enjoy all the advantages+you already have in Haskell while creating \latex documents. A common purpose is to+automatize the creation of such documents, perhaps from a source data in Haskell.+A more exotic one is to render chess tables. Possibilities are in a wide range.+The idea is the following: if you can do it with \latex, you can do it with \hatex,+but adding all the Haskell features.