mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-07-31 12:11:52 -07:00
X.P.OrgMode: Fix behaviour of getLast
So far, while parsing strings like "<ptn><more-letters>", the `getLast` function immediately stopped on strings of the form "<ptn><whitespace>". This may be a bit confusing given the functions name. Strings of the—perhaps artificial—form "a +d f 1 +d f 2" would be cut short and parsed as Deadline "a" (Time { date = Next Friday, tod = Just 01:00 }) instead of the more intuitive Deadline "a +d f 1" (Time { date = Next Friday, tod = Just 02:00 }). This is readily fixed by applying the `go` parser as often as possible, only returning the longest list, and then pruning eventual leftovers at the end of the string. Since we were already invoking `dropWhileEnd` to trim whitespace before, the added `reverse`s should not impact performance at all. Fixes: https://github.com/xmonad/xmonad-contrib/issues/584
This commit is contained in:
@@ -360,17 +360,18 @@ pInput inp = fmap fst . listToMaybe . (`readP_to_S` inp) . lchoice $
|
|||||||
]
|
]
|
||||||
where
|
where
|
||||||
getLast :: String -> ReadP String
|
getLast :: String -> ReadP String
|
||||||
getLast ptn = go ""
|
getLast ptn = reverse
|
||||||
|
. dropWhile (== ' ') -- trim whitespace at the end
|
||||||
|
. drop (length ptn) -- drop only the last pattern
|
||||||
|
. reverse
|
||||||
|
. concat
|
||||||
|
<$> endBy1 (go "") (pure ptn)
|
||||||
where
|
where
|
||||||
go :: String -> ReadP String
|
go :: String -> ReadP String
|
||||||
go consumed = do
|
go consumed = do
|
||||||
next <- munch (/= head ptn)
|
str <- munch (/= head ptn)
|
||||||
next' <- munch1 (/= ' ')
|
word <- munch1 (/= ' ')
|
||||||
if next' == ptn
|
bool go pure (word == ptn) $ consumed <> str <> word
|
||||||
then -- If we're done, it's time to prune extra whitespace
|
|
||||||
pure $ consumed <> dropWhileEnd (== ' ') next
|
|
||||||
else -- If not, keep it as it's part of something else
|
|
||||||
go $ consumed <> next <> next'
|
|
||||||
|
|
||||||
-- | Try to parse a 'Time'.
|
-- | Try to parse a 'Time'.
|
||||||
pTimeOfDay :: ReadP (Maybe TimeOfDay)
|
pTimeOfDay :: ReadP (Maybe TimeOfDay)
|
||||||
@@ -435,3 +436,13 @@ pInt = read <$> munch1 isDigit
|
|||||||
-- parsing when the left-most parser succeeds.
|
-- parsing when the left-most parser succeeds.
|
||||||
lchoice :: [ReadP a] -> ReadP a
|
lchoice :: [ReadP a] -> ReadP a
|
||||||
lchoice = foldl' (<++) empty
|
lchoice = foldl' (<++) empty
|
||||||
|
|
||||||
|
-- | Like 'Text.ParserCombinators.ReadP.endBy1', but only return the
|
||||||
|
-- parse where @parser@ had the highest number of applications.
|
||||||
|
endBy1 :: ReadP a -> ReadP sep -> ReadP [a]
|
||||||
|
endBy1 parser sep = many1 (parser <* sep)
|
||||||
|
where
|
||||||
|
-- | Like 'Text.ParserCombinators.ReadP.many1', but use '(<++)'
|
||||||
|
-- instead of '(+++)'.
|
||||||
|
many1 :: ReadP a -> ReadP [a]
|
||||||
|
many1 p = (:) <$> p <*> (many1 p <++ pure [])
|
||||||
|
Reference in New Issue
Block a user