{-# LANGUAGE TypeApplications #-} module Control.Addressbook.Query where import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.Combinators as C import qualified Data.Conduit.List as CL import qualified Data.Conduit.Text as CT import qualified Data.Trie as Trie import System.IO (stdout) import Data.Maybe (fromMaybe) import System.Environment (lookupEnv) import System.FilePath (()) import Control.Exception (catch) query :: Text -> IO () query prefix = do datDir <- fromMaybe "./" <$> lookupEnv "HOME" state <- catch @IOError (runResourceT $ runConduit $ readState datDir) (\_ -> pure Trie.empty) runConduit $ outputResults state where readState :: FilePath -> ConduitM () Void (ResourceT IO) (Trie.Trie [Text]) readState dir = CB.sourceFile (dir ".addressbook.dat") .| CT.decode CT.utf8 .| CT.lines .| C.foldMap (\s -> Trie.singleton (TE.encodeUtf8 $ T.toLower s) [s]) outputResults :: Trie.Trie [Text] -> ConduitM () Void IO () outputResults state = CL.sourceList (Trie.elems $ Trie.submap (TE.encodeUtf8 prefix) state) .| C.concat .| C.map (<> "\n") .| CT.encode CT.utf8 .| CB.sinkHandle stdout