citeproc-hs-0.2: src/Text/CSL/Style.hs
{-# OPTIONS_GHC -fglasgow-exts #-} -- for deriving Typeable
{-# LANGUAGE PatternGuards #-}
-----------------------------------------------------------------------------
-- |
-- Module : Text.CSL.Style
-- Copyright : (c) Andrea Rossato
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Andrea Rossato <andrea.rossato@unitn.it>
-- Stability : unstable
-- Portability : unportable
--
-- The Style types
--
-----------------------------------------------------------------------------
module Text.CSL.Style where
import Data.Generics
-- | The representation of a parsed CSL style.
data Style
= Style
{ styleClass :: String
, styleInfo :: Maybe CSInfo
, styleLang :: String
, styleLocale :: String
, csTerms :: [TermMap]
, csMacros :: [MacroMap]
, citation :: Citation
, biblio :: Maybe Bibliography
} deriving ( Show, Typeable, Data )
type TermMap
= ((String,Form),(String,String))
type MacroMap
= (String,[Element])
data Citation
= Citation
{ citOptions :: [Option]
, citSort :: [Sort]
, citLayout :: Layout
} deriving ( Show, Typeable, Data )
data Bibliography
= Bibliography
{ bibOptions :: [Option]
, bibSort :: [Sort]
, bibLayout :: Layout
} deriving ( Show, Typeable, Data )
type Option = (String,String)
data Layout
= Layout
{ layFormat :: Formatting
, layDelim :: Delimiter
, elements :: [Element]
} deriving ( Show, Typeable, Data )
data Element
= Choose IfThen [IfThen] [Element]
| Macro String Form Formatting
| Const String Formatting
| PointLocator String Form Formatting
| Variable [String] Form Formatting Delimiter
| Term String Form Formatting Bool Bool
| Label String Form Formatting Bool Bool
| Number String NumericForm Formatting
| ShortNames [String] Formatting Delimiter
| Names [String] [Name] Formatting Delimiter [Element]
| Substitute [Element]
| Group Formatting Delimiter String [Element]
| Date [String] Formatting Delimiter [DatePart]
deriving ( Show, Eq, Typeable, Data )
data IfThen
= IfThen Condition Match [Element]
deriving ( Eq, Show, Typeable, Data )
data Condition
= Condition
{ isType :: [String]
, isSet :: [String]
, isNumeric :: [String]
, isDate :: [String]
, isPosition :: [String]
, disambiguation :: [String]
, isLocator :: [String]
}
deriving ( Eq, Show, Typeable, Data )
type Delimiter
= String
data Match
= Any
| All
| None
deriving ( Show, Read, Eq, Typeable, Data )
match :: Match -> [Bool] -> Bool
match All = and
match Any = or
match None = and . map not
data DatePart
= DatePart String String Formatting
deriving ( Show, Eq, Typeable, Data )
defaultDate :: [DatePart]
defaultDate
= [ DatePart "year" "" emptyFormatting
, DatePart "month" "" emptyFormatting
, DatePart "day" "" emptyFormatting]
data Sort
= SortVariable String Sorting
| SortMacro String Sorting
deriving ( Eq, Show, Typeable, Data )
data Sorting
= Ascending String
| Descending String
deriving ( Eq, Read, Typeable, Data )
instance Show Sorting where
show (Ascending s) = s
show (Descending s) = s
instance Ord Sorting where
compare (Ascending a) (Ascending b) = compare a b
compare (Descending a) (Descending b) = compare b a
compare _ _ = EQ
data Form
= Long
| Verb
| Short
| VerbShort
| Symbol
deriving ( Eq, Show, Read, Typeable, Data )
data NumericForm
= Numeric
| Ordinal
| Roman
deriving ( Eq, Show, Read, Typeable, Data )
data Name
= Name Form Formatting NameFormatting Delimiter
| NameLabel Form Formatting Bool Bool
deriving ( Eq, Show, Typeable, Data )
isName :: Name -> Bool
isName x = case x of Name {} -> True; _ -> False
data NameFormatting
= NameFormatting
{ andConnector :: String
, delimiterPrecedesLast :: String
, nameAsSortOrder :: String
, sortSeparator :: String
, initializeWith :: String
} deriving ( Eq, Show, Typeable, Data )
defaultNameFormatting :: NameFormatting
defaultNameFormatting
= NameFormatting
{ andConnector = "text"
, delimiterPrecedesLast = ""
, nameAsSortOrder = ""
, sortSeparator = ""
, initializeWith = ""
}
data Formatting
= Formatting
{ prefix :: String
, suffix :: String
, fontFamily :: String
, fontStyle :: String
, fontVariant :: String
, fontWeight :: String
, textDecoration :: String
, verticalAlign :: String
, textCase :: String
, display :: String
, quotes :: Bool
} deriving ( Eq, Ord, Read, Show, Typeable, Data )
emptyFormatting :: Formatting
emptyFormatting
= Formatting [] [] [] [] [] [] [] [] [] [] False
data CSInfo
= CSInfo
{ csiTitle :: String
, csiAuthor :: CSAuthor
, csiCategories :: [CSCategory]
, csiId :: String
, csiUpdated :: String
} deriving ( Show, Read, Typeable, Data )
data CSAuthor = CSAuthor String String String deriving ( Show, Read, Eq, Typeable, Data )
data CSCategory = CSCategory String String String deriving ( Show, Read, Eq, Typeable, Data )
-- | The formatted output, produced after post-processing the
-- evaluated citations.
data FormattedOutput
= FO String Formatting [FormattedOutput]
| Delimiter String
deriving ( Eq, Show )
-- | The 'Output' generated by the evaluation of a style. Must be
-- further processed for disambiguation and collapsing.
data Output
= OStr String Formatting -- ^ A simple 'String'
| OName String [String] Formatting -- ^ A (family) name with the list of given names.
| OYear String String Formatting -- ^ The year and a suffix if needed
| OCitNum Int Formatting -- ^ The citation number
| Output [Output] Formatting -- ^ Some nested 'Output'
| OContrib String [Output] [[Output]] -- ^ The citation key with the contributor(s), and everything
-- used for disambiguation.
| ODel String -- ^ A delimiter string.
deriving ( Eq, Ord, Show, Typeable, Data )
-- | A citation group: a list of evaluated citations, the 'Formatting'
-- to be applied to them, and the 'Delimiter' between individual
-- citations.
data CitationGroup = CG Formatting String [Output] deriving ( Show, Eq, Typeable, Data )
data BiblioData
= BD
{ citations :: [[FormattedOutput]]
, bibliography :: [[FormattedOutput]]
} deriving ( Show )
-- | A record with all the data to produce the 'FormattedOutput' of a
-- citation: the citation key, the part of the citation that may be
-- colliding with other citations (the list of contributors for the
-- same year), the data to disambiguate it (all possible contributors
-- and all possible given names), and the disambiguated citation and
-- its year.
data CiteData
= CD
{ key :: String
, collision :: [Output]
, disambData :: [[Output]]
, disambed :: [Output]
, citYear :: String
} deriving ( Show, Typeable, Data )
instance Eq CiteData where
(==) (CD ka ca _ _ _)
(CD kb cb _ _ _) = ka == kb && ca == cb
-- | Convert evaluated 'Output' into 'FormattedOutput', ready for the
-- output filters.
formatOutput :: Output -> FormattedOutput
formatOutput o
| ODel s <- o = Delimiter s
| OStr s f <- o = FO s f []
| OName s _ f <- o = FO s f []
| OYear s _ f <- o = FO s f []
| Output os f <- o = FO "" f (format os)
| OContrib _ s _ <- o = FO "" emptyFormatting (format s)
| OCitNum i f <- o = FO (show i) f []
| otherwise = FO "" emptyFormatting []
where
format = map formatOutput
-- | Map the evaluated output of a citation group.
mapGroupOutput :: (Output -> [a]) -> CitationGroup -> [a]
mapGroupOutput f (CG _ _ os) = concatMap f os
-- | A generic processing function.
proc :: (Typeable a, Data b) => (a -> a) -> b -> b
proc f = everywhere (mkT f)
-- | A generic query function.
query :: (Typeable a, Data b) => (a -> [c]) -> b -> [c]
query f = everything (++) ([] `mkQ` f)
-- | Removes all given names form a 'OName' element with 'proc'.
rmGivenNames :: Output -> Output
rmGivenNames o
| OName s _ f <- o = OName s [] f
| otherwise = o
-- | Removes all contributors' names.
rmContribs :: Output -> Output
rmContribs o
| OContrib s _ _ <- o = OContrib s [] []
| otherwise = o
-- | Add, with 'proc', a give name to the family name. Needed for
-- disambiguation.
addGivenNames :: [Output] -> [Output]
addGivenNames
= reverse . addGN True . reverse
where
addGN _ [] = []
addGN b (o:os)
| OName _ xs f <- o
, xs /= [] = if b then OName (head xs) (tail xs) f : addGN False os else o:os
| otherwise = o : addGN b os
-- | Add the year suffix to the year. Needed for disambiguation.
addYearSuffix :: Output -> Output
addYearSuffix o
| OYear y s f <- o = OYear (y ++ s) s f
| otherwise = o