Merge pull request #2950 from tarleb/org-ref-support

Org reader: support org-ref style citations
This commit is contained in:
John MacFarlane 2016-05-31 12:44:29 -07:00
commit 061bc60f70
3 changed files with 107 additions and 7 deletions

View file

@ -193,15 +193,78 @@ endline = try $ do
cite :: OrgParser (F Inlines) cite :: OrgParser (F Inlines)
cite = try $ do cite = try $ do
guardEnabled Ext_citations guardEnabled Ext_citations
(cs, raw) <- withRaw normalCite (cs, raw) <- withRaw (pandocOrgCite <|> orgRefCite)
return $ (flip B.cite (B.text raw)) <$> cs return $ (flip B.cite (B.text raw)) <$> cs
normalCite :: OrgParser (F [Citation]) -- | A citation in Pandoc Org-mode style (@[\@citekey]@).
normalCite = try $ char '[' pandocOrgCite :: OrgParser (F [Citation])
*> skipSpaces pandocOrgCite = try $
*> citeList char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']'
<* 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 :: OrgParser (F [Citation])
citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces) citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces)

View file

@ -79,6 +79,7 @@ module Text.Pandoc.Readers.Org.Parsing
, skipMany1 , skipMany1
, spaces , spaces
, anyChar , anyChar
, satisfy
, string , string
, count , count
, eof , eof

View file

@ -300,6 +300,42 @@ tests =
, citationHash = 0} , citationHash = 0}
in (para $ cite [citation] "[see @item1 p. 34-35]") 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" =: , "Inline LaTeX symbol" =:
"\\dots" =?> "\\dots" =?>
para "" para ""