hdmenu-0.3.0: src/Core/Parser.hs
module Core.Parser
( -- * Parse the given file
getHist -- :: FilePath -> IO Items
-- * The actual parser
, pFile -- :: ByteString -> Items
) where
import Core.Util
import Data.ByteString.Char8 qualified as BS
import Data.ByteString.Lex.Fractional (readDecimal)
-- | Read a history file (the file must exist) and parse it into a map.
getHist :: FilePath -> IO Items
getHist = fmap pFile . BS.readFile
-- | Parse a history file of name-number pairs.
pFile :: ByteString -> Items
pFile = fromList . go []
where
go :: [(ByteString, Double)] -> ByteString -> [(ByteString, Double)]
go its "" = its
go its input = go (it : its) rest
where
(it, rest) :: ((ByteString, Double), ByteString)
= bimap (second (maybe 0 fst . readDecimal) . spanEnd (/= ' '))
(BS.drop 1)
. BS.span (/= '\n')
$ input
spanEnd :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
spanEnd p bs = (init' $ BS.dropWhileEnd p bs, BS.takeWhileEnd p bs)
init' :: ByteString -> ByteString
init' = maybe "" fst . BS.unsnoc
{-# INLINE pFile #-}