packages feed

countable-inflections 0.2.0 → 0.3.0

raw patch · 5 files changed

+102/−46 lines, 5 filesdep ~QuickCheckdep ~basedep ~exceptionsPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: QuickCheck, base, exceptions, hspec, text

API changes (from Hackage documentation)

+ Text.Countable: inflect :: Text -> Int -> Text
+ Text.Countable: inflectWith :: [Inflection] -> Text -> Int -> Text

Files

CHANGELOG.md view
@@ -0,0 +1,11 @@+## 0.3.0++* Bumped lts from 8.0 to 10.8++## 0.2.1++* Add inflect and inflectWith methods for pluralizing or singularizing based on input++## 0.2.0++* solidify basic API and fix regex problems with replace
README.md view
@@ -41,7 +41,7 @@ λ: :t makeMatchMapping [(RegexPattern, RegexReplace)] -> [Inflection] -λ: let mapping = makeMatchMapping [("(octop)us", "\1i")]+λ: let mapping = makeMatchMapping [("(octop)us", "\\1i")] λ: pluralizeWith mapping "octopus" "octopi" ```@@ -67,6 +67,18 @@ [Text] -> [Inflection] ``` +### Inflect++In general you can input a number and singularize or pluralize based on the count, for example:++```haskell+setReport = do+  sets <- getSets+  n <- length sets+  print $ show n ++ " " ++ inflect "sets" n+```++This way it'll list as "1 set" or "5 sets" based on the input.  ## License 
Text/Countable.hs view
@@ -3,11 +3,15 @@ -- Copyright   :  © 2016 Brady Ouren -- License     :  MIT ----- Maintainer  :  Brady Ouren <brady@andand.co>--- Stability   :  experimental+-- Maintainer  :  Brady Ouren <brady.ouren@gmail.com>+-- Stability   :  stable -- Portability :  portable -- -- pluralization and singularization transformations+--+-- Note: This library is portable in the sense of haskell extensions+-- however, it is _not_ portable in the sense of requiring PCRE regex+-- bindings on the system  {-# LANGUAGE OverloadedStrings #-} @@ -16,39 +20,39 @@   , pluralizeWith   , singularize   , singularizeWith+  , inflect+  , inflectWith   , makeMatchMapping   , makeIrregularMapping   , makeUncountableMapping   ) where -import Data.Maybe (catMaybes, fromMaybe, isNothing)-import Data.Text as T+import Data.Maybe (catMaybes, fromMaybe, isJust)+import Data.Text (Text) import Data.Text.Encoding (decodeUtf8, encodeUtf8) import Text.Countable.Data import Text.Regex.PCRE.ByteString import Text.Regex.PCRE.ByteString.Utils (substitute') import System.IO.Unsafe -type RegexPattern = T.Text-type RegexReplace = T.Text-type Singular = T.Text-type Plural = T.Text+type RegexPattern = Text+type RegexReplace = Text+type Singular = Text+type Plural = Text  data Inflection   = Simple (Singular, Plural)   | Match (Maybe Regex, RegexReplace) -data MatchType = HasMatch | HasNoMatch- -- | pluralize a word given a default mapping-pluralize :: T.Text -> T.Text+pluralize :: Text -> Text pluralize = pluralizeWith mapping   where     mapping = defaultIrregulars ++ defaultUncountables ++ defaultPlurals  -- | singularize a word given a default mapping-singularize :: T.Text -> T.Text+singularize :: Text -> Text singularize = singularizeWith mapping   where     mapping = defaultIrregulars ++ defaultUncountables ++ defaultSingulars@@ -56,23 +60,36 @@ -- | pluralize a word given a custom mapping. -- Build the [Inflection] with a combination of -- `makeUncountableMapping` `makeIrregularMapping` `makeMatchMapping`-pluralizeWith :: [Inflection] -> T.Text -> T.Text-pluralizeWith mapping t = fromMaybe t $ headMaybe matches-  where-    matches = catMaybes $ fmap (pluralLookup t) (Prelude.reverse mapping)+pluralizeWith :: [Inflection] -> Text -> Text+pluralizeWith = lookupWith pluralLookup  -- | singularize a word given a custom mapping. -- Build the [Inflection] with a combination of -- `makeUncountableMapping` `makeIrregularMapping` `makeMatchMapping`-singularizeWith :: [Inflection] -> T.Text -> T.Text-singularizeWith mapping t = fromMaybe t $ headMaybe matches+singularizeWith :: [Inflection] -> Text -> Text+singularizeWith =  lookupWith singularLookup++-- | inflect a word given any number+inflect :: Text -> Int -> Text+inflect t i = case i of+  1 -> singularize t+  _ -> pluralize t++-- | inflect a word given any number and inflection mapping+inflectWith :: [Inflection] -> Text -> Int -> Text+inflectWith l t i = case i of+  1 -> singularizeWith l t+  _ -> pluralizeWith l t++lookupWith :: (Text -> Inflection -> Maybe Text) -> [Inflection] -> Text -> Text+lookupWith f mapping target = fromMaybe target $ headMaybe matches   where-    matches = catMaybes $ fmap (singularLookup t) (Prelude.reverse mapping)+    matches = catMaybes $ fmap (f target) (Prelude.reverse mapping)  -- | Makes a simple list of mappings from singular to plural, e.g [("person", "people")] -- the output of [Inflection] should be consumed by `singularizeWith` or `pluralizeWith` makeMatchMapping :: [(RegexPattern, RegexReplace)] -> [Inflection]-makeMatchMapping = fmap (\(pattern, rep) -> Match (regexPattern pattern, rep))+makeMatchMapping = fmap (\(pat, rep) -> Match (regexPattern pat, rep))  -- | Makes a simple list of mappings from singular to plural, e.g [("person", "people")] -- the output of [Inflection] should be consumed by `singularizeWith` or `pluralizeWith`@@ -82,8 +99,8 @@ -- | Makes a simple list of uncountables which don't have -- singular plural versions, e.g ["fish", "money"] -- the output of [Inflection] should be consumed by `singularizeWith` or `pluralizeWith`-makeUncountableMapping :: [T.Text] -> [Inflection]-makeUncountableMapping = fmap (\a -> (Simple (a,a)))+makeUncountableMapping :: [Text] -> [Inflection]+makeUncountableMapping = fmap (\a -> Simple (a,a))   defaultPlurals :: [Inflection]@@ -98,32 +115,33 @@ defaultUncountables :: [Inflection] defaultUncountables = makeUncountableMapping defaultUncountables' -pluralLookup :: T.Text -> Inflection -> Maybe T.Text+pluralLookup :: Text -> Inflection -> Maybe Text pluralLookup t (Match (r1,r2)) = runSub (r1,r2) t-pluralLookup t (Simple (a,b)) = if t == a then (Just b) else Nothing+pluralLookup t (Simple (a,b)) = if t == a then Just b else Nothing -singularLookup :: T.Text -> Inflection -> Maybe T.Text+singularLookup :: Text -> Inflection -> Maybe Text singularLookup t (Match (r1,r2)) = runSub (r1,r2) t-singularLookup t (Simple (a,b)) = if t == b then (Just a) else Nothing+singularLookup t (Simple (a,b)) = if t == b then Just a else Nothing -runSub :: (Maybe Regex, RegexReplace) -> T.Text -> Maybe T.Text+runSub :: (Maybe Regex, RegexReplace) -> Text -> Maybe Text runSub (Nothing, _) _ = Nothing runSub (Just reg, rep) t = matchWithReplace (reg, rep) t -matchWithReplace :: (Regex, RegexReplace) -> T.Text -> Maybe T.Text-matchWithReplace (reg, rep) t = case regexMatch t reg of-  HasNoMatch -> Nothing-  HasMatch   -> toMaybe $ substitute' reg (encodeUtf8 t) (encodeUtf8 rep)+matchWithReplace :: (Regex, RegexReplace) -> Text -> Maybe Text+matchWithReplace (reg, rep) t =+  if regexMatch t reg+  then toMaybe $ substitute' reg (encodeUtf8 t) (encodeUtf8 rep)+  else Nothing   where     toMaybe = either (const Nothing) (Just . decodeUtf8) -regexMatch :: T.Text -> Regex -> MatchType+regexMatch :: Text -> Regex -> Bool regexMatch t r = case match of-                   Left _ -> HasNoMatch-                   Right m -> if isNothing m then HasNoMatch else HasMatch+                   Left _ -> False+                   Right m -> isJust m   where match = unsafePerformIO $ execute r (encodeUtf8 t) -regexPattern :: T.Text -> Maybe Regex+regexPattern :: Text -> Maybe Regex regexPattern pat = toMaybe reg   where toMaybe = either (const Nothing) Just         reg = unsafePerformIO $ compile compCaseless execBlank (encodeUtf8 pat)
countable-inflections.cabal view
@@ -1,5 +1,5 @@ name:                countable-inflections-version:             0.2.0+version:             0.3.0 synopsis:            Countable Text Inflections description:   Provides methods for singularizing and pluralizing text.@@ -7,10 +7,10 @@  license:             MIT license-file:        LICENSE.md-author:              Brady Ouren <brady@andand.co>+author:              Brady Ouren <brady.ouren@gmail.com> homepage:            https://github.com/tippenein/countable-inflections bug-reports:         https://github.com/tippenein/countable-inflections/issues-maintainer:          Brady Ouren <brady@andand.co>+maintainer:          Brady Ouren <brady.ouren@gmail.com> copyright:           2016 Brady Ouren category:            Text build-type:          Simple@@ -32,9 +32,9 @@   other-modules:       Text.Countable.Data   ghc-options:         -Wall   build-depends:-      base         >= 4.6   && < 4.10-    , exceptions   >= 0.6   && < 0.9-    , text         >= 0.2   && < 1.3+      base >= 4.8 && < 5+    , exceptions+    , text     , regex-pcre-builtin     , pcre-utils     , bytestring@@ -46,10 +46,10 @@   main-is: Spec.hs   build-depends:       countable-inflections-    , QuickCheck   >= 2.7.6 && < 3.0-    , base         >= 4.2   && < 4.10-    , hspec        >= 2.0   && < 3.0-    , text         >= 0.2   && < 1.3+    , QuickCheck+    , base+    , hspec+    , text   ghc-options:         -Wall   default-language:    Haskell2010   other-modules:       Text.CountableSpec
test/Text/CountableSpec.hs view
@@ -10,6 +10,21 @@ spec = do   irregularCases   matchingCases+  inflectingCases++inflectingCases :: Spec+inflectingCases = do+  describe "given 1" $ do+    it "singularizes" $+      inflect "sets" 1 `shouldBe` "set"++  describe "given 10" $ do+    it "pluralizes" $+      inflect "sets" 10 `shouldBe` "sets"++    it "pluralizes when in doubt" $+      inflect "sets" (-1) `shouldBe` "sets"+  matchingCases :: Spec matchingCases = do