module FastTags.Util where
import qualified Data.ByteString as ByteString
import qualified Data.Char as Char
import qualified Data.Function as Function
import qualified Data.List as List
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import qualified Data.Text as Text
import Data.Text (Text)
import qualified Data.Text.Encoding as Encoding
import qualified Data.Text.Encoding.Error as Encoding.Error
readFileLenient :: FilePath -> IO Text
readFileLenient = fmap (Encoding.decodeUtf8With Encoding.Error.lenientDecode)
. ByteString.readFile
dropBefore :: (a -> Bool) -> [a] -> [a]
dropBefore f = go
where
go [] = []
go [_] = []
go xs@(_ : rest@(y:_))
| f y = xs
| otherwise = go rest
sortOn :: (Ord k) => (a -> k) -> [a] -> [a]
sortOn key = List.sortBy (compare `Function.on` key)
split :: (Eq a) => a -> [a] -> [[a]]
split _ [] = []
split x xs = xs': split x (drop 1 xs'')
where (xs', xs'') = break (==x) xs
headt :: Text -> Maybe Char
headt = fmap fst . Text.uncons
mhead :: [a] -> Maybe a
mhead [] = Nothing
mhead (x:_) = Just x
mlast :: [a] -> Maybe a
mlast xs
| null xs = Nothing
| otherwise = Just (last xs)
keyOn :: (a -> k) -> [a] -> [(k, a)]
keyOn f xs = zip (map f xs) xs
groupOn :: Eq k => (a -> k) -> [a] -> [[a]]
groupOn key = List.groupBy (\a b -> key a == key b)
groupOnKey :: Ord key => (a -> key) -> [a] -> [(key, [a])]
groupOnKey key = Map.toAscList . List.foldl' go Map.empty
where go m x = Map.alter (Just . maybe [x] (x:)) (key x) m
isSymbolCharacterCategory :: Char.GeneralCategory -> Bool
isSymbolCharacterCategory cat = Set.member cat symbolCategories
where
symbolCategories :: Set.Set Char.GeneralCategory
symbolCategories = Set.fromList
[ Char.ConnectorPunctuation
, Char.DashPunctuation
, Char.OtherPunctuation
, Char.MathSymbol
, Char.CurrencySymbol
, Char.ModifierSymbol
, Char.OtherSymbol
]
unique :: Ord a => [a] -> [a]
unique = Set.toList . Set.fromList