Skip to content

Commit

Permalink
Add documentation for filter function with custom scoring function
Browse files Browse the repository at this point in the history
Replace all functions using previous filter without custom scoring
with a call to the new filter function where the scoring function is the basic match function.
  • Loading branch information
VeryMilkyJoe committed Jul 6, 2023
1 parent 505809c commit e41f143
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 33 deletions.
2 changes: 1 addition & 1 deletion ghcide/src/Development/IDE/Plugin/Completions/Logic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ getCompletions plugins ideOpts CC {allModNamesAsNS, anyQualCompls, unqualCompls,
$ (if T.null enteredQual then id else mapMaybe (T.stripPrefix enteredQual))
allModNamesAsNS

filtCompls = Fuzzy.filter chunkSize maxC prefixText ctxCompls (label . snd)
filtCompls = Fuzzy.filter chunkSize maxC prefixText ctxCompls (label . snd) Fuzzy.match
where

mcc = case maybe_parsed of
Expand Down
47 changes: 15 additions & 32 deletions ghcide/src/Text/Fuzzy/Parallel.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- | Parallel versions of 'filter' and 'simpleFilter'

module Text.Fuzzy.Parallel
( filter, filter',
( filter,
simpleFilter, simpleFilter',
match, defChunkSize, defMaxResults,
Scored(..)
Expand Down Expand Up @@ -29,7 +29,6 @@ data Scored a = Scored {score :: !Int, original:: !a}
-- Just 5
--
{-# INLINABLE match #-}

match :: T.Text -- ^ Pattern in lowercase except for first character
-> T.Text -- ^ The text to search in.
-> Maybe Int -- ^ The score
Expand Down Expand Up @@ -70,23 +69,6 @@ match (T.Text pArr pOff pLen) (T.Text sArr sOff sLen) = go 0 1 pOff sOff

toLowerAscii w = if (w - 65) < 26 then w .|. 0x20 else w

-- | The function to filter a list of values by fuzzy search on the text extracted from them.
filter :: Int -- ^ Chunk size. 1000 works well.
-> Int -- ^ Max. number of results wanted
-> T.Text -- ^ Pattern.
-> [t] -- ^ The list of values containing the text to search in.
-> (t -> T.Text) -- ^ The function to extract the text from the container.
-> [Scored t] -- ^ The list of results, sorted, highest score first.
filter chunkSize maxRes pattern ts extract = partialSortByAscScore maxRes perfectScore (concat vss)
where
-- Preserve case for the first character, make all others lowercase
pattern' = case T.uncons pattern of
Just (c, rest) -> T.cons c (T.toLower rest)
_ -> pattern
vss = map (mapMaybe (\t -> flip Scored t <$> match pattern' (extract t))) (chunkList chunkSize ts)
`using` parList (evalList rseq)
perfectScore = fromMaybe (error $ T.unpack pattern) $ match pattern' pattern'

-- | Sensible default value for chunk size to use when calling simple filter.
defChunkSize :: Int
defChunkSize = 1000
Expand All @@ -108,18 +90,21 @@ simpleFilter :: Int -- ^ Chunk size. 1000 works well.
-> [T.Text] -- ^ List of texts to check.
-> [Scored T.Text] -- ^ The ones that match.
simpleFilter chunk maxRes pattern xs =
filter chunk maxRes pattern xs id
filter chunk maxRes pattern xs id match


-- | The function to filter a list of values by fuzzy search on the text extracted from them.
filter' :: Int -- ^ Chunk size. 1000 works well.
-- | The function to filter a list of values by fuzzy search on the text extracted from them,
-- using a custom matching function which determines how close words are.
filter :: Int -- ^ Chunk size. 1000 works well.
-> Int -- ^ Max. number of results wanted
-> T.Text -- ^ Pattern.
-> [t] -- ^ The list of values containing the text to search in.
-> (t -> T.Text) -- ^ The function to extract the text from the container.
-> (T.Text -> T.Text -> Maybe Int) -- ^ Function to use for matching
-> (T.Text -> T.Text -> Maybe Int)
-- ^ Custom scoring function to use for calculating how close words are
-- When the function returns Nothing, this means the values are incomparable.
-> [Scored t] -- ^ The list of results, sorted, highest score first.
filter' chunkSize maxRes pattern ts extract match' = partialSortByAscScore maxRes perfectScore (concat vss)
filter chunkSize maxRes pattern ts extract match' = partialSortByAscScore maxRes perfectScore (concat vss)
where
-- Preserve case for the first character, make all others lowercase
pattern' = case T.uncons pattern of
Expand All @@ -129,21 +114,19 @@ filter' chunkSize maxRes pattern ts extract match' = partialSortByAscScore maxRe
`using` parList (evalList rseq)
perfectScore = fromMaybe (error $ T.unpack pattern) $ match' pattern' pattern'

-- | Return all elements of the list that have a fuzzy
-- match against the pattern, using a custom match function. Runs with default settings where
-- nothing is added around the matches, as case insensitive.
--
-- >>> simpleFilter 1000 10 "vm" ["vim", "emacs", "virtual machine"]
-- [Scored {score = 4, original = "vim"},Scored {score = 4, original = "virtual machine"}]
-- | Return all elements of the list that have a fuzzy match against the pattern,
-- the closeness of the match is determined using the custom scoring match function that is passed.
-- Runs with default settings where nothing is added around the matches, as case insensitive.
{-# INLINABLE simpleFilter' #-}
simpleFilter' :: Int -- ^ Chunk size. 1000 works well.
-> Int -- ^ Max. number of results wanted
-> T.Text -- ^ Pattern to look for.
-> [T.Text] -- ^ List of texts to check.
-> (T.Text -> T.Text -> Maybe Int) -- ^ Function to use for matching
-> (T.Text -> T.Text -> Maybe Int)
-- ^ Custom scoring function to use for calculating how close words are
-> [Scored T.Text] -- ^ The ones that match.
simpleFilter' chunk maxRes pattern xs match' =
filter' chunk maxRes pattern xs id match'
filter chunk maxRes pattern xs id match'
--------------------------------------------------------------------------------

chunkList :: Int -> [a] -> [[a]]
Expand Down

0 comments on commit e41f143

Please sign in to comment.