diff options
Diffstat (limited to 'src/Data/Name.hs')
| -rw-r--r-- | src/Data/Name.hs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/Data/Name.hs b/src/Data/Name.hs new file mode 100644 index 0000000..9572709 --- /dev/null +++ b/src/Data/Name.hs @@ -0,0 +1,76 @@ +module Data.Name + ( Name (..) + , Name_ + -- * Parsers + , readNameLFM + , readNameFML + -- * Writers + , renderNameLFM + , renderNameFML + ) where + +import Prolog +import Data.Char (isSpace) +import Data.List qualified as L +import Data.Text qualified as T + + +data Name a = Name + { lastName :: !a + , firstName :: !a + , middleName :: !(Maybe a) + } deriving (Eq, Functor, Foldable, Generic, Generic1, Ord, Show, Traversable) + +type Name_ = Name StrictText + +instance Binary a => Binary (Name a) + +instance Applicative Name where + pure a = Name a a (pure a) + Name l f m <*> Name l' f' m' = Name (l l') (f f') (m <*> m') + + +readNameLFM :: Alternative m => StrictText -> m Name_ +readNameLFM t = T.map (\c -> if c == '~' then ' ' else c) <<$>> + case T.break (== ',') t of + (l, fm) + | T.null l -> empty + | otherwise -> case T.dropWhile ((||) <$> isSpace <*> (== ',')) fm of + fm' + | T.null fm' -> empty + | otherwise -> case T.break isSpace fm' of + (f, m) -> pure $ Name l f $ case T.dropWhile isSpace m of + x | T.null x -> Nothing + | otherwise -> Just x + +readNameFML :: Alternative m => StrictText -> m Name_ +readNameFML t = T.map (\c -> if c == '~' then ' ' else c) <<$>> + case T.words t of + [] -> empty + (f:xs) -> case unsnoc xs of + Nothing -> empty + Just (m, l) -> pure $ Name f l $ case m of + [] -> Nothing + _ -> Just $ T.unwords m + +showNameLFM :: Name_ -> StrictText +showNameLFM (Name l f m) = stt l <> ", " <> stt f <> maybe "" (\x -> " " <> stt x) m + +showNameFML :: Name_ -> StrictText +showNameFML (Name l f m) = stt f <> maybe " " (\x -> " " <> stt x <> " ") m <> stt l + +renderNameLFM :: (Semigroup a, IsString a) => Name a -> a +renderNameLFM (Name l f m) = l <> ", " <> f <> maybe "" (\x -> " " <> x) m + +renderNameFML :: (Semigroup a, IsString a) => Name a -> a +renderNameFML (Name l f m) = f <> maybe " " (\x -> " " <> x <> " ") m <> l + +-- Helpers + +unsnoc :: [a] -> Maybe ([a],a) +unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing +{-# INLINABLE unsnoc #-} + +stt :: StrictText -> StrictText +stt = T.map $ \c -> if isSpace c then '~' else c +{-# INLINABLE stt #-} |
