diff --git a/.travis.yml b/.travis.yml index 7c81bb2..9b7d724 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ script: *) cabal test --show-details=always ;; esac - cabal sdist - - cabal haddock | grep "100%" | wc -l | grep "14" + - cabal haddock | grep "100%" | wc -l | grep "13" # after_script: # - cabal install hpc-coveralls diff --git a/Text/Inflections.hs b/Text/Inflections.hs index 6c7e814..cebcfde 100644 --- a/Text/Inflections.hs +++ b/Text/Inflections.hs @@ -71,36 +71,26 @@ code or bug reports: -} module Text.Inflections - ( camelize - , camelizeCustom - - , dasherize - - , humanize - - , underscore - - , titleize - - , Transliterations - , defaultMap - - , parameterize - , parameterizeCustom - - , transliterate - , transliterateCustom - - , ordinal - , ordinalize - - , parseSnakeCase - , parseCamelCase + ( camelize + , camelizeCustom + , dasherize + , humanize + , underscore + , titleize + , Transliterations + , defaultMap + , parameterize + , parameterizeCustom + , transliterate + , transliterateCustom + , ordinal + , ordinalize + , parseSnakeCase + , parseCamelCase -- * Often used combinators - , toUnderscore - , toDashed - , toCamelCased - ) + , toUnderscore + , toDashed + , toCamelCased ) where import Control.Monad (liftM) @@ -114,9 +104,9 @@ import Text.Inflections.Ordinal (ordinal, ordinalize) import Text.Inflections.Parameterize (parameterize, parameterizeCustom) import Text.Inflections.Parse.CamelCase (parseCamelCase) import Text.Inflections.Parse.SnakeCase (parseSnakeCase) -import Text.Inflections.Parse.Types import Text.Inflections.Titleize (titleize) import Text.Inflections.Transliterate (transliterate, transliterateCustom) +import Text.Inflections.Types import Text.Inflections.Underscore (underscore) import Text.Megaparsec diff --git a/Text/Inflections/Camelize.hs b/Text/Inflections/Camelize.hs index 5991524..bb80524 100644 --- a/Text/Inflections/Camelize.hs +++ b/Text/Inflections/Camelize.hs @@ -18,34 +18,30 @@ module Text.Inflections.Camelize where import Data.Text (Text) -import Text.Inflections.Parse.Types +import Text.Inflections.Types import qualified Data.Text as T -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#else +#if !MIN_VERSION_base(4,8,0) import Control.Applicative #endif --- |Turns a an input Word List in into CamelCase. Returns the CamelCase String. +-- | Turn an input word list in into CamelCase. -- -- >>> camelize [ Word "foo", Acronym "bar", Word "bazz" ] -- "FoobarBazz" camelize - :: [Word] -- ^ Input Words to separate with underscores - -> Text -- ^ The camelized 'Text' + :: [SomeWord] -- ^ Input words + -> Text -- ^ The camelized 'Text' camelize = camelizeCustom True -{-# INLINE camelize #-} --- |Turns an input Word List into a CamelCase String. +-- | Turn an input word list into a CamelCase String. -- -- >>> camelizeCustom False [ Word "foo", Acronym "bar", Word "bazz" ] -- "foobarBazz" camelizeCustom - :: Bool -- ^ Whether to capitalize the first character in the output String - -> [Word] -- ^ The input Words - -> Text -- ^ The camelized 'Text' + :: Bool -- ^ Whether to capitalize the first character in the output String + -> [SomeWord] -- ^ The input Words + -> Text -- ^ The camelized 'Text' camelizeCustom _ [] = "" camelizeCustom c (x:xs) = T.concat $ - mapWord (if c then T.toTitle else T.toLower) x : (mapWord T.toTitle <$> xs) -{-# INLINE camelizeCustom #-} + unSomeWord (if c then T.toTitle else T.toLower) x : (unSomeWord T.toTitle <$> xs) diff --git a/Text/Inflections/Dasherize.hs b/Text/Inflections/Dasherize.hs index 4746e96..8b46aa8 100644 --- a/Text/Inflections/Dasherize.hs +++ b/Text/Inflections/Dasherize.hs @@ -9,25 +9,24 @@ -- -- Conversion to dasherized phrases. -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} -module Text.Inflections.Dasherize ( dasherize ) where +module Text.Inflections.Dasherize + ( dasherize ) +where import Data.Text (Text) -import Text.Inflections.Parse.Types +import Text.Inflections.Types import qualified Data.Text as T -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#endif - -- | Replaces underscores in a snake_cased string with dashes (hyphens). -- --- >>> dasherize [ Word "foo", Acronym "bar", Word "bazz" ] +-- >>> foo <- SomeWord <$> mkWord "foo" +-- >>> bar <- SomeWord <$> mkAcronym "bar" +-- >>> bazz <- SomeWord <$> mkWord "bazz" +-- >>> dasherize [foo,bar,bazz] -- "foo-bar-bazz" dasherize - :: [Word] -- ^ Input Words to separate with dashes - -> Text -- ^ The dasherized String -dasherize = T.intercalate "-" . fmap (mapWord T.toLower) -{-# INLINE dasherize #-} + :: [SomeWord] -- ^ Input Words to separate with dashes + -> Text -- ^ The dasherized String +dasherize = T.intercalate "-" . fmap (unSomeWord T.toLower) diff --git a/Text/Inflections/Humanize.hs b/Text/Inflections/Humanize.hs index e25765d..6defa50 100644 --- a/Text/Inflections/Humanize.hs +++ b/Text/Inflections/Humanize.hs @@ -17,12 +17,10 @@ module Text.Inflections.Humanize where import Data.Text (Text) -import Text.Inflections.Parse.Types +import Text.Inflections.Types import qualified Data.Text as T -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#else +#if !MIN_VERSION_base(4,8,0) import Control.Applicative #endif @@ -30,13 +28,15 @@ import Control.Applicative -- 'Text.Inflections.Titleize.titleize', this is meant for creating pretty -- output. -- --- >>> humanize [ Word "foo", Acronym "bar", Word "bazz" ] +-- >>> humanize [Word "foo", Acronym "bar", Word "bazz"] -- "Foo bar bazz" +-- +-- Note that as of version 0.3.0.0 @Word@ and @Acronym@ constructors are +-- hidden, but you still can construct them with 'mkWord' and 'mkAcronym'. humanize - :: [Word] -- ^ List of Words, first of which will be capitalized - -> Text -- ^ The humanized output + :: [SomeWord] -- ^ List of Words, first of which will be capitalized + -> Text -- ^ The humanized output humanize xs' = - case mapWord (T.replace "_" " ") <$> xs' of + case unSomeWord (T.replace "_" " ") <$> xs' of [] -> "" (x:xs) -> T.unwords $ T.toTitle x : (T.toLower <$> xs) -{-# INLINE humanize #-} diff --git a/Text/Inflections/Parse/Acronym.hs b/Text/Inflections/Parse/Acronym.hs deleted file mode 100644 index cadf723..0000000 --- a/Text/Inflections/Parse/Acronym.hs +++ /dev/null @@ -1,32 +0,0 @@ --- | --- Module : Text.Inflections.Parse.Acronym --- Copyright : © 2016 Justin Leitgeb --- License : MIT --- --- Maintainer : Justin Leitgeb --- Stability : experimental --- Portability : portable --- --- Parser for acronyms. - -{-# LANGUAGE CPP #-} - -module Text.Inflections.Parse.Acronym - ( acronym ) -where - -import Data.Text (Text) -import Text.Inflections.Parse.Types -import Text.Megaparsec -import Text.Megaparsec.Text -import qualified Data.Text as T - -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#endif - --- | Parser that accepts a 'Text' from given collection and turns it into --- an 'Acronym'. -acronym :: [Text] -> Parser Word -acronym = fmap (Acronym . T.pack) . choice . fmap (string . T.unpack) -{-# INLINE acronym #-} diff --git a/Text/Inflections/Parse/CamelCase.hs b/Text/Inflections/Parse/CamelCase.hs index 6ef5571..fcb4663 100644 --- a/Text/Inflections/Parse/CamelCase.hs +++ b/Text/Inflections/Parse/CamelCase.hs @@ -10,26 +10,25 @@ -- Parser for camel case “symbols”. {-# LANGUAGE CPP #-} +{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.Parse.CamelCase ( parseCamelCase ) where +import Control.Applicative import Data.Text (Text) -import Text.Inflections.Parse.Acronym (acronym) -import Text.Inflections.Parse.Types (Word(..)) +import Text.Inflections.Types import Text.Megaparsec import Text.Megaparsec.Text import qualified Data.Text as T #if MIN_VERSION_base(4,8,0) import Prelude hiding (Word) -#else -import Control.Applicative #endif --- |Parse a CamelCase string. +-- | Parse a CamelCase string. -- -- >>> parseCamelCase ["Bar"] "FooBarBazz" -- Right [Word "Foo",Acronym "Bar",Word "Bazz"] @@ -37,20 +36,32 @@ import Control.Applicative -- Left "(unknown)" (line 1, column 4): -- unexpected '_' parseCamelCase - :: [Text] -- ^ Collection of acronyms - -> Text -- ^ Input - -> Either (ParseError Char Dec) [Word] -- ^ Result of parsing + :: [Word 'Acronym] -- ^ Collection of acronyms + -> Text -- ^ Input + -> Either (ParseError Char Dec) [SomeWord] -- ^ Result of parsing parseCamelCase acronyms = parse (parser acronyms) "" parser - :: [Text] -- ^ Collection of acronyms - -> Parser [Word] -- ^ CamelCase parser -parser acronyms = many (acronym acronyms <|> word) <* eof -{-# INLINE parser #-} + :: [Word 'Acronym] -- ^ Collection of acronyms + -> Parser [SomeWord] -- ^ CamelCase parser +parser acronyms = many (a <|> n) <* eof + where + n = SomeWord <$> word + a = SomeWord <$> acronym acronyms -word :: Parser Word +acronym :: [Word 'Acronym] -> Parser (Word 'Acronym) +acronym acronyms = do + x <- T.pack <$> choice (string . T.unpack . unWord <$> acronyms) + case mkAcronym x of + Nothing -> empty -- cannot happen if the system is sound + Just acr -> return acr +{-# INLINE acronym #-} + +word :: Parser (Word 'Normal) word = do firstChar <- upperChar <|> lowerChar restChars <- many $ lowerChar <|> digitChar - return . Word . T.pack $ firstChar : restChars + case (mkWord . T.pack) (firstChar : restChars) of + Nothing -> empty -- cannot happen if the system is sound + Just wrd -> return wrd {-# INLINE word #-} diff --git a/Text/Inflections/Parse/SnakeCase.hs b/Text/Inflections/Parse/SnakeCase.hs index 0d9b207..ae01ce2 100644 --- a/Text/Inflections/Parse/SnakeCase.hs +++ b/Text/Inflections/Parse/SnakeCase.hs @@ -9,47 +9,59 @@ -- -- Parser for snake case “symbols”. -{-# LANGUAGE CPP #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE DataKinds #-} module Text.Inflections.Parse.SnakeCase ( parseSnakeCase ) where +import Control.Applicative import Data.Text (Text) -import Text.Inflections.Parse.Acronym (acronym) -import Text.Inflections.Parse.Types (Word(..)) +import Text.Inflections.Types import Text.Megaparsec import Text.Megaparsec.Text import qualified Data.Text as T #if MIN_VERSION_base(4,8,0) import Prelude hiding (Word) -#else -import Control.Applicative #endif --- |Parses a snake_case string. +-- | Parse a snake_case string. -- --- >>> parseSnakeCase ["bar"] "foo_bar_bazz" +-- >>> bar <- mkAcronym "bar" +-- >>> parseSnakeCase [bar] "foo_bar_bazz" -- Right [Word "foo",Acronym "bar",Word "bazz"] +-- -- >>> parseSnakeCase [] "fooBarBazz" -- Left "(unknown)" (line 1, column 4): -- unexpected 'B' parseSnakeCase - :: [Text] -- ^ Collection of acronyms + :: [Word 'Acronym] -- ^ Collection of acronyms -> Text -- ^ Input - -> Either (ParseError Char Dec) [Word] -- ^ Result of parsing + -> Either (ParseError Char Dec) [SomeWord] -- ^ Result of parsing parseSnakeCase acronyms = parse (parser acronyms) "" parser - :: [Text] - -> Parser [Word] -parser acronyms = do - ws <- (acronym acronyms <|> word) `sepBy` char '_' - eof - return ws -{-# INLINE parser #-} + :: [Word 'Acronym] + -> Parser [SomeWord] +parser acronyms = ((a <|> n) `sepBy` char '_') <* eof + where + n = SomeWord <$> word + a = SomeWord <$> acronym acronyms -word :: Parser Word -word = Word . T.pack <$> (some lowerChar <|> some digitChar) +acronym :: [Word 'Acronym] -> Parser (Word 'Acronym) +acronym acronyms = do + x <- T.pack <$> choice (string . T.unpack . unWord <$> acronyms) + case mkAcronym x of + Nothing -> empty -- cannot happen if the system is sound + Just acr -> return acr +{-# INLINE acronym #-} + +word :: Parser (Word 'Normal) +word = do + x <- T.pack <$> (some lowerChar <|> some digitChar) + case mkWord x of + Nothing -> empty -- cannot happen if the system is sound + Just wrd -> return wrd {-# INLINE word #-} diff --git a/Text/Inflections/Parse/Types.hs b/Text/Inflections/Parse/Types.hs deleted file mode 100644 index 7951e28..0000000 --- a/Text/Inflections/Parse/Types.hs +++ /dev/null @@ -1,54 +0,0 @@ --- | --- Module : Text.Inflections.Parse.Types --- Copyright : © 2016 Justin Leitgeb --- License : MIT --- --- Maintainer : Justin Leitgeb --- Stability : experimental --- Portability : portable --- --- Types used in the library. - -{-# LANGUAGE CPP #-} -{-# LANGUAGE DeriveDataTypeable #-} - -module Text.Inflections.Parse.Types - ( Word (..) -- FIXME we should not export the constructor - , unWord - , mapWord - , InflectionException (..) ) -where - -import Control.Monad.Catch (Exception) -import Data.Text (Text) -import Data.Typeable (Typeable) -import Text.Megaparsec - -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#endif - --- | A 'String' that should be kept whole through applied inflections -data Word - = Word Text -- ^ A word that may be transformed by inflection - | Acronym Text -- ^ A word that may not be transformed by inflections - deriving (Show, Eq) - --- | Get a 'Text' value from 'Word'. -unWord :: Word -> Text -unWord (Word s) = s -unWord (Acronym s) = s -{-# INLINE unWord #-} - --- | Apply 'Text' transforming function to a 'Word' unless it's a 'Acronym'. -mapWord :: (Text -> Text) -> Word -> Text -mapWord f (Word s) = f s -mapWord _ (Acronym s) = s -{-# INLINE mapWord #-} - --- | The exceptions that is thrown when parsing of input fails. - -data InflectionException = InflectionParsingFailed (ParseError Char Dec) - deriving (Eq, Show, Typeable) - -instance Exception InflectionException diff --git a/Text/Inflections/Titleize.hs b/Text/Inflections/Titleize.hs index ee6429b..8f0d4d0 100644 --- a/Text/Inflections/Titleize.hs +++ b/Text/Inflections/Titleize.hs @@ -9,26 +9,19 @@ -- -- Conversion to titleized phrases. -{-# LANGUAGE CPP #-} - module Text.Inflections.Titleize ( titleize ) where import Data.Text (Text) -import Text.Inflections.Parse.Types +import Text.Inflections.Types import qualified Data.Text as T -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#endif - -- | Capitalize all the Words in the input list. -- -- >>> titleize [ Word "foo", Acronym "bar", Word "bazz" ] -- "Foo bar Bazz" titleize - :: [Word] -- ^ List of Words, first of which will be capitalized - -> Text -- ^ The titleized String -titleize = T.unwords . fmap (mapWord T.toTitle) -{-# INLINE titleize #-} + :: [SomeWord] -- ^ List of Words, first of which will be capitalized + -> Text -- ^ The titleized String +titleize = T.unwords . fmap (unSomeWord T.toTitle) diff --git a/Text/Inflections/Types.hs b/Text/Inflections/Types.hs new file mode 100644 index 0000000..ca183a8 --- /dev/null +++ b/Text/Inflections/Types.hs @@ -0,0 +1,122 @@ +-- | +-- Module : Text.Inflections.Types +-- Copyright : © 2016 Justin Leitgeb +-- License : MIT +-- +-- Maintainer : Justin Leitgeb +-- Stability : experimental +-- Portability : portable +-- +-- Types used in the library. Usually you don't need to import this module +-- and "Text.Inflections" should be enough. + +{-# LANGUAGE CPP #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} + +module Text.Inflections.Types + ( Word + , WordType (..) + , mkWord + , mkAcronym + , unWord + , SomeWord (..) + , unSomeWord + , InflectionException (..) ) +where + +import Control.Monad.Catch +import Data.Char (isSpace) +import Data.Data (Data) +import Data.Text (Text) +import Data.Typeable (Typeable) +import GHC.Generics (Generic) +import Text.Megaparsec +import qualified Data.Text as T + +#if MIN_VERSION_base(4,8,0) +import Prelude hiding (Word) +#endif + +-- | Create a word from given 'Text'. The input should not contain spaces or +-- 'InflectionInvalidWord' will be thrown. + +mkWord :: MonadThrow m => Text -> m (Word 'Normal) +mkWord txt = + if T.any isSpace txt + then throwM (InflectionInvalidWord txt) + else return (Word txt) + +-- | Create an acronym from given 'Text'. The input should not contain +-- spaces or 'InflectionInvalidAcronym' will be thrown. Acronym is different +-- from normal word by that it may not be transformed by inflections. + +mkAcronym :: MonadThrow m => Text -> m (Word 'Acronym) +mkAcronym txt = + if T.any isSpace txt + then throwM (InflectionInvalidAcronym txt) + else return (Word txt) + +-- | A 'Text' value that should be kept whole through applied inflections. +data Word (t :: WordType) = Word Text + deriving (Eq, Ord, Show) + +instance Show (Word 'Normal) where + show (Word x) = "Word " ++ show x + +instance Show (Word 'Acronym) where + show (Word x) = "Acronym " ++ show x + +-- | A type-level tag for words. + +data WordType = Normal | Acronym + +-- | Get a 'Text' value from 'Word'. +unWord :: Word t -> Text +unWord (Word s) = s + +-- | An existential wrapper that allows to keep words and acronyms in single +-- list for example. The only thing that receiver of 'SomeWord' can do is to +-- apply 'unWord' on it, of course. This is faciliated by 'unSomeWord'. + +data SomeWord where + SomeWord :: Transformable (Word t) => Word t -> SomeWord + -- NOTE The constraint is only needed because GHC is not smart enough + -- (yet?) to figure out that t cannot be anything other than Normal and + -- Acronym and thus all cases are already covered by the instances + -- provided below. + +instance Show SomeWord where + show (SomeWord w) = show w + +-- | Extract 'Text' from 'SomeWord' and apply given function only if the +-- word inside wasn't an acronym. + +unSomeWord :: (Text -> Text) -> SomeWord -> Text +unSomeWord f (SomeWord w) = transform f w + +-- | Non public stuff. + +class Transformable a where + transform :: (Text -> Text) -> a -> Text + +instance Transformable (Word 'Normal) where + transform f = f . unWord + +instance Transformable (Word 'Acronym) where + transform _ = unWord + +-- | The exceptions that is thrown when parsing of input fails. + +data InflectionException + = InflectionParsingFailed (ParseError Char Dec) + | InflectionInvalidWord Text + | InflectionInvalidAcronym Text + deriving (Eq, Show, Typeable, Data, Generic) + +instance Exception InflectionException diff --git a/Text/Inflections/Underscore.hs b/Text/Inflections/Underscore.hs index b965bd1..3f80fce 100644 --- a/Text/Inflections/Underscore.hs +++ b/Text/Inflections/Underscore.hs @@ -9,7 +9,6 @@ -- -- Conversion to phrases separated by underscores. -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.Underscore @@ -17,19 +16,14 @@ module Text.Inflections.Underscore where import Data.Text (Text) -import Text.Inflections.Parse.Types +import Text.Inflections.Types import qualified Data.Text as T -#if MIN_VERSION_base(4,8,0) -import Prelude hiding (Word) -#endif - -- |Turns a CamelCase string into an underscore_separated 'Text'. -- -- >>> underscore [ Word "foo", Acronym "bar", Word "bazz" ] -- "foo_bar_bazz" underscore - :: [Word] -- ^ Input Words to separate with underscores - -> Text -- ^ The underscored String -underscore = T.intercalate "_" . fmap (mapWord T.toLower) -{-# INLINE underscore #-} + :: [SomeWord] -- ^ Input Words to separate with underscores + -> Text -- ^ The underscored String +underscore = T.intercalate "_" . fmap (unSomeWord T.toLower) diff --git a/inflections.cabal b/inflections.cabal index c8f3451..c21a1fd 100644 --- a/inflections.cabal +++ b/inflections.cabal @@ -29,7 +29,7 @@ flag dev library exposed-modules: Text.Inflections - , Text.Inflections.Parse.Types + , Text.Inflections.Types other-modules: Text.Inflections.Data , Text.Inflections.Camelize @@ -37,7 +37,6 @@ library , Text.Inflections.Humanize , Text.Inflections.Ordinal , Text.Inflections.Parameterize - , Text.Inflections.Parse.Acronym , Text.Inflections.Parse.CamelCase , Text.Inflections.Parse.SnakeCase , Text.Inflections.Titleize diff --git a/test/Text/Inflections/DasherizeSpec.hs b/test/Text/Inflections/DasherizeSpec.hs index 7c5f7ea..050629c 100644 --- a/test/Text/Inflections/DasherizeSpec.hs +++ b/test/Text/Inflections/DasherizeSpec.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.DasherizeSpec @@ -7,9 +8,15 @@ where import Test.Hspec import Text.Inflections (dasherize) -import Text.Inflections.Parse.Types (Word (..)) +import Text.Inflections.Types + +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative +#endif spec :: Spec spec = describe "dasherize" $ - it "dasherizes a collection of words sentence" $ - dasherize [Word "foo", Word "bar"] `shouldBe` "foo-bar" + it "dasherizes a collection of words sentence" $ do + foo <- SomeWord <$> mkWord "foo" + bar <- SomeWord <$> mkWord "bar" + dasherize [foo,bar] `shouldBe` "foo-bar" diff --git a/test/Text/Inflections/HumanizeSpec.hs b/test/Text/Inflections/HumanizeSpec.hs index 3f36e30..7b742c7 100644 --- a/test/Text/Inflections/HumanizeSpec.hs +++ b/test/Text/Inflections/HumanizeSpec.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.HumanizeSpec (spec) where @@ -5,13 +6,22 @@ module Text.Inflections.HumanizeSpec (spec) where import Test.Hspec import Text.Inflections (humanize) -import Text.Inflections.Parse.Types (Word(..)) +import Text.Inflections.Types + +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative +#endif spec :: Spec spec = describe "humazine" $ do - it "converts snake case to a human-readable string" $ - humanize [Word "employee", Word "salary"] `shouldBe` "Employee salary" - it "turns underscores into spaces" $ - humanize [Word "employee", Word "has_salary"] `shouldBe` "Employee has salary" - it "capitalizes the first word of a sentence" $ - humanize [Word "underground"] `shouldBe` "Underground" + 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" + hasSalary <- SomeWord <$> mkWord "has_salary" + humanize [employee, hasSalary] `shouldBe` "Employee has salary" + it "capitalizes the first word of a sentence" $ do + underground <- SomeWord <$> mkWord "underground" + humanize [underground] `shouldBe` "Underground" diff --git a/test/Text/Inflections/TitleizeSpec.hs b/test/Text/Inflections/TitleizeSpec.hs index 82f7c68..4359ff2 100644 --- a/test/Text/Inflections/TitleizeSpec.hs +++ b/test/Text/Inflections/TitleizeSpec.hs @@ -1,15 +1,22 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.TitleizeSpec (spec) where import Test.Hspec - import Text.Inflections (titleize) -import Text.Inflections.Parse.Types (Word(..)) +import Text.Inflections.Types + +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative +#endif spec :: Spec spec = describe "titleize" $ do - it "converts two words to title case" $ - titleize [Word "Employee", Word "Salary"] `shouldBe` "Employee Salary" - it "converts one word to title case" $ - titleize [Word "underground"] `shouldBe` "Underground" + it "converts two words to title case" $ do + employee <- SomeWord <$> mkWord "Employee" + salary <- SomeWord <$> mkWord "Salary" + titleize [employee,salary] `shouldBe` "Employee Salary" + it "converts one word to title case" $ do + underground <- SomeWord <$> mkWord "underground" + titleize [underground] `shouldBe` "Underground" diff --git a/test/Text/Inflections/UnderscoreSpec.hs b/test/Text/Inflections/UnderscoreSpec.hs index eaaa705..c128299 100644 --- a/test/Text/Inflections/UnderscoreSpec.hs +++ b/test/Text/Inflections/UnderscoreSpec.hs @@ -1,12 +1,19 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Text.Inflections.UnderscoreSpec (spec) where import Test.Hspec import Text.Inflections (underscore) -import Text.Inflections.Parse.Types (Word(..)) +import Text.Inflections.Types + +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative +#endif spec :: Spec spec = describe "underscore" $ - it "converts a word list to snake case" $ - underscore [Word "test", Word "this"] `shouldBe` "test_this" + it "converts a word list to snake case" $ do + test <- SomeWord <$> mkWord "test" + this <- SomeWord <$> mkWord "this" + underscore [test, this] `shouldBe` "test_this"