diff options
| author | Igor Pashev <pashev.igor@gmail.com> | 2021-07-17 18:10:34 +0200 | 
|---|---|---|
| committer | Igor Pashev <pashev.igor@gmail.com> | 2021-07-17 18:46:16 +0200 | 
| commit | 48459559a13a20083fc9b31eb523b8ea2bf0a63f (patch) | |
| tree | 1c04e75709457403110a6f8c5c90099f22369de3 /src/Text/Pandoc/Writers/LaTeX/Citation.hs | |
| parent | 0c39509d9b6a58958228cebf5d643598e5c98950 (diff) | |
| parent | 46099e79defe662e541b12548200caf29063c1c6 (diff) | |
| download | pandoc-48459559a13a20083fc9b31eb523b8ea2bf0a63f.tar.gz | |
Merge branch 'master' of https://github.com/jgm/pandoc
Diffstat (limited to 'src/Text/Pandoc/Writers/LaTeX/Citation.hs')
| -rw-r--r-- | src/Text/Pandoc/Writers/LaTeX/Citation.hs | 181 | 
1 files changed, 181 insertions, 0 deletions
| diff --git a/src/Text/Pandoc/Writers/LaTeX/Citation.hs b/src/Text/Pandoc/Writers/LaTeX/Citation.hs new file mode 100644 index 000000000..f48a43d7a --- /dev/null +++ b/src/Text/Pandoc/Writers/LaTeX/Citation.hs @@ -0,0 +1,181 @@ +{-# LANGUAGE OverloadedStrings #-} +{- | +   Module      : Text.Pandoc.Writers.LaTeX.Citation +   Copyright   : Copyright (C) 2006-2021 John MacFarlane +   License     : GNU GPL, version 2 or above + +   Maintainer  : John MacFarlane <jgm@berkeley.edu> +   Stability   : alpha +   Portability : portable +-} +module Text.Pandoc.Writers.LaTeX.Citation +  ( citationsToNatbib, +    citationsToBiblatex +  ) where + +import Data.Text (Text) +import Data.Char (isPunctuation) +import qualified Data.Text as T +import Text.Pandoc.Class.PandocMonad (PandocMonad) +import Text.Pandoc.Definition +import Data.List (foldl') +import Text.DocLayout (Doc, brackets, empty, (<+>), text, isEmpty, literal, +                       braces) +import Text.Pandoc.Walk +import Text.Pandoc.Writers.LaTeX.Types ( LW ) + +citationsToNatbib :: PandocMonad m +                  => ([Inline] -> LW m (Doc Text)) +                  -> [Citation] +                  -> LW m (Doc Text) +citationsToNatbib inlineListToLaTeX [one] +  = citeCommand inlineListToLaTeX c p s k +  where +    Citation { citationId = k +             , citationPrefix = p +             , citationSuffix = s +             , citationMode = m +             } +      = one +    c = case m of +             AuthorInText   -> "citet" +             SuppressAuthor -> "citeyearpar" +             NormalCitation -> "citep" + +citationsToNatbib inlineListToLaTeX cits +  | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits +  = citeCommand inlineListToLaTeX "citep" p s ks +  where +     noPrefix  = all (null . citationPrefix) +     noSuffix  = all (null . citationSuffix) +     ismode m  = all ((==) m  . citationMode) +     p         = citationPrefix  $ +                 head cits +     s         = citationSuffix  $ +                 last cits +     ks        = T.intercalate ", " $ map citationId cits + +citationsToNatbib inlineListToLaTeX (c:cs) +  | citationMode c == AuthorInText = do +     author <- citeCommand inlineListToLaTeX "citeauthor" [] [] (citationId c) +     cits   <- citationsToNatbib inlineListToLaTeX +                  (c { citationMode = SuppressAuthor } : cs) +     return $ author <+> cits + +citationsToNatbib inlineListToLaTeX cits = do +  cits' <- mapM convertOne cits +  return $ text "\\citetext{" <> foldl' combineTwo empty cits' <> text "}" +  where +    citeCommand' = citeCommand inlineListToLaTeX +    combineTwo a b | isEmpty a = b +                   | otherwise = a <> text "; " <> b +    convertOne Citation { citationId = k +                        , citationPrefix = p +                        , citationSuffix = s +                        , citationMode = m +                        } +        = case m of +               AuthorInText   -> citeCommand' "citealt"  p s k +               SuppressAuthor -> citeCommand' "citeyear" p s k +               NormalCitation -> citeCommand' "citealp"  p s k + +citeCommand :: PandocMonad m +            => ([Inline] -> LW m (Doc Text)) +            -> Text +            -> [Inline] +            -> [Inline] +            -> Text +            -> LW m (Doc Text) +citeCommand inlineListToLaTeX c p s k = do +  args <- citeArguments inlineListToLaTeX p s k +  return $ literal ("\\" <> c) <> args + +type Prefix = [Inline] +type Suffix = [Inline] +type CiteId = Text +data CiteGroup = CiteGroup Prefix Suffix [CiteId] + +citeArgumentsList :: PandocMonad m +              => ([Inline] -> LW m (Doc Text)) +              -> CiteGroup +              -> LW m (Doc Text) +citeArgumentsList _inlineListToLaTeX (CiteGroup _ _ []) = return empty +citeArgumentsList inlineListToLaTeX (CiteGroup pfxs sfxs ids) = do +      pdoc <- inlineListToLaTeX pfxs +      sdoc <- inlineListToLaTeX sfxs' +      return $ optargs pdoc sdoc <> +              braces (literal (T.intercalate "," (reverse ids))) +      where sfxs' = stripLocatorBraces $ case sfxs of +                (Str t : r) -> case T.uncons t of +                  Just (x, xs) +                    | T.null xs +                    , isPunctuation x -> dropWhile (== Space) r +                    | isPunctuation x -> Str xs : r +                  _ -> sfxs +                _   -> sfxs +            optargs pdoc sdoc = case (isEmpty pdoc, isEmpty sdoc) of +                 (True, True ) -> empty +                 (True, False) -> brackets sdoc +                 (_   , _    ) -> brackets pdoc <> brackets sdoc + +citeArguments :: PandocMonad m +              => ([Inline] -> LW m (Doc Text)) +              -> [Inline] +              -> [Inline] +              -> Text +              -> LW m (Doc Text) +citeArguments inlineListToLaTeX p s k = +  citeArgumentsList inlineListToLaTeX (CiteGroup p s [k]) + +-- strip off {} used to define locator in pandoc-citeproc; see #5722 +stripLocatorBraces :: [Inline] -> [Inline] +stripLocatorBraces = walk go +  where go (Str xs) = Str $ T.filter (\c -> c /= '{' && c /= '}') xs +        go x        = x + +citationsToBiblatex :: PandocMonad m +                    => ([Inline] -> LW m (Doc Text)) +                    -> [Citation] -> LW m (Doc Text) +citationsToBiblatex inlineListToLaTeX [one] +  = citeCommand inlineListToLaTeX cmd p s k +    where +       Citation { citationId = k +                , citationPrefix = p +                , citationSuffix = s +                , citationMode = m +                } = one +       cmd = case m of +                  SuppressAuthor -> "autocite*" +                  AuthorInText   -> "textcite" +                  NormalCitation -> "autocite" + +citationsToBiblatex inlineListToLaTeX (c:cs) +  | all (\cit -> null (citationPrefix cit) && null (citationSuffix cit)) (c:cs) +    = do +      let cmd = case citationMode c of +                    SuppressAuthor -> "\\autocite*" +                    AuthorInText   -> "\\textcite" +                    NormalCitation -> "\\autocite" +      return $ text cmd <> +               braces (literal (T.intercalate "," (map citationId (c:cs)))) +  | otherwise +    = do +      let cmd = case citationMode c of +                    SuppressAuthor -> "\\autocites*" +                    AuthorInText   -> "\\textcites" +                    NormalCitation -> "\\autocites" + +      groups <- mapM (citeArgumentsList inlineListToLaTeX) +                     (reverse (foldl' grouper [] (c:cs))) + +      return $ text cmd <> mconcat groups + +  where grouper prev cit = case prev of +         ((CiteGroup oPfx oSfx ids):rest) +             | null oSfx && null pfx -> CiteGroup oPfx sfx (cid:ids) : rest +         _ -> CiteGroup pfx sfx [cid] : prev +         where pfx = citationPrefix cit +               sfx = citationSuffix cit +               cid = citationId cit + +citationsToBiblatex _ _ = return empty | 
