fuzzily 0.1.0.0 → 0.2.0.0
raw patch · 4 files changed
+123/−40 lines, 4 filesdep ~HUnitdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: HUnit, base
API changes (from Hackage documentation)
Files
- README.md +17/−11
- fuzzily.cabal +3/−4
- src/Text/Fuzzily.hs +15/−13
- tests/tests.hs +88/−12
README.md view
@@ -9,6 +9,12 @@ which itselft was a port of the JavaScript library [mattyork/fuzzy](https://github.com/mattyork/fuzzy). +It's main difference is more readable code and a cleaner API:++- Descriptive variable names+- ADTs instead of booleans+- …+ It was initially forked to be used in [TaskLite](https://tasklite.org/)'s `find` sub-command. @@ -18,36 +24,36 @@ ```haskell > import Text.Fuzzily -> match "fnt" "infinite" ("", "") id HandleCase-Just (Fuzzily+> match HandleCase ("", "") id "fnt" "infinite"+Just (Fuzzy { original = "infinite" , rendered = "infinite" , score = 3 }) -> match "hsk" ("Haskell",1995) ("<", ">") fst IgnoreCase-Just (Fuzzily+> match IgnoreCase ("<", ">") fst "hsk" ("Haskell", 1995)+Just (Fuzzy { original = ("Haskell", 1995)- , rendered = "<h>a<s><k>ell"+ , rendered = "<H>a<s><k>ell" , score = 5 }) > langs = [("Standard ML", 1990), ("OCaml", 1996), ("Scala", 2003)]-> filter "ML" langs ("<", ">") fst IgnoreCase-[ Fuzzily+> filter IgnoreCase ("<", ">") fst "ML" langs+[ Fuzzy { original = ("Standard ML", 1990)- , rendered = "standard <m><l>"+ , rendered = "Standard <M><L>" , score = 4 }-, Fuzzily+, Fuzzy { original = ("OCaml", 1996)- , rendered = "oca<m><l>"+ , rendered = "OCa<m><l>" , score = 4 } ] > simpleFilter "vm" ["vim", "emacs", "virtual machine"]-["vim","virtual machine"]+["vim", "virtual machine"] > test "brd" "bread" True
fuzzily.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: fuzzily-version: 0.1.0.0+version: 0.2.0.0 synopsis: Filters a list based on a fuzzy string search description: Fuzzily is a library that filters a list based on a fuzzy string search. Uses 'TextualMonoid' to be able to run on different types of strings.@@ -54,9 +54,8 @@ NoImplicitPrelude ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-orphans build-depends:- HUnit- , base+ HUnit ==1.6.*+ , base >=4.18.2 && <5 , fuzzily- , monoid-subclasses >=1.2.5 && <1.3 , protolude >=0.3.4 && <0.4 default-language: Haskell2010
src/Text/Fuzzily.hs view
@@ -71,6 +71,7 @@ , score = 5 }) -}+{-# INLINABLE match #-} match :: (T.TextualMonoid text) => CaseSensitivity@@ -85,14 +86,13 @@ -- ^ Value containing the text to search in -> Maybe (Fuzzy value text) -- ^ Original value, rendered string, and score-match caseSensitivity (pre, post) extractFunc pattern value =+match caseSensitivity (pre, post) extractFunc pattern value = do let+ normFunc = if caseSensitivity == HandleCase+ then identity+ else toLower+ searchText = extractFunc value- (searchTextNorm, patternNorm) =- let mapToLower = T.map toLower- in if caseSensitivity == HandleCase- then (searchText, pattern)- else (mapToLower searchText, pattern) (totalScore, _, result, patternFromFold) = T.foldl_'@@ -105,7 +105,7 @@ , pat ) Just (x, xs) ->- if x == c+ if normFunc x == normFunc c then let cur' = cur * 2 + 1 in ( tot + cur'@@ -120,14 +120,14 @@ , pat ) )- (0, 0, mempty, patternNorm)- searchTextNorm- in- if null patternFromFold- then Just (Fuzzy value result totalScore)- else Nothing+ (0, 0, mempty, pattern)+ searchText + if null patternFromFold+ then Just (Fuzzy value result totalScore)+ else Nothing + {-| The function to filter a list of values by fuzzy search on the text extracted from them.@@ -145,6 +145,7 @@ } ] -}+{-# INLINABLE filter #-} filter :: (T.TextualMonoid text) => CaseSensitivity@@ -176,6 +177,7 @@ >>> simpleFilter "vm" ["vim", "emacs", "virtual machine"] ["vim","virtual machine"] -}+{-# INLINABLE simpleFilter #-} simpleFilter :: (T.TextualMonoid text) => text
tests/tests.hs view
@@ -2,10 +2,13 @@ import Protolude ( Bool (False, True),+ Char, IO,+ Int, Maybe (Just, Nothing), Monad (return), Ord ((>)),+ fst, head, identity, map,@@ -16,9 +19,10 @@ import Test.HUnit (Assertion, Test (..), runTestTT, (@?=)) import Text.Fuzzily as Fu ( CaseSensitivity (HandleCase, IgnoreCase),- Fuzzy (original, rendered, score),+ Fuzzy (Fuzzy, original, rendered, score), filter, match,+ simpleFilter, test, ) @@ -32,7 +36,7 @@ TestList [ TestLabel "test" $ TestList- [ TestLabel "should return true when fuzzy match" $+ [ TestLabel "returns true when fuzzy match" $ from [ Fu.test "back" "imaback" @?= True , Fu.test "back" "bakck" @?= True@@ -48,7 +52,7 @@ , TestLabel "match" $ TestList [ TestLabel- "should return a greater score for consecutive matches of pattern"+ "returns a greater score for consecutive matches of pattern" $ from [ (>) (Fu.score <$> Fu.match IgnoreCase ("", "") identity "abcd" "zabcd")@@ -56,7 +60,7 @@ @?= True ] , TestLabel- "should return the string as is if no pre/post and case sensitive"+ "returns the string as is if no pre/post and case sensitive" $ from [ Fu.rendered <$> Fu.match@@ -67,7 +71,7 @@ "ZaZbZ" @?= Just "ZaZbZ" ]- , TestLabel "should return Nothing on no match" $+ , TestLabel "returns Nothing on no match" $ from [ Fu.match IgnoreCase@@ -77,7 +81,7 @@ "ZaZbZ" @?= Nothing ]- , TestLabel "should be case sensitive is specified" $+ , TestLabel "is case sensitive if specified" $ from [ Fu.match HandleCase@@ -87,7 +91,7 @@ "Haskell" @?= Nothing ]- , TestLabel "should be wrap pre and post around matches" $+ , TestLabel "wraps pre and post around matches" $ from [ Fu.rendered <$> Fu.match@@ -101,19 +105,91 @@ ] , TestLabel "filter" $ TestList- [ TestLabel "should return list untouched when given empty pattern" $+ [ TestLabel "returns list untouched when given empty pattern" $ from- [ map- Fu.original- (Fu.filter HandleCase ("", "") identity "" ["abc", "def"])+ [ ( Fu.original+ `map` ( Fu.filter+ HandleCase+ ("", "")+ identity+ ""+ ["abc", "def"]+ )+ ) @?= ["abc", "def"] ]- , TestLabel "should return the highest score first" $+ , TestLabel "returns the highest score first" $ from [ (@?=) (head (Fu.filter HandleCase ("", "") identity "cb" ["cab", "acb"])) (head (Fu.filter HandleCase ("", "") identity "cb" ["acb"])) ]+ , TestLabel "keeps original casing when filtering case insensitive" $+ from+ [ ( Fu.original+ `map` ( Fu.filter+ IgnoreCase+ ("", "")+ identity+ "abc"+ ["aBc"]+ )+ )+ @?= ["aBc"]+ ]+ ]+ , TestLabel "README examples" $+ TestList+ [ TestLabel "hsk" $+ from+ [ ( match+ IgnoreCase+ ("<", ">")+ fst+ "hsk"+ ("Haskell", 1995 :: Int)+ )+ @?= Just+ ( Fuzzy+ { original = ("Haskell", 1995)+ , rendered = "<H>a<s><k>ell"+ , score = 5+ }+ )+ ]+ , TestLabel "langs" $+ from+ [ let+ langs :: [([Char], Int)]+ langs =+ [ ("Standard ML", 1990)+ , ("OCaml", 1996)+ , ("Scala", 2003)+ ]+ result = filter IgnoreCase ("<", ">") fst "ML" langs+ expected =+ [ Fuzzy+ { original = ("Standard ML", 1990)+ , rendered = "Standard <M><L>"+ , score = 4+ }+ , Fuzzy+ { original = ("OCaml", 1996)+ , rendered = "OCa<m><l>"+ , score = 4+ }+ ]+ in+ result @?= expected+ ]+ , TestLabel "simple filter" $+ from+ [ simpleFilter "vm" ["vim", "emacs", "virtual machine"]+ @?= ["vim", "virtual machine"]+ ]+ , TestLabel "test" $+ from+ [test "brd" "bread" @?= True] ] ]