{-# LANGUAGE TupleSections #-} module Dustme.Search where import Control.Monad (guard) import Data.Char (isSpace) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HM import Data.List (sortBy) import Data.Maybe (mapMaybe) import Data.Monoid ((<>)) import Data.Ord (comparing) import Data.Text (Text) import qualified Data.Text as T import Dustme.Score (bestMatches, getIndices, matchComparison) import Dustme.Types import Safe (headMay) -- Could be more sophisticated here isBoundaryChar = isSpace emptyCache = HM.empty getResults :: [Text] -> SearchCache -> Search -> (SearchResult, SearchCache) getResults candidates cache search = case HM.lookup search cache of Nothing -> let result = runSearch search candidates in (result, HM.insert search result cache) Just cached -> (cached, cache) runSearch :: Search -> [Text] -> SearchResult runSearch (Search st) candidates = sortBy matchComparison $ mapMaybe (headMay . bestMatches st) candidates applyOp :: [Text] -> SearchOp -> Search -> SearchResult -> (Search,[Text]) applyOp candidates op (Search st) matches = case op of AddText t -> ( Search (st <> t) , map matchText matches) Backspace -> ( Search (T.dropEnd 1 st) , candidates) DeleteWord -> ( Search $ T.dropWhileEnd (not . isBoundaryChar) st , candidates)