git.iko.soy/typeable/pandoc
on master help sign in
Use parsec parsers to split locator.
283f1e6John MacFarlane
src/Text/Pandoc/Biblio.hs+34−27
@@ -36,6 +36,9 @@ import qualified Data.Map as M
36import Text.CSL hiding ( Cite(..), Citation(..) )
36import Text.CSL hiding ( Cite(..), Citation(..) )
37import qualified Text.CSL as CSL ( Cite(..) )
37import qualified Text.CSL as CSL ( Cite(..) )
38import Text.Pandoc.Definition
38import Text.Pandoc.Definition
39+import Text.Pandoc.Shared (stringify)
40+import Text.ParserCombinators.Parsec
41+import Control.Monad
39
42
40-- | Process a 'Pandoc' document by adding citations formatted
43-- | Process a 'Pandoc' document by adding citations formatted
41-- according to a CSL style, using 'citeproc' from citeproc-hs.
44-- according to a CSL style, using 'citeproc' from citeproc-hs.
@@ -152,7 +155,7 @@ setCitationNoteNum i = map $ \c -> c { citationNoteNum = i}
152toCslCite :: Citation -> CSL.Cite
155toCslCite :: Citation -> CSL.Cite
153toCslCite c
156toCslCite c
154 = let (l, s) = locatorWords $ citationSuffix c
157 = let (l, s) = locatorWords $ citationSuffix c
155− (la,lo) = parseLocator $ unwords l
158+ (la,lo) = parseLocator l
156 citMode = case citationMode c of
159 citMode = case citationMode c of
157 AuthorInText -> (True, False)
160 AuthorInText -> (True, False)
158 SuppressAuthor -> (False,True )
161 SuppressAuthor -> (False,True )
@@ -168,30 +171,34 @@ toCslCite c
168 , CSL.citeHash = citationHash c
171 , CSL.citeHash = citationHash c
169 }
172 }
170
173
171−locatorWords :: [Inline] -> ([String], [Inline])
174+locatorWords :: [Inline] -> (String, [Inline])
172−locatorWords (Space : t) = locatorWords t
175+locatorWords inp =
173−locatorWords (Str "" : t) = locatorWords t
176+ case parse (liftM2 (,) pLocator getInput) "suffix" inp of
174−locatorWords a@(Str (',' : s) : t)
177+ Right r -> r
175− = if ws /= [] then (ws, t') else ([], a)
178+ Left _ -> ("",inp)
176− where
179+
177− (ws, t') = locatorWords (Str s:t)
180+pMatch :: (Inline -> Bool) -> GenParser Inline st Inline
178−locatorWords i
181+pMatch condition = try $ do
182+ t <- anyToken
183+ guard $ condition t
184+ return t
185+
186+pSpace :: GenParser Inline st Inline
187+pSpace = pMatch (== Space)
188+
189+pLocator :: GenParser Inline st String
190+pLocator = try $ do
191+ optional $ pMatch (== Str ",")
192+ optional pSpace
193+ f <- many1 (notFollowedBy pSpace >> anyToken)
194+ gs <- many1 pWordWithDigits
195+ return $ stringify f ++ (' ' : unwords gs)
196+
197+pWordWithDigits :: GenParser Inline st String
198+pWordWithDigits = try $ do
199+ pSpace
200+ r <- many1 (notFollowedBy pSpace >> anyToken)
201+ let s = stringify r
179− = if any isDigit w then (w':ws, s'') else ([], i)
202+ guard $ any isDigit s
180− where
203+ return s
181− (w, s') = locatorWord i
182− (ws, s'') = locatorWords s'
183− w' = if ws == [] then w else w ++ ","
184−
185−locatorWord :: [Inline] -> (String, [Inline])
186−locatorWord (Space : r) = (" " ++ ts, r')
187− where
188− (ts, r') = locatorWord r
189−locatorWord (Str t : r)
190− | t' /= "" = (w , Str t' : r)
191− | otherwise = (t ++ ts, r' )
192− where
193− w = takeWhile (/= ',') t
194− t' = dropWhile (/= ',') t
195− (ts, r') = locatorWord r
196−locatorWord i = ("", i)
197
204