diff options
author | John MacFarlane <jgm@berkeley.edu> | 2016-05-31 12:44:29 -0700 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2016-05-31 12:44:29 -0700 |
commit | 061bc60f70eb2b2a9e7fcea96dda9ff172411650 (patch) | |
tree | 2d73596e2d46382f15144a1d04b3bbb5a8c7a6ae | |
parent | 669ecbd4abc0061d83537511ebeae10713a50047 (diff) | |
parent | f226cb88b040dcd19e09ca7772ee0c6172eaecc2 (diff) | |
download | pandoc-061bc60f70eb2b2a9e7fcea96dda9ff172411650.tar.gz |
Merge pull request #2950 from tarleb/org-ref-support
Org reader: support org-ref style citations
-rw-r--r-- | src/Text/Pandoc/Readers/Org/Inlines.hs | 77 | ||||
-rw-r--r-- | src/Text/Pandoc/Readers/Org/Parsing.hs | 1 | ||||
-rw-r--r-- | tests/Tests/Readers/Org.hs | 36 |
3 files changed, 107 insertions, 7 deletions
diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs index a122c334a..6971ca3c6 100644 --- a/src/Text/Pandoc/Readers/Org/Inlines.hs +++ b/src/Text/Pandoc/Readers/Org/Inlines.hs @@ -193,15 +193,78 @@ endline = try $ do cite :: OrgParser (F Inlines) cite = try $ do guardEnabled Ext_citations - (cs, raw) <- withRaw normalCite + (cs, raw) <- withRaw (pandocOrgCite <|> orgRefCite) return $ (flip B.cite (B.text raw)) <$> cs -normalCite :: OrgParser (F [Citation]) -normalCite = try $ char '[' - *> skipSpaces - *> citeList - <* skipSpaces - <* char ']' +-- | A citation in Pandoc Org-mode style (@[\@citekey]@). +pandocOrgCite :: OrgParser (F [Citation]) +pandocOrgCite = try $ + char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']' + +orgRefCite :: OrgParser (F [Citation]) +orgRefCite = try $ normalOrgRefCite <|> (fmap (:[]) <$> linkLikeOrgRefCite) + +normalOrgRefCite :: OrgParser (F [Citation]) +normalOrgRefCite = try $ do + mode <- orgRefCiteMode + sequence <$> sepBy1 (orgRefCiteList mode) (char ',') + where + -- | A list of org-ref style citation keys, parsed as citation of the given + -- citation mode. + orgRefCiteList :: CitationMode -> OrgParser (F Citation) + orgRefCiteList citeMode = try $ do + key <- orgRefCiteKey + returnF $ Citation + { citationId = key + , citationPrefix = mempty + , citationSuffix = mempty + , citationMode = citeMode + , citationNoteNum = 0 + , citationHash = 0 + } + +-- | Read a link-like org-ref style citation. The citation includes pre and +-- post text. However, multiple citations are not possible due to limitations +-- in the syntax. +linkLikeOrgRefCite :: OrgParser (F Citation) +linkLikeOrgRefCite = try $ do + _ <- string "[[" + mode <- orgRefCiteMode + key <- orgRefCiteKey + _ <- string "][" + pre <- trimInlinesF . mconcat <$> manyTill inline (try $ string "::") + spc <- option False (True <$ spaceChar) + suf <- trimInlinesF . mconcat <$> manyTill inline (try $ string "]]") + return $ do + pre' <- pre + suf' <- suf + return Citation + { citationId = key + , citationPrefix = B.toList pre' + , citationSuffix = B.toList (if spc then B.space <> suf' else suf') + , citationMode = mode + , citationNoteNum = 0 + , citationHash = 0 + } + +-- | Read a citation key. The characters allowed in citation keys are taken +-- from the `org-ref-cite-re` variable in `org-ref.el`. +orgRefCiteKey :: OrgParser String +orgRefCiteKey = try . many1 . satisfy $ \c -> + isAlphaNum c || c `elem` ("-_:\\./"::String) + +-- | Supported citation types. Only a small subset of org-ref types is +-- supported for now. TODO: rewrite this, use LaTeX reader as template. +orgRefCiteMode :: OrgParser CitationMode +orgRefCiteMode = + choice $ map (\(s, mode) -> mode <$ try (string s <* char ':')) + [ ("cite", AuthorInText) + , ("citep", NormalCitation) + , ("citep*", NormalCitation) + , ("citet", AuthorInText) + , ("citet*", AuthorInText) + , ("citeyear", SuppressAuthor) + ] citeList :: OrgParser (F [Citation]) citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces) diff --git a/src/Text/Pandoc/Readers/Org/Parsing.hs b/src/Text/Pandoc/Readers/Org/Parsing.hs index 9a1420645..0b6b876d8 100644 --- a/src/Text/Pandoc/Readers/Org/Parsing.hs +++ b/src/Text/Pandoc/Readers/Org/Parsing.hs @@ -79,6 +79,7 @@ module Text.Pandoc.Readers.Org.Parsing , skipMany1 , spaces , anyChar + , satisfy , string , count , eof diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs index 345ed462a..9bd999b01 100644 --- a/tests/Tests/Readers/Org.hs +++ b/tests/Tests/Readers/Org.hs @@ -300,6 +300,42 @@ tests = , citationHash = 0} in (para $ cite [citation] "[see @item1 p. 34-35]") + , "Org-ref simple citation" =: + "cite:pandoc" =?> + let citation = Citation + { citationId = "pandoc" + , citationPrefix = mempty + , citationSuffix = mempty + , citationMode = AuthorInText + , citationNoteNum = 0 + , citationHash = 0 + } + in (para $ cite [citation] "cite:pandoc") + + , "Org-ref simple citep citation" =: + "citep:pandoc" =?> + let citation = Citation + { citationId = "pandoc" + , citationPrefix = mempty + , citationSuffix = mempty + , citationMode = NormalCitation + , citationNoteNum = 0 + , citationHash = 0 + } + in (para $ cite [citation] "citep:pandoc") + + , "Org-ref extended citation" =: + "[[citep:Dominik201408][See page 20::, for example]]" =?> + let citation = Citation + { citationId = "Dominik201408" + , citationPrefix = toList "See page 20" + , citationSuffix = toList ", for example" + , citationMode = NormalCitation + , citationNoteNum = 0 + , citationHash = 0 + } + in (para $ cite [citation] "[[citep:Dominik201408][See page 20::, for example]]") + , "Inline LaTeX symbol" =: "\\dots" =?> para "…" |