module PureScript.Ide.Matcher (flexMatcher, runMatcher) where
import Data.Function (on)
import Data.List (sortBy)
import Data.Maybe (mapMaybe)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import PureScript.Ide.Types
import Text.Regex.TDFA ((=~))
type ScoredCompletion = (Double, Completion)
flexMatcher :: T.Text -> Matcher
flexMatcher pattern = mkMatcher (flexMatch pattern)
mkMatcher :: ([Completion] -> [ScoredCompletion]) -> Matcher
mkMatcher matcher = Matcher $ fmap snd . sortCompletions . matcher
runMatcher :: Matcher -> [Completion] -> [Completion]
runMatcher (Matcher m) = m
sortCompletions :: [ScoredCompletion] -> [ScoredCompletion]
sortCompletions = sortBy (flip compare `on` fst)
flexMatch :: T.Text -> [Completion] -> [ScoredCompletion]
flexMatch pattern = mapMaybe (flexRate pattern)
flexRate :: T.Text -> Completion -> Maybe ScoredCompletion
flexRate pattern c@(Completion (_,ident,_)) =
(,) <$> flexScore pattern ident <*> pure c
flexScore :: T.Text -> DeclIdent -> Maybe Double
flexScore "" _ = Nothing
flexScore pat str =
case TE.encodeUtf8 str =~ TE.encodeUtf8 pat' :: (Int, Int) of
(1,0) -> Nothing
(start,len) -> Just $ calcScore start (start + len)
where
Just (first, pattern) = T.uncons pat
pat' = first `T.cons` T.concatMap (T.snoc ".*") pattern
calcScore start end =
100.0 / fromIntegral ((1 + start) * (end start + 1))