packages feed

lambdatex (empty) → 0.1.0.0

raw patch · 18 files changed

+1126/−0 lines, 18 filesdep +HaTeXdep +QuickCheckdep +basesetup-changed

Dependencies added: HaTeX, QuickCheck, base, containers, directory, hspec, lambdatex, mtl, text, transformers

Files

+ LICENSE view
@@ -0,0 +1,339 @@+                    GNU GENERAL PUBLIC LICENSE+                       Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++                            Preamble++  The licenses for most software are designed to take away your+freedom to share and change it.  By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users.  This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it.  (Some other Free Software Foundation software is covered by+the GNU Lesser General Public License instead.)  You can apply it to+your programs, too.++  When we speak of free software, we are referring to freedom, not+price.  Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++  To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have.  You must make sure that they, too, receive or can get the+source code.  And you must show them these terms so they know their+rights.++  We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++  Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software.  If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++  Finally, any free program is threatened constantly by software+patents.  We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary.  To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++  The precise terms and conditions for copying, distribution and+modification follow.++                    GNU GENERAL PUBLIC LICENSE+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++  0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License.  The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language.  (Hereinafter, translation is included without limitation in+the term "modification".)  Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope.  The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++  1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++  2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++    a) You must cause the modified files to carry prominent notices+    stating that you changed the files and the date of any change.++    b) You must cause any work that you distribute or publish, that in+    whole or in part contains or is derived from the Program or any+    part thereof, to be licensed as a whole at no charge to all third+    parties under the terms of this License.++    c) If the modified program normally reads commands interactively+    when run, you must cause it, when started running for such+    interactive use in the most ordinary way, to print or display an+    announcement including an appropriate copyright notice and a+    notice that there is no warranty (or else, saying that you provide+    a warranty) and that users may redistribute the program under+    these conditions, and telling the user how to view a copy of this+    License.  (Exception: if the Program itself is interactive but+    does not normally print such an announcement, your work based on+    the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole.  If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works.  But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++  3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++    a) Accompany it with the complete corresponding machine-readable+    source code, which must be distributed under the terms of Sections+    1 and 2 above on a medium customarily used for software interchange; or,++    b) Accompany it with a written offer, valid for at least three+    years, to give any third party, for a charge no more than your+    cost of physically performing source distribution, a complete+    machine-readable copy of the corresponding source code, to be+    distributed under the terms of Sections 1 and 2 above on a medium+    customarily used for software interchange; or,++    c) Accompany it with the information you received as to the offer+    to distribute corresponding source code.  (This alternative is+    allowed only for noncommercial distribution and only if you+    received the program in object code or executable form with such+    an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it.  For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable.  However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++  4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License.  Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++  5. You are not required to accept this License, since you have not+signed it.  However, nothing else grants you permission to modify or+distribute the Program or its derivative works.  These actions are+prohibited by law if you do not accept this License.  Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++  6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions.  You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++  7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all.  For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices.  Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++  8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded.  In such case, this License incorporates+the limitation as if written in the body of this License.++  9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time.  Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number.  If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation.  If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++  10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission.  For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this.  Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++                            NO WARRANTY++  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++                     END OF TERMS AND CONDITIONS++            How to Apply These Terms to Your New Programs++  If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++  To do so, attach the following notices to the program.  It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++    {description}+    Copyright (C) {year}  {fullname}++    This program is free software; you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation; either version 2 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License along+    with this program; if not, write to the Free Software Foundation, Inc.,+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++    Gnomovision version 69, Copyright (C) year name of author+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary.  Here is a sample; alter the names:++  Yoyodyne, Inc., hereby disclaims all copyright interest in the program+  `Gnomovision' (which makes passes at compilers) written by James Hacker.++  {signature of Ty Coon}, 1 April 1989+  Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs.  If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ lambdatex.cabal view
@@ -0,0 +1,65 @@+name:                lambdatex+version:             0.1.0.0+synopsis:            Type-Safe LaTeX EDSL+description:         +  ΛTeX, pronounced 'LambdaTeX' is a Haskell EDSL that adds type-safety to LaTeX.+  ΛTeX-generated LaTeX code should compile without errors.++  TODO(kerckhove) big fancy example+homepage:            http://github.com/NorfairKing/lambdatex+license:             GPL+license-file:        LICENSE+author:              Tom Sydney Kerckhove+maintainer:          syd.kerckhove@gmail.com+copyright:           2015 Tom Sydney Kerckhove+category:            Text+build-type:          Simple+-- extra-source-files:+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Text.LaTeX.LambdaTeX+                       Text.LaTeX.LambdaTeX.Error+                       Text.LaTeX.LambdaTeX.Package+                       Text.LaTeX.LambdaTeX.Package.Internal+                       Text.LaTeX.LambdaTeX.Package.Types+                       Text.LaTeX.LambdaTeX.Part+                       Text.LaTeX.LambdaTeX.Reference+                       Text.LaTeX.LambdaTeX.Reference.Internal+                       Text.LaTeX.LambdaTeX.Reference.Types+                       Text.LaTeX.LambdaTeX.Selection+                       Text.LaTeX.LambdaTeX.Selection.Internal+                       Text.LaTeX.LambdaTeX.Selection.Types+                       Text.LaTeX.LambdaTeX.Types+                       Text.LaTeX.LambdaTeX.Utils+  build-depends:       base             >= 4.6      && < 5.0+                     , HaTeX            >= 3.16     && < 3.17+                     , mtl              >= 2.2      && < 2.3+                     , text             >= 1.2      && < 1.3+                     , containers       >= 0.5      && < 0.6+                     , transformers     >= 0.4      && < 0.5+                     , directory        >= 1.2      && < 1.3+  ghc-options:        -Wall+                      -fwarn-unused-imports+                      -fwarn-incomplete-patterns+                      -fno-warn-unused-do-bind+                      -fno-warn-name-shadowing+                      -fno-warn-orphans+                      -fforce-recomp+  default-language:    Haskell2010++test-suite lambdatex-test+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       base+                     , lambdatex+                     , hspec+                     , QuickCheck+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/NorfairKing/lambdatex
+ src/Text/LaTeX/LambdaTeX.hs view
@@ -0,0 +1,127 @@+-- |+-- TODO(kerckhove) big example here!+--+{-# LANGUAGE OverloadedStrings #-}+module Text.LaTeX.LambdaTeX (+    -- * Building ΛTeX+      module Text.LaTeX.LambdaTeX++    -- ** Selections+    , module Text.LaTeX.LambdaTeX.Selection++    -- ** References+    , module Text.LaTeX.LambdaTeX.Reference++    -- ** Packages dependencies+    , module Text.LaTeX.LambdaTeX.Package++    -- ** Re-exports+    , module Text.LaTeX.LambdaTeX.Types++    ) where++import           Control.Monad.IO.Class                  (MonadIO (..))++import qualified Data.Set                                as S+import qualified Data.Text                               as T+import qualified Data.Text.IO                            as T++import           Text.LaTeX.Base                         (LaTeX, renderFile)++import           Text.LaTeX.LambdaTeX.Package+import           Text.LaTeX.LambdaTeX.Package.Internal+import           Text.LaTeX.LambdaTeX.Reference+import           Text.LaTeX.LambdaTeX.Reference.Internal+import           Text.LaTeX.LambdaTeX.Reference.Types+import           Text.LaTeX.LambdaTeX.Selection+import           Text.LaTeX.LambdaTeX.Selection.Types+import           Text.LaTeX.LambdaTeX.Types+import           Text.LaTeX.LambdaTeX.Utils++-- | Build all the files for a LaTeX project given by a ΛTeXT generator+--   This either returns Left with an error or Right () to signify success.+--+--   This function takes care of some of the LaTeX tediousness:+--+--      * LaTeX file generation+--      * Automatic bibtex file generation+--      * All safety provided by 'execLambdaTeXT' (in the form of textual errors)+--      * TODO(kerckhove) Automatic asynchronic resolution of figure dependencies on graphviz or tikz figures+buildLaTeXProject :: MonadIO m => ΛTeXT m a -> ProjectConfig -> m (Either [ΛError] ())+buildLaTeXProject func conf = do+    (errs, (latex, refs)) <- execLambdaTeXT func $ projectGenerationConfig conf++    -- Render tex file+    let mainTexFile = projectTexFileName conf ++ ".tex"+    liftIO $ renderFile mainTexFile latex++    -- Render bib file+    let mainBibFile = projectBibFileName conf ++ ".bib"+    liftIO $ removeIfExists mainBibFile+    liftIO $ T.appendFile mainBibFile $ renderReferences refs++    return $ if null errs+        then Right ()+        else Left errs++-- | Execute a ΛTeXT generation+--   This either returns a tuple of the errors and a tuple of the resulting LaTeX value and a list of external references that need to be put into a bibtex file.+--+--   This function takes care of a lot of safety issues:+--+--      * Subset selection. This allows you to build large documents in parts.+--      * External dependency selection. No more '??' for external references in the output pdf.+--      * Internal dependency safety. No more '??' for external references in the internal pdf.+--      * Package dependency resolution, TODO(kerckhove) with packages in the right order+--      * Dependency selection of figure dependencies on graphviz or tikz figures+execLambdaTeXT :: Monad m => ΛTeXT m a -> GenerationConfig -> m ([ΛError], (LaTeX, [Reference]))+execLambdaTeXT func conf = do+    ((_,latex), _, output) <- runΛTeX func (ΛConfig $ generationSelection conf) initState+    let result = injectPackageDependencies (S.toList $ outputPackageDependencies output) latex+    let refs = S.toList $ outputExternalReferences output++    -- Check reference errors+    let made = outputLabelsMade output+        needed = outputLabelsNeeded output+        diff = S.difference needed made++    let referss = map ReferenceMissing $ S.toList diff++    return (referss, (result, refs))++  where+    initState :: ΛState+    initState = ΛState { stateCurrentPart = emptyPart }+++-- * Configuration++-- | Configuration of a ΛTeX project+data ProjectConfig = ProjectConfig {+      projectGenerationConfig :: GenerationConfig+    , projectBibFileName      :: String+    , projectTexFileName      :: String+    }++-- | Default project configuration.+--+--  Modify this instead of building your own 'ProjectConfig'+defaultProjectConfig :: ProjectConfig+defaultProjectConfig = ProjectConfig {+      projectGenerationConfig = defaultGenerationConfig+    , projectBibFileName = "main"+    , projectTexFileName = "main"+    }++-- | Configuration of ΛTeX generation+data GenerationConfig = GenerationConfig {+      generationSelection :: Selection+    }++-- | Default generation config.+--+--  Modify this instead of building your own 'GenerationConfig'+defaultGenerationConfig :: GenerationConfig+defaultGenerationConfig = GenerationConfig {+      generationSelection = [All]+    }
+ src/Text/LaTeX/LambdaTeX/Error.hs view
@@ -0,0 +1,6 @@+module Text.LaTeX.LambdaTeX.Error where++import           Data.Text (Text)++data ΛError = ReferenceMissing Text+    deriving (Show, Eq)
+ src/Text/LaTeX/LambdaTeX/Package.hs view
@@ -0,0 +1,21 @@+-- | This module allows you to automatically resolve LaTeX package dependencies in your document.+--+-- Note: If you want different arguments to a package, you have to specify this by making a 'manual' 'packageDep' declaration before your document.+module Text.LaTeX.LambdaTeX.Package where++import           Text.LaTeX.Base.Syntax++import qualified Data.Set                           as S++import           Text.LaTeX.LambdaTeX.Package.Types+import           Text.LaTeX.LambdaTeX.Types++-- | Declare a dependency to a package, with given arguments+packageDep :: Monad m => [LaTeX] -- ^ Arguments+                      -> Text -- ^ Name of the LaTeX package+                      -> ΛTeXT m ()+packageDep args name = λtell $ mempty { outputPackageDependencies = S.singleton (PackageDep name args) }++-- | Declare a dependency to a package without any arguments+packageDep_ :: Monad m => Text -> ΛTeXT m ()+packageDep_ name = packageDep [] name
+ src/Text/LaTeX/LambdaTeX/Package/Internal.hs view
@@ -0,0 +1,27 @@+module Text.LaTeX.LambdaTeX.Package.Internal where++import           Text.LaTeX.Base.Syntax++import           Text.LaTeX.LambdaTeX.Package.Types+import           Text.LaTeX.LambdaTeX.Types++-- | Inject package dependencies into a given LaTeX document.+--   This is done by top-level functions in @Text.LaTeX.LambdaTeX@ automatically+injectPackageDependencies :: [PackageDep] -> LaTeX -> LaTeX+injectPackageDependencies ps = go+    -- We're looking for this: TeXComm "documentclass" ...+  where+    -- We have to go looking through the LaTeX :(+    go t@(TeXComm "documentclass" _) = TeXSeq t packages+    go (TeXSeq t1 t2) = TeXSeq (go t1) (go t2)+    go c = c++    packages :: LaTeX+    packages = mconcat $ map (\(PackageDep name args) -> usepackage args name) ps+++-- | Redefinition of @usepackage@ to use Text+--   Don't use this directly, use the packageDep instead!+usepackage :: [LaTeX] -> Text -> LaTeX+usepackage ls pn = TeXComm "usepackage" [MOptArg ls, FixArg $ TeXRaw pn]+
+ src/Text/LaTeX/LambdaTeX/Package/Types.hs view
@@ -0,0 +1,14 @@+module Text.LaTeX.LambdaTeX.Package.Types where++import           Data.Ord               (comparing)+import           Data.Text              (Text)++import           Text.LaTeX.Base.Syntax (LaTeX)++data PackageDep = PackageDep {+      packageDepName    :: Text+    , packageDepOptions :: [LaTeX]+  } deriving (Show, Eq)++instance Ord PackageDep where+    compare = comparing packageDepName
+ src/Text/LaTeX/LambdaTeX/Part.hs view
@@ -0,0 +1,15 @@+module Text.LaTeX.LambdaTeX.Part where++import           Data.Text (Text)++newtype Part = Part { unPart :: [Text] }++emptyPart :: Part+emptyPart = Part { unPart = [] }++pushPart :: Part -> Text -> Part+pushPart p t = Part { unPart = unPart p ++ [t] }++popPart :: Part -> Part+popPart p = Part { unPart = init $ unPart p }+
+ src/Text/LaTeX/LambdaTeX/Reference.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.LaTeX.LambdaTeX.Reference where++import           Text.LaTeX.Base.Class+import           Text.LaTeX.Base.Syntax++import qualified Text.LaTeX.Base.Commands                as H (label, pageref,+                                                               ref)++import           Text.LaTeX.LambdaTeX.Reference.Internal+import           Text.LaTeX.LambdaTeX.Reference.Types+import           Text.LaTeX.LambdaTeX.Types++-- * Internal references+-- An internal references point is defined by a label+-- It is then referenced with @ref label@+--+-- ΛTeX automatically ensures that those references are always internally consistent+-- BUT you have to make sure that you use these functions instead of the regular ones.++-- ** Labels++-- | Label a part+label :: Monad m => Text -> ΛTeXT m ()+label l = do+    fromLaTeX $ H.label $ TeXRaw l+    addLabelMade l++-- | The safe version of LaTeX's @ref@+ref :: Monad m => Text -> ΛTeXT m ()+ref l = do+    fromLaTeX $ H.ref $ TeXRaw l+    addLabelNeeded l++-- | The safe version of LaTeX's @pageref@+pageref :: Monad m => Text -> ΛTeXT m ()+pageref l = do+    fromLaTeX $ H.pageref $ TeXRaw l+    addLabelNeeded l++-- * External references+-- ** Defining references++-- TODO(kerckhove) Check for duplicate fields?++-- | Define an external reference.+--   Use 'cite' or 'nocite' to use this in your document.+makeReference :: ReferenceType -> Text -> [(Text, Text)] -> Reference+makeReference = Reference++-- ** Using references++-- | Refer to an external reference.+cite :: Monad m => Reference -> ΛTeXT m ()+cite ref = do+  fromLaTeX $ comm1 "cite" $ TeXRaw $ referenceName ref+  addReference ref++-- | Put an external reference in your list of references without using it.+nocite :: Monad m => Reference -> ΛTeXT m ()+nocite ref = do+  fromLaTeX $ comm1 "nocite" $ TeXRaw $ referenceName ref+  addReference ref++-- ** Reference Types+--+-- See [The Wiki article on which fields each of them requires](https://en.wikibooks.org/wiki/LaTeX/Bibliography_Management)+--+-- TODO(kerckhove) Generate these!+unpublished :: ReferenceType+unpublished = "unpublished"++lectureSlides :: ReferenceType+lectureSlides = "unpublished"++online :: ReferenceType+online = "online"++article :: ReferenceType+article = "article"+
+ src/Text/LaTeX/LambdaTeX/Reference/Internal.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.LaTeX.LambdaTeX.Reference.Internal where++import qualified Data.Set                             as S+import qualified Data.Text                            as T++import           Text.LaTeX.LambdaTeX.Reference.Types+import           Text.LaTeX.LambdaTeX.Types++-- * Internal references++-- | Declare that a label has been made+addLabelMade ::  Monad m => Text -> ΛTeXT m ()+addLabelMade label = λtell $ mempty { outputLabelsMade = S.singleton label }++-- | Declare that a label is needed+addLabelNeeded ::  Monad m => Text -> ΛTeXT m ()+addLabelNeeded label = λtell $ mempty { outputLabelsNeeded = S.singleton label }++-- * External references++-- | Render references to bib(La)TeX format+renderReferences :: [Reference] -> Text+renderReferences rs = (`mappend` "\n\n") . T.intercalate ",\n\n" $ map showRef rs+  where+    showRef :: Reference -> Text+    showRef r = mconcat+        [+          "@"+        , referenceType r+        , "{"+        , referenceName r+        , ",\n"+        , T.intercalate ",\n" (map showField $ referenceFields r)+        , "\n}"+        ]++    showField :: (Text, Text) -> Text+    showField (a, b) = mconcat ["  ", a, " = {", b, "}"]++-- | Add a reference to a ΛTeX generator+addReference :: Monad m => Reference -> ΛTeXT m ()+addReference ref = λtell $ mempty { outputExternalReferences = S.singleton ref }
+ src/Text/LaTeX/LambdaTeX/Reference/Types.hs view
@@ -0,0 +1,16 @@+module Text.LaTeX.LambdaTeX.Reference.Types where++import           Data.Ord  (comparing)+import           Data.Text (Text)++type ReferenceType = Text+data Reference = Reference {+      referenceType   :: ReferenceType+    , referenceName   :: Text+    , referenceFields :: [(Text, Text)]+  } deriving (Show, Eq)++instance Ord Reference where+    compare = comparing referenceName++
+ src/Text/LaTeX/LambdaTeX/Selection.hs view
@@ -0,0 +1,46 @@+module Text.LaTeX.LambdaTeX.Selection where++import           Control.Monad                           (when)++import qualified Data.Text                               as T++import           Text.LaTeX.LambdaTeX.Selection.Internal+import           Text.LaTeX.LambdaTeX.Selection.Types+import           Text.LaTeX.LambdaTeX.Types++-- * Making selections++-- | Construct a selection from a space-separated list of strings representing selectors+--+-- > constructSelection = map constructSelector . words+constructSelection :: String -> Selection+constructSelection = map constructSelector . words++-- | Construct a selector from a string+--+-- >>> constructSelector "all"+-- > All+--+-- >>> constructSelector "mySection.mySubsection"+-- > Match ["mySection", "mySubsection"]+--+-- >>> constructSelector "+mySection.mySubsection"+-- > Match ["mySection", "mySubsection"]+--+-- >>> constructSelector "-mySection.mySubsection"+-- > Ignore ["mySection", "mySubsection"]+constructSelector :: String -> Selector+constructSelector "all" = All+constructSelector ('+':s) = Match $ map T.pack $ split s+constructSelector ('-':s) = Ignore $ map T.pack $ split s+constructSelector s = Match $ map T.pack $ split s++-- * Using selections++-- | Declare a sub-part of the document with a name.+--   This allows you to use the subset-selection feature later.+note :: Monad m => Text -> ΛTeXT m () -> ΛTeXT m ()+note partname func = inPart partname $ do+    s <- isSelected+    when s func+
+ src/Text/LaTeX/LambdaTeX/Selection/Internal.hs view
@@ -0,0 +1,82 @@+module Text.LaTeX.LambdaTeX.Selection.Internal where++import           Data.List                            (isPrefixOf)++import           Text.LaTeX.LambdaTeX.Selection.Types+import           Text.LaTeX.LambdaTeX.Types++-- | Whether a part is selected by a given list of selectors.+--+-- A part is selected if:+--+-- All parts are selected or+-- It it is matched and not ignored.+selects :: Part -> [Selector] -> Bool+selects (Part ps) ss = go ps ss False+    where+        go :: [Text] -> [Selector] -> Bool -> Bool+        go _ [] b                       = b+        go ps (All:ss) _                = go ps ss True+        go ps ((Match s):ss) b          = if ps `matches` s+                                          then go ps ss True+                                          else go ps ss b+        go ps ((Ignore s):ss) True      = if ps `matches` s+                                          then go ps ss False+                                          else go ps ss True+        go ps ((Ignore _):ss) False     = go ps ss False++-- | Whether the current part is selected to be generated+isSelected :: Monad m => ΛTeXT m Bool+isSelected = do+    part <- currentPart+    sels <- λasks configSelection+    return $ selects part sels++-- * Current part Helpers++-- | Returns the current part from the ΛTeX state+currentPart :: Monad m => ΛTeXT m Part+currentPart = λgets stateCurrentPart++-- | Execute the following function with a given sub-part name+inPart :: Monad m => Text -> ΛTeXT m () -> ΛTeXT m ()+inPart partname func = do+    pushCurrentPart partname+    func+    popCurrentPart++-- | Push a new part name onto the current part stack+--+-- WARNING: This should never be used outside of 'inPart'+pushCurrentPart :: Monad m => Text -> ΛTeXT m ()+pushCurrentPart partname = λmodify (\s -> s { stateCurrentPart = pushPart (stateCurrentPart s) partname})++-- | Pop a part name off the current part stack+--+-- WARNING: This should never be used outside of 'inPart'+popCurrentPart :: Monad m => ΛTeXT m ()+popCurrentPart = λmodify (\s -> s { stateCurrentPart = popPart $ stateCurrentPart s })+++-- * Text Helpers++-- | Split a string on a dot.+-- This can be useful to convert from a 'Selector's textual representation back to a selector+--+-- > split = splitOn '.'+split :: String -> [String]+split = splitOn '.'++-- | Split a string on a specific character+splitOn :: Char -> String -> [String]+splitOn c s = go s []+  where+    go :: String -> String -> [String]+    go [] s = [s]+    go (sc:ss) acc | sc == c   = acc : go [] ss+                   | otherwise = go ss (acc ++ [sc])+++-- | Tests whether a given part matches a given selector's part specification+matches :: [Text] -> [Text] -> Bool+matches = flip isPrefixOf
+ src/Text/LaTeX/LambdaTeX/Selection/Types.hs view
@@ -0,0 +1,10 @@+module Text.LaTeX.LambdaTeX.Selection.Types where++import           Data.Text (Text)++type Selection = [Selector]+data Selector = All+              | Match [Text]+              | Ignore [Text]+    deriving (Show, Eq)+
+ src/Text/LaTeX/LambdaTeX/Types.hs view
@@ -0,0 +1,209 @@+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE UndecidableInstances       #-}++module Text.LaTeX.LambdaTeX.Types (+      module Text.LaTeX.LambdaTeX.Types+    , module Text.LaTeX.LambdaTeX.Part+    , module Text.LaTeX.LambdaTeX.Error+    , module Text.LaTeX.LambdaTeX.Package.Types+    , module Text.LaTeX.LambdaTeX.Reference.Types+    , module Text.LaTeX.LambdaTeX.Selection.Types++#if !MIN_VERSION_base(4,8,0)+    , module Control.Applicative+    , module Data.Monoid+#endif+    , Text+    ) where++#if !MIN_VERSION_base(4,8,0)+import           Control.Applicative+import           Data.Monoid                          hiding (All)+#endif++import           Control.Monad                        (liftM)+import           Control.Monad.IO.Class               (MonadIO, liftIO)+import           Control.Monad.Reader                 (MonadReader (..), asks)+import           Control.Monad.RWS                    (RWST (..))+import           Control.Monad.State                  (MonadState (..), gets,+                                                       modify)+import           Control.Monad.Trans                  (MonadTrans (..), lift)+import           Control.Monad.Writer                 (MonadWriter (..))++import           Data.Set                             (Set)+import qualified Data.Set                             as S+import           Data.String                          (IsString (..))+import           Data.Text                            (Text)++import           Text.LaTeX.Base                      (LaTeX, LaTeXT, runLaTeXT)+import           Text.LaTeX.Base.Class                (LaTeXC (..), fromLaTeX)+import           Text.LaTeX.Base.Writer               (extractLaTeX, textell)++import           Text.LaTeX.Packages.AMSMath          ()++import           Text.LaTeX.LambdaTeX.Error+import           Text.LaTeX.LambdaTeX.Package.Types+import           Text.LaTeX.LambdaTeX.Part+import           Text.LaTeX.LambdaTeX.Reference.Types+import           Text.LaTeX.LambdaTeX.Selection.Types++-- * The ΛTeX Monad+type LambdaTeXT = ΛTeXT+type LambdaTeXT_ m = ΛTeXT_ m++type ΛTeXT_ m = ΛTeXT m ()++newtype ΛTeXT m a =+    ΛTeXT { unwrapΛTeXT :: LaTeXT (RWST ΛConfig ΛOutput ΛState m) a }+    deriving (Functor, Applicative, Monad)++-- TODO(kerckhove) Move and add amsmath dependency+instance (Monad m, a ~ ()) => Num (ΛTeXT m a) where+    (+) a b = ΛTeXT $ unwrapΛTeXT a + unwrapΛTeXT b+    (-) a b = ΛTeXT $ unwrapΛTeXT a - unwrapΛTeXT b+    (*) a b = ΛTeXT $ unwrapΛTeXT a * unwrapΛTeXT b+    negate = ΛTeXT . negate . unwrapΛTeXT+    fromInteger = fromLaTeX . fromInteger+    abs = ΛTeXT . abs . unwrapΛTeXT+    -- Non-defined methods+    signum = ΛTeXT . signum . unwrapΛTeXT+++-- TODO(kerckhove) Move and add amsmath dependency+instance (Monad m, a ~ ()) => Fractional (ΛTeXT m a) where+    (/) a b = ΛTeXT $ unwrapΛTeXT a / unwrapΛTeXT b+    fromRational = fromLaTeX . fromRational++-- TODO(kerckhove) Also instantiate floating?++runΛTeX :: Monad m => ΛTeXT m a -> ΛConfig -> ΛState -> m ((a, LaTeX), ΛState, ΛOutput)+runΛTeX func conf state = runRWST (runLaTeXT $ unwrapΛTeXT func) conf state++instance MonadTrans ΛTeXT where+    lift = ΛTeXT . lift . lift++instance MonadIO m => MonadIO (ΛTeXT m) where+    liftIO = lift . liftIO++instance (Monad m, a ~ ()) => LaTeXC (ΛTeXT m a) where+    liftListL f xs = mapM extractΛLaTeX_ xs >>= λtextell . f++instance (Monad m, a ~ ()) => IsString (ΛTeXT m a) where+    fromString = λtextell . fromString++instance (Monad m, a ~ ()) => Monoid (ΛTeXT m a) where+    mempty = return ()+    mappend = (>>)++λtextell :: Monad m => LaTeX -> ΛTeXT m ()+λtextell = ΛTeXT . textell++λtell :: Monad m => ΛOutput -> ΛTeXT m ()+λtell = ΛTeXT . tell++λask :: Monad m => ΛTeXT m ΛConfig+λask = λasks id++λasks :: Monad m => (ΛConfig -> a) -> ΛTeXT m a+λasks = ΛTeXT . asks++λget :: Monad m => ΛTeXT m ΛState+λget = λgets id++λgets :: Monad m => (ΛState -> a) -> ΛTeXT m a+λgets = ΛTeXT . gets++λmodify :: Monad m => (ΛState -> ΛState) -> ΛTeXT m ()+λmodify = ΛTeXT . modify++-- | This function run a 'LaTeXT' computation,+-- lifting the result again in the monad.+extractΛLaTeX :: Monad m => ΛTeXT m a -> ΛTeXT m (a,LaTeX)+extractΛLaTeX = ΛTeXT . extractLaTeX . unwrapΛTeXT++-- | Like 'extractΛLaTeX' but without the result+extractΛLaTeX_ :: Monad m => ΛTeXT m a -> ΛTeXT m LaTeX+extractΛLaTeX_ = liftM snd . extractΛLaTeX++-- | Internal ΛTeXT configration+data ΛConfig    = ΛConfig {+      configSelection :: Selection+    }++-- | Internal ΛTeXT configration output+data ΛOutput    = ΛOutput {+      outputPackageDependencies :: Set PackageDep+    , outputExternalReferences  :: Set Reference+    , outputLabelsMade          :: Set Text+    , outputLabelsNeeded        :: Set Text+    }++instance Monoid ΛOutput where+    mempty = ΛOutput {+            outputPackageDependencies   = S.empty+          , outputExternalReferences    = S.empty+          , outputLabelsMade = S.empty+          , outputLabelsNeeded = S.empty+        }++    mappend o1 o2 = ΛOutput {+            outputPackageDependencies =+                S.union+                    (outputPackageDependencies o1)+                    (outputPackageDependencies o2)+          , outputExternalReferences =+                S.union+                    (outputExternalReferences o1)+                    (outputExternalReferences o2)+          , outputLabelsMade =+                S.union+                    (outputLabelsMade o1)+                    (outputLabelsMade o2)+          , outputLabelsNeeded =+                S.union+                    (outputLabelsNeeded o1)+                    (outputLabelsNeeded o2)+        }++-- | Internal ΛTeXT configration state+data ΛState = ΛState {+      stateCurrentPart :: Part+    }++-- Orphan Monad Transformer instances for LaTeXT+instance MonadReader r m => MonadReader r (LaTeXT m) where+    ask   = lift ask+    local = local+    reader = lift . reader++instance MonadState s m => MonadState s (LaTeXT m) where+    get = lift get+    put = lift . put+    state = lift . state++instance MonadWriter w m => MonadWriter w (LaTeXT m) where+    tell = lift . tell+    listen = listen+    pass = pass+++-- Monad Transformer instances for ΛTeXT+instance MonadReader r m => MonadReader r (ΛTeXT m) where+    ask   = lift ask+    local = local+    reader = lift . reader++instance MonadState s m => MonadState s (ΛTeXT m) where+    get = lift get+    put = lift . put+    state = lift . state++instance MonadWriter w m => MonadWriter w (ΛTeXT m) where+    tell = lift . tell+    listen = listen+    pass = pass+
+ src/Text/LaTeX/LambdaTeX/Utils.hs view
@@ -0,0 +1,14 @@+-- | ΛTeX utilities+module Text.LaTeX.LambdaTeX.Utils where++import           Control.Exception+import           System.Directory  (removeFile)+import           System.IO.Error   (isDoesNotExistError)++-- | Remove the given file if it exists+removeIfExists :: FilePath -> IO ()+removeIfExists fileName = removeFile fileName `catch` handleExists+  where handleExists e+          | isDoesNotExistError e = return ()+          | otherwise = throwIO e+
+ test/Spec.hs view
@@ -0,0 +1,9 @@+import           Control.Exception (evaluate)+import           Test.Hspec+import           Test.QuickCheck++main :: IO ()+main = hspec $ do+    describe "unfinished test suite" $ do+        it "is not finished yet, so here's a dummy test" $ do+            True