inflections 0.3.0.0 → 0.4.0.0
raw patch · 10 files changed
+175/−41 lines, 10 filesdep +containersdep +semigroupsdep +voiddep ~hspec-megaparsecdep ~megaparsecnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: containers, semigroups, void
Dependency ranges changed: hspec-megaparsec, megaparsec
API changes (from Hackage documentation)
+ Text.Inflections: humanizeCustom :: Bool -> [SomeWord] -> Text
+ Text.Inflections: toHumanized :: Bool -> Text -> Either (ParseError Char Void) Text
- Text.Inflections: InflectionParsingFailed :: (ParseError Char Dec) -> InflectionException
+ Text.Inflections: InflectionParsingFailed :: (ParseError Char Void) -> InflectionException
- Text.Inflections: betterThrow :: MonadThrow m => Either (ParseError Char Dec) a -> m a
+ Text.Inflections: betterThrow :: MonadThrow m => Either (ParseError Char Void) a -> m a
- Text.Inflections: parseCamelCase :: (Foldable f, Functor f) => f (Word Acronym) -> Text -> Either (ParseError Char Dec) [SomeWord]
+ Text.Inflections: parseCamelCase :: (Foldable f, Functor f) => f (Word Acronym) -> Text -> Either (ParseError Char Void) [SomeWord]
- Text.Inflections: parseSnakeCase :: (Foldable f, Functor f) => f (Word Acronym) -> Text -> Either (ParseError Char Dec) [SomeWord]
+ Text.Inflections: parseSnakeCase :: (Foldable f, Functor f) => f (Word Acronym) -> Text -> Either (ParseError Char Void) [SomeWord]
- Text.Inflections: toCamelCased :: Bool -> Text -> Either (ParseError Char Dec) Text
+ Text.Inflections: toCamelCased :: Bool -> Text -> Either (ParseError Char Void) Text
- Text.Inflections: toDashed :: Text -> Either (ParseError Char Dec) Text
+ Text.Inflections: toDashed :: Text -> Either (ParseError Char Void) Text
- Text.Inflections: toUnderscore :: Text -> Either (ParseError Char Dec) Text
+ Text.Inflections: toUnderscore :: Text -> Either (ParseError Char Void) Text
Files
- CHANGELOG.md +4/−0
- Text/Inflections.hs +34/−12
- Text/Inflections/Humanize.hs +24/−3
- Text/Inflections/Parse/CamelCase.hs +6/−3
- Text/Inflections/Parse/SnakeCase.hs +5/−2
- Text/Inflections/Titleize.hs +2/−2
- Text/Inflections/Types.hs +2/−1
- inflections.cabal +14/−4
- test/Text/Inflections/HumanizeSpec.hs +40/−13
- test/Text/InflectionsSpec.hs +44/−1
CHANGELOG.md view
@@ -1,3 +1,7 @@+## Inflections 0.4.0.0++* Update megaparsec to version 6.+ ## Inflections 0.3.0.0 * A more type-safe API forbidding creation of invalid words.
Text/Inflections.hs view
@@ -96,6 +96,7 @@ , camelizeCustom , dasherize , humanize+ , humanizeCustom , underscore , titleize , Transliterations@@ -110,15 +111,17 @@ , toUnderscore , toDashed , toCamelCased+ , toHumanized , betterThrow ) where import Control.Monad.Catch (MonadThrow (..)) import Data.Text (Text)+import Data.Void (Void) import Text.Inflections.Camelize (camelize, camelizeCustom) import Text.Inflections.Dasherize (dasherize) import Text.Inflections.Data (Transliterations, defaultTransliterations)-import Text.Inflections.Humanize (humanize)+import Text.Inflections.Humanize (humanize, humanizeCustom) import Text.Inflections.Ordinal (ordinal, ordinalize) import Text.Inflections.Parameterize (parameterize, parameterizeCustom) import Text.Inflections.Parse.CamelCase (parseCamelCase)@@ -139,7 +142,7 @@ -- -- >>> toUnderscore "FooBarBazz" -- "foo_bar_bazz"-toUnderscore :: Text -> Either (ParseError Char Dec) Text+toUnderscore :: Text -> Either (ParseError Char Void) Text toUnderscore = fmap underscore . parseCamelCase [] -- | Transforms CamelCasedString to snake-cased-string-with-dashes.@@ -148,26 +151,45 @@ -- -- >>> toDashed "FooBarBazz" -- "foo-bar-bazz"-toDashed :: Text -> Either (ParseError Char Dec) Text+toDashed :: Text -> Either (ParseError Char Void) Text toDashed = fmap dasherize . parseCamelCase [] -- | Transforms underscored_text to CamelCasedText. If first argument is--- 'True' then FirstCharacter in result string will be in upper case. If--- 'False' then firstCharacter will be in lower case.+-- 'True' then the first character in the result string will be in upper case. If+-- 'False' then the first character will be in lower case. ----- > toCamelCased t = fmap (camelizeCustom t) . parseSnakeCase []+-- > toCamelCased c = fmap (camelizeCustom c) . parseSnakeCase [] -- -- >>> toCamelCased True "foo_bar_bazz" -- "FooBarBazz" -- >>> toCamelCased False "foo_bar_bazz" -- "fooBarBazz" toCamelCased- :: Bool -- ^ Capitalize the first character- -> Text -- ^ Input- -> Either (ParseError Char Dec) Text -- ^ Ouput-toCamelCased t = fmap (camelizeCustom t) . parseSnakeCase []+ :: Bool -- ^ Capitalize the first character+ -> Text -- ^ Input+ -> Either (ParseError Char Void) Text -- ^ Output+toCamelCased c = fmap (camelizeCustom c) . parseSnakeCase [] --- | Lift something of type @'Either' ('ParseError' 'Char' 'Dec') a@ to+-- | Transforms underscored_text to space-separated human-readable text.+-- If first argument is 'True' then the first character in the result+-- string will be in upper case. If 'False' then the first character will be+-- in lower case.+--+-- > toHumanized c = fmap (humanizeCustom c) . parseSnakeCase []+--+-- >>> toHumanized True "foo_bar_bazz"+-- "Foo bar bazz"+-- >>> toHumanized False "foo_bar_bazz"+-- "foo bar bazz"+--+-- /since 0.3.0.0/+toHumanized+ :: Bool -- ^ Capitalize the first character+ -> Text -- ^ Input+ -> Either (ParseError Char Void) Text -- ^ Output+toHumanized c = fmap (humanizeCustom c) . parseSnakeCase []++-- | Lift something of type @'Either' ('ParseError' 'Char' 'Void') a@ to -- an instance of 'MonadThrow'. Useful when you want to shortcut on parsing -- failures and you're in an instance of 'MonadThrow'. --@@ -175,6 +197,6 @@ -- -- /since 0.3.0.0/ -betterThrow :: MonadThrow m => Either (ParseError Char Dec) a -> m a+betterThrow :: MonadThrow m => Either (ParseError Char Void) a -> m a betterThrow (Left err) = throwM (InflectionParsingFailed err) betterThrow (Right x) = return x
Text/Inflections/Humanize.hs view
@@ -13,7 +13,8 @@ {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.Humanize- ( humanize )+ ( humanize+ , humanizeCustom ) where import Data.Text (Text)@@ -36,7 +37,27 @@ humanize :: [SomeWord] -- ^ List of words, first of which will be capitalized -> Text -- ^ The humanized output-humanize xs' =+humanize = humanizeCustom True+++-- | Separate words with spaces, optionally capitalizing the first word. Like+-- 'Text.Inflections.Titleize.titleize', this is meant for creating pretty+-- output.+--+-- >>> foo <- SomeWord <$> mkWord "foo"+-- >>> bar <- SomeWord <$> mkAcronym "bar"+-- >>> bazz <- SomeWord <$> mkWord "bazz"+-- >>> humanizeCustom True [foo,bar,bazz]+-- "Foo bar bazz"+-- >>> humanizeCustom False [foo,bar,bazz]+-- "foo bar bazz"+--+-- /since 0.3.0.0/+humanizeCustom+ :: Bool -- ^ Whether to capitalize the first character in the output String+ -> [SomeWord] -- ^ List of words, first of which will be capitalized+ -> Text -- ^ The humanized output+humanizeCustom c xs' = case unSomeWord (T.replace "_" " ") <$> xs' of [] -> ""- (x:xs) -> T.unwords $ T.toTitle x : (T.toLower <$> xs)+ (x:xs) -> T.unwords $ (if c then T.toTitle else T.toLower) x : (T.toLower <$> xs)
Text/Inflections/Parse/CamelCase.hs view
@@ -19,9 +19,10 @@ import Control.Applicative import Data.Text (Text)+import Data.Void (Void) import Text.Inflections.Types import Text.Megaparsec-import Text.Megaparsec.Text+import Text.Megaparsec.Char import qualified Data.Text as T #if MIN_VERSION_base(4,8,0)@@ -31,6 +32,8 @@ import Prelude hiding (elem) #endif +type Parser = Parsec Void Text+ -- | Parse a CamelCase string. -- -- >>> bar <- mkAcronym "bar"@@ -44,7 +47,7 @@ parseCamelCase :: (Foldable f, Functor f) => f (Word 'Acronym) -- ^ Collection of acronyms -> Text -- ^ Input- -> Either (ParseError Char Dec) [SomeWord] -- ^ Result of parsing+ -> Either (ParseError Char Void) [SomeWord] -- ^ Result of parsing parseCamelCase acronyms = parse (parser acronyms) "" parser :: (Foldable f, Functor f)@@ -59,7 +62,7 @@ => f (Word 'Acronym) -> Parser (Word 'Acronym) acronym acronyms = do- x <- T.pack <$> choice (string . T.unpack . unWord <$> acronyms)+ x <- choice (string . unWord <$> acronyms) case mkAcronym x of Nothing -> empty -- cannot happen if the system is sound Just acr -> return acr
Text/Inflections/Parse/SnakeCase.hs view
@@ -18,9 +18,10 @@ import Control.Applicative import Data.Text (Text)+import Data.Void (Void) import Text.Inflections.Types import Text.Megaparsec-import Text.Megaparsec.Text+import Text.Megaparsec.Char import qualified Data.Text as T #if MIN_VERSION_base(4,8,0)@@ -30,6 +31,8 @@ import Prelude hiding (elem) #endif +type Parser = Parsec Void Text+ -- | Parse a snake_case string. -- -- >>> bar <- mkAcronym "bar"@@ -43,7 +46,7 @@ parseSnakeCase :: (Foldable f, Functor f) => f (Word 'Acronym) -- ^ Collection of acronyms -> Text -- ^ Input- -> Either (ParseError Char Dec) [SomeWord] -- ^ Result of parsing+ -> Either (ParseError Char Void) [SomeWord] -- ^ Result of parsing parseSnakeCase acronyms = parse (parser acronyms) "" parser :: (Foldable f, Functor f)
Text/Inflections/Titleize.hs view
@@ -17,7 +17,7 @@ import Text.Inflections.Types import qualified Data.Text as T --- | Capitalize all the Words in the input list.+-- | Capitalize all the 'SomeWord' words in the input list. -- -- >>> foo <- SomeWord <$> mkWord "foo" -- >>> bar <- SomeWord <$> mkAcronym "bar"@@ -25,6 +25,6 @@ -- >>> titleize [foo,bar,bazz] -- "Foo bar Bazz" titleize- :: [SomeWord] -- ^ List of words, first of which will be capitalized+ :: [SomeWord] -- ^ List of words, of which all 'SomeWord' words will be capitalized and all acronyms will be left as is -> Text -- ^ The titleized 'Text' titleize = T.unwords . fmap (unSomeWord T.toTitle)
Text/Inflections/Types.hs view
@@ -33,6 +33,7 @@ import Control.Monad.Catch import Data.Char (isAlphaNum) import Data.Data (Data)+import Data.Void (Void) import Data.Text (Text) import Data.Typeable (Typeable) import GHC.Generics (Generic)@@ -135,7 +136,7 @@ -- /since 0.3.0.0/ data InflectionException- = InflectionParsingFailed (ParseError Char Dec)+ = InflectionParsingFailed (ParseError Char Void) | InflectionInvalidWord Text | InflectionInvalidAcronym Text deriving (Eq, Show, Typeable, Data, Generic)
inflections.cabal view
@@ -1,5 +1,5 @@ name: inflections-version: 0.3.0.0+version: 0.4.0.0 synopsis: Inflections library for Haskell description: Inflections provides methods for singularization, pluralization,@@ -49,9 +49,12 @@ ghc-options: -O2 -Wall build-depends: base >= 4.6 && < 5.0 , exceptions >= 0.6 && < 0.9- , megaparsec >= 5.0 && < 6.0+ , megaparsec >= 6.0 && < 7.0 , text >= 0.2 && < 1.3 , unordered-containers >= 0.2.7 && < 0.3+ if !impl(ghc >= 7.10)+ build-depends: void == 0.7.*+ default-language: Haskell2010 test-suite test@@ -61,10 +64,17 @@ build-depends: inflections , QuickCheck >= 2.7.6 && < 3.0 , base >= 4.6 && < 5.0+ , containers >= 0.5 && < 0.7 , hspec >= 2.0 && < 3.0- , hspec-megaparsec >= 0.3 && < 0.4- , megaparsec >= 5.1 && < 6.0+ , hspec-megaparsec >= 1.0 && < 2.0+ , megaparsec , text >= 0.2 && < 1.3+ if !impl(ghc >= 7.10)+ build-depends: void == 0.7.*++ if !impl(ghc >= 8.0)+ build-depends: semigroups == 0.18.*+ if flag(dev) ghc-options: -Wall -Werror else
test/Text/Inflections/HumanizeSpec.hs view
@@ -12,16 +12,43 @@ #endif spec :: Spec-spec = describe "humazine" $ do- it "converts snake case to a human-readable string" $ do- employee <- SomeWord <$> mkWord "employee"- salary <- SomeWord <$> mkWord "salary"- humanize [employee,salary] `shouldBe` "Employee salary"- it "turns underscores into spaces" $ do- employee <- SomeWord <$> mkWord "employee"- has <- SomeWord <$> mkWord "has"- salary <- SomeWord <$> mkWord "salary"- humanize [employee, has, salary] `shouldBe` "Employee has salary"- it "capitalizes the first word of a sentence" $ do- underground <- SomeWord <$> mkWord "underground"- humanize [underground] `shouldBe` "Underground"+spec = do+ describe "humanize" $ do+ it "converts snake case to a human-readable string" $ do+ employee <- SomeWord <$> mkWord "employee"+ salary <- SomeWord <$> mkWord "salary"+ humanize [employee,salary] `shouldBe` "Employee salary"+ it "turns underscores into spaces" $ do+ employee <- SomeWord <$> mkWord "employee"+ has <- SomeWord <$> mkWord "has"+ salary <- SomeWord <$> mkWord "salary"+ humanize [employee, has, salary] `shouldBe` "Employee has salary"+ it "capitalizes the first word of a sentence" $ do+ underground <- SomeWord <$> mkWord "underground"+ humanize [underground] `shouldBe` "Underground"+ describe "humanizeCustom False" $ do+ it "converts snake case to a human-readable string" $ do+ employee <- SomeWord <$> mkWord "employee"+ salary <- SomeWord <$> mkWord "salary"+ humanizeCustom False [employee,salary] `shouldBe` "employee salary"+ it "turns underscores into spaces" $ do+ employee <- SomeWord <$> mkWord "employee"+ has <- SomeWord <$> mkWord "has"+ salary <- SomeWord <$> mkWord "salary"+ humanizeCustom False [employee, has, salary] `shouldBe` "employee has salary"+ it "lower-cases the first word of a sentence" $ do+ underground <- SomeWord <$> mkWord "underground"+ humanizeCustom False [underground] `shouldBe` "underground"+ describe "humanizeCustom True" $ do+ it "converts snake case to a human-readable string" $ do+ employee <- SomeWord <$> mkWord "employee"+ salary <- SomeWord <$> mkWord "salary"+ humanizeCustom True [employee,salary] `shouldBe` "Employee salary"+ it "turns underscores into spaces" $ do+ employee <- SomeWord <$> mkWord "employee"+ has <- SomeWord <$> mkWord "has"+ salary <- SomeWord <$> mkWord "salary"+ humanizeCustom True [employee, has, salary] `shouldBe` "Employee has salary"+ it "capitalizes the first word of a sentence" $ do+ underground <- SomeWord <$> mkWord "underground"+ humanizeCustom True [underground] `shouldBe` "Underground"
test/Text/InflectionsSpec.hs view
@@ -1,11 +1,45 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.InflectionsSpec (spec) where +import Data.Void import Test.Hspec import Test.QuickCheck import Text.Inflections+import Text.Megaparsec +import qualified Data.List.NonEmpty as NE+import qualified Data.Set as S++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative+#endif++arbitraryParseError :: Gen (ParseError Char Void)+arbitraryParseError = oneof [trivialError, fancyError]+ where+ trivialError = TrivialError <$> nonEmptyArbitrary <*> maybeErrorItem <*> setErrorItem+ fancyError = FancyError <$> nonEmptyArbitrary <*> setErrorFancy+ nonEmptyArbitrary = NE.fromList <$> listOf1 arbitrarySourcePos+ setErrorFancy = S.fromList <$> listOf arbitraryErrorFancy+ maybeErrorItem = oneof [ Just <$> arbitraryErrorItem, return Nothing]+ setErrorItem = S.fromList <$> listOf arbitraryErrorItem++arbitrarySourcePos :: Gen SourcePos+arbitrarySourcePos = SourcePos <$> arbitrary <*> posArbitrary <*> posArbitrary+ where+ posArbitrary = mkPos <$> ((+1) . abs <$> arbitrary)++arbitraryErrorFancy :: Gen (ErrorFancy e)+arbitraryErrorFancy = oneof [ ErrorFail <$> arbitrary ]++arbitraryErrorItem :: (Arbitrary e) => Gen (ErrorItem e)+arbitraryErrorItem = oneof [ tokens_, labels_, return EndOfInput ]+ where+ tokens_ = Tokens <$> (NE.fromList <$> listOf1 arbitrary)+ labels_ = Label <$> (NE.fromList <$> listOf1 arbitrary)+ spec :: Spec spec = do @@ -27,12 +61,21 @@ it "converts snake case to camel case with the first word capitalized" $ toCamelCased True "underscored_text" `shouldBe` Right "UnderscoredText" + describe "toHumanized" $ do+ context "when the first argument is False" $+ it "converts snake case to human-readable form with lower-case initial letter" $+ toHumanized False "underscored_text" `shouldBe` Right "underscored text"+ context "when the first argument is True" $+ it "converts snake case to human-readable form with the first word capitalized" $+ toHumanized True "underscored_text" `shouldBe` Right "Underscored text"+ describe "betterThrow" $ do context "when given a parse error" $ it "throws the correct exception" $- property $ \err ->+ property $ forAll arbitraryParseError $ \err -> betterThrow (Left err) `shouldThrow` (== InflectionParsingFailed err)+ context "when given a value in Right" $ it "returns the value" $ property $ \x ->