packages feed

comma-and 0.1.0.1 → 0.2.0.0

raw patch · 5 files changed

+213/−63 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.Comma: CommaValues :: s -> s -> CommaValues s
+ Text.Comma: [commaAndText] :: CommaValues s -> s
+ Text.Comma: [commaText] :: CommaValues s -> s
+ Text.Comma: commaEmptyWith :: (IsString s, Semigroup s, Foldable f) => s -> CommaValues s -> f s -> s
+ Text.Comma: commaWith :: (IsString s, Monoid s, Foldable f) => CommaValues s -> f s -> s
+ Text.Comma: data CommaValues s
+ Text.Comma: instance Data.String.IsString s => Data.Default.Class.Default (Text.Comma.CommaValues s)
+ Text.Comma: instance GHC.Classes.Eq s => GHC.Classes.Eq (Text.Comma.CommaValues s)
+ Text.Comma: instance GHC.Classes.Ord s => GHC.Classes.Ord (Text.Comma.CommaValues s)
+ Text.Comma: instance GHC.Read.Read s => GHC.Read.Read (Text.Comma.CommaValues s)
+ Text.Comma: instance GHC.Show.Show s => GHC.Show.Show (Text.Comma.CommaValues s)
+ Text.Comma: toCommaValues :: IsString s => CommaStyle -> CommaValues s

Files

CHANGELOG.md view
@@ -2,6 +2,10 @@  Convert a list of items to text by adding commas and an "and" at the end. +## Version 0.2.0.0++Introducing `CommaValues` to allow working with different languages.+ ## Version 0.1.0.0  The first working version of `comma-and`.
README.md view
@@ -18,7 +18,7 @@  ## *String-like* types? -The package can work with types that are an instance of `IsString` and `Monoid`. So this means it works with `String`, `Text`, `ByteString`, `MarkupM`, and probably a lot more types that concatenate with the `Monoid` instance, and are an instance of `IsString`.+The package can work with types that are an instance of `IsString` and `Monoid`. So this means it works with `String`, [`Text`](https://hackage.haskell.org/package/text/docs/Data-Text-Internal-Lazy.html#t:Text), [`ByteString`](https://hackage.haskell.org/package/bytestring/docs/Data-ByteString.html#t:ByteString), [`MarkupM`](https://hackage.haskell.org/package/blaze-markup/docs/Text-Blaze-Internal.html#t:MarkupM), [`LaTeX`](https://hackage.haskell.org/package/HaTeX-3.22.4.2/docs/Text-LaTeX-Base-Syntax.html#t:LaTeX), and probably a lot more types that concatenate with the `Monoid` instance, and are an instance of `IsString`.  ## `comma-and` is *safe* Haskell 
comma-and.cabal view
@@ -1,7 +1,7 @@ name:                comma-and-version:             0.1.0.1+version:             0.2.0.0 synopsis: Join text together with commas, and "and".-description: Convert a 'Text' object into a visually pleasant URL component.+description: Join text together with commas, and "and". homepage:            https://github.com/hapytex/comma-and#readme license:             BSD3 license-file:        LICENSE
src/Text/Comma.hs view
@@ -1,108 +1,232 @@ {-# LANGUAGE Safe #-} -{-|-Module      : Text.Comma-Description : Join text together with a comma, and "and".-Maintainer  : hapytexeu+gh@gmail.com-Stability   : experimental-Portability : POSIX+-- |+-- Module      : Text.Comma+-- Description : Join text together with a comma, and "and".+-- Maintainer  : hapytexeu+gh@gmail.com+-- Stability   : experimental+-- Portability : POSIX+--+-- This module provides functions to join elements of /string-like/ types by adding a comma between the elements, and an "and" (optionally with a comma) between the one-but-last and the last element.+module Text.Comma+  ( -- * Data structures for text joining+    CommaStyle (OxfordComma, NoComma),+    CommaValues (CommaValues, commaText, commaAndText),+    toCommaValues,+    lastJoin, -This module provides functions to join elements of /string-like/ types by adding a comma between the elements, and an "and" (optionally with a comma) between the one-but-last and the last element.--}+    -- * Join with commas and "and"+    commaAs,+    commaEmptyAs,+    commaWith,+    commaEmptyWith,+    comma,+    noComma,+    commaEmpty,+    noCommaEmpty, -module Text.Comma (-    comma_, and_, commaAnd_-  , CommaStyle(OxfordComma, NoComma)-  , lastJoin-  , commaAs, commaEmptyAs, comma, noComma, commaEmpty, noCommaEmpty-  , combineWith, combineWithEmpty-  ) where+    -- * Basic joining of elements+    combineWith,+    combineWithEmpty, -import Data.Default.Class(Default(def))-import Data.Foldable(toList)-import Data.String(IsString(fromString))+    -- * /String-like/ constants+    comma_,+    and_,+    commaAnd_,+  )+where +import Data.Default.Class (Default (def))+import Data.Foldable (toList)+import Data.String (IsString (fromString))+ -- | The /string-like/ value for a comma, so @", "@.-comma_-  :: IsString s-  => s  -- ^ A /string-like/ type.+comma_ ::+  (IsString s) =>+  -- | A /string-like/ type.+  s comma_ = fromString ", "  -- | The /string-like/ value for an "and", so @" and "@.-and_-  :: IsString s-  => s  -- ^ A /string-like/ type.+and_ ::+  (IsString s) =>+  -- | A /string-like/ type.+  s and_ = fromString " and "  -- | The /string-like/ value for a comma and an "and", so @", and "@.-commaAnd_-  :: IsString s-  => s  -- ^ A /string-like/ type.+commaAnd_ ::+  (IsString s) =>+  -- | A /string-like/ type.+  s commaAnd_ = fromString ", and " +-- | A small data type that contains the /string-like/ values for the 'commaText, and the 'commaAndText': the join between the one but last, and last element. This can be used+-- to define a way to comma-and in a different language.+data CommaValues s+  = -- | The (only) data constructor that takes values for the comma and the "comma and" to join.+    CommaValues+    { -- | The text used to join two elements together, if the second element is /not/ the last element in the series.+      commaText :: s,+      -- | The text used to join the one but last and the last element together.+      commaAndText :: s+    }+  deriving (Eq, Ord, Read, Show)++instance (IsString s) => Default (CommaValues s) where+  def = CommaValues comma_ commaAnd_++-- | Convert the given 'CommaStyle' to the corresponding 'CommaValue' item.+toCommaValues ::+  (IsString s) =>+  -- | The given 'CommaStyle' to convert into the corrsponding 'CommaValues' object.+  CommaStyle ->+  -- | A 'CommaValues' object that contains the separators for the items.+  CommaValues s+toCommaValues OxfordComma = CommaValues comma_ commaAnd_+toCommaValues NoComma = CommaValues comma_ and_+ -- | The two different ways to join the last two items together: with or without a comma. data CommaStyle-  = OxfordComma  -- ^ The /Oxford comma/ which uses a comma before the latest element, also known as /Harvard comma/ or /series comma/.-  | NoComma  -- ^ The comma style where there is no comma before the "and" of the last item, informally known as the /Heathen comma/.+  = -- | The /Oxford comma/ which uses a comma before the latest element, also known as /Harvard comma/ or /series comma/.+    OxfordComma+  | -- | The comma style where there is no comma before the "and" of the last item, informally known as the /Heathen comma/.+    NoComma   deriving (Bounded, Enum, Eq, Ord, Read, Show)  instance Default CommaStyle where   def = OxfordComma  -- | Specify the string that determines how to join the last but one and the last item based on the 'CommaStyle'.-lastJoin-  :: IsString s-  => CommaStyle -- ^ The given comma style.-  -> s  -- ^ A string that specifies how to join the last but one item and the last item based on the comma style.+lastJoin ::+  (IsString s) =>+  -- | The given comma style.+  CommaStyle ->+  -- | A string that specifies how to join the last but one item and the last item based on the comma style.+  s lastJoin OxfordComma = commaAnd_ lastJoin _ = and_  -- | Join the 'Foldable' of elements with a given item for a comma and for the last join with a custom value if the 'Foldable' is empty.-combineWithEmpty-  :: (Semigroup s, Foldable f)-  => s  -- ^ The item used if the foldable item is empty.-  -> s  -- ^ The /comma/ item placed between each item and the next, except for the last join.-  -> s  -- ^ The item used to join the one but last item and the last item.-  -> f s  -- ^ The 'Foldable' of items that should be joined.-  -> s  -- ^ The item generated by joining the elements with the comma and last join item.+combineWithEmpty ::+  (Semigroup s, Foldable f) =>+  -- | The item used if the foldable item is empty.+  s ->+  -- | The /comma/ item placed between each item and the next, except for the last join.+  s ->+  -- | The item used to join the one but last item and the last item.+  s ->+  -- | The 'Foldable' of items that should be joined.+  f s ->+  -- | The item generated by joining the elements with the comma and last join item.+  s combineWithEmpty e c0 c1 = _combine e c0 c1 . toList  -- | Join the 'Foldable' of elements with a given item for a comma and for the last join.-combineWith-  :: (Monoid s, Foldable f)-  => s  -- ^ The /comma/ item placed between each item and the next, except for the last join.-  -> s  -- ^ The item used to join the one but last item and the last item.-  -> f s  -- ^ The 'Foldable' of items that should be joined.-  -> s  -- ^ The item generated by joining the elements with the comma and last join item.+combineWith ::+  (Monoid s, Foldable f) =>+  -- | The /comma/ item placed between each item and the next, except for the last join.+  s ->+  -- | The item used to join the one but last item and the last item.+  s ->+  -- | The 'Foldable' of items that should be joined.+  f s ->+  -- | The item generated by joining the elements with the comma and last join item.+  s combineWith c0 c1 = _combine mempty c0 c1 . toList -_combine :: Semigroup s => s -> s -> s -> [s] -> s+_combine :: (Semigroup s) => s -> s -> s -> [s] -> s _combine e _ _ [] = e _combine _ _ _ [s] = s-_combine _ c0 c1 (x:x2:xs) = go xs x x2-  where go [] s1 s2 = s1 <> c1 <> s2-        go (s3:ss) s1 s2 = s1 <> c0 <> go ss s2 s3+_combine _ c0 c1 (x : x2 : xs) = go xs x x2+  where+    go [] s1 s2 = s1 <> c1 <> s2+    go (s3 : ss) s1 s2 = s1 <> c0 <> go ss s2 s3 --- | Joins the sequence of items with the /Oxford comma/ style, uses the empty string if there are no items.-comma :: (IsString s, Monoid s, Foldable f) => f s -> s+-- | Joins the sequence of items with the /Oxford comma/ style, uses 'mempty' as empty string if there are no items.+comma ::+  (IsString s, Monoid s, Foldable f) =>+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas and just "and" as last separator.+  s comma = combineWith comma_ commaAnd_ --- | Joins the sequence of items with the /no comma/ style, uses the empty string if there are no items.-noComma :: (IsString s, Monoid s, Foldable f) => f s -> s+-- | Joins the sequence of items with the /no comma/ style, uses 'mempty' as empty string if there are no items.+noComma ::+  (IsString s, Monoid s, Foldable f) =>+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas, and ", and" (with comma) as last separator.+  s noComma = combineWith comma_ and_  -- | Join the sequence of items with the /Oxford comma/ style, uses a given "string" if there are no items.-commaEmpty :: (IsString s, Semigroup s, Foldable f) => s -> f s -> s+commaEmpty ::+  (IsString s, Semigroup s, Foldable f) =>+  -- | The item to return if the 'Foldable' is empty.+  s ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas and just "and" as last separator.+  s commaEmpty e = combineWithEmpty e comma_ commaAnd_  -- | Join the sequence of items with the /no comma/ style, uses a given "string" if there are no items.-noCommaEmpty :: (IsString s, Semigroup s, Foldable f) => s -> f s -> s+noCommaEmpty ::+  (IsString s, Semigroup s, Foldable f) =>+  -- | The item to return if the 'Foldable' is empty.+  s ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas, and ", and" (with comma) as last separator.+  s noCommaEmpty e = combineWithEmpty e comma_ and_ --- | Join the sequence of items with the given comma style, uses the empty string if there are no items.-commaAs :: (IsString s, Monoid s, Foldable f) => CommaStyle -> f s -> s+-- | Join the sequence of items with the given comma style, uses 'mempty' as empty string if there are no items.+commaAs ::+  (IsString s, Monoid s, Foldable f) =>+  -- | The given 'CommaStyle' to use.+  CommaStyle ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas as specified by the given 'CommaStyle'.+  s commaAs = combineWith comma_ . lastJoin  -- | Join the sequence of items with the given comma style, uses a given "string" if there are no items.-commaEmptyAs :: (IsString s, Semigroup s, Foldable f) => s -> CommaStyle -> f s -> s+commaEmptyAs ::+  (IsString s, Semigroup s, Foldable f) =>+  -- | The item to return if the 'Foldable' is empty.+  s ->+  -- | The given 'CommaStyle' to use.+  CommaStyle ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas as specified by the given 'CommaStyle'.+  s commaEmptyAs e = combineWithEmpty e comma_ . lastJoin++-- | Join the sequence of items with the given 'CommaValues', uses 'mempty' as empty string if there are no items.+commaWith ::+  (IsString s, Monoid s, Foldable f) =>+  -- | A 'CommaValues' object that determines the normal separator and the last separator.+  CommaValues s ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas as specified by the given 'CommaValues'.+  s+commaWith ~(CommaValues c ca) = combineWith c ca++-- | Join the sequence of items with the given 'CommaValues', uses a given "string" if there are no items.+commaEmptyWith ::+  (IsString s, Semigroup s, Foldable f) =>+  -- | The item to return if the 'Foldable' is empty.+  s ->+  -- | A 'CommaValues' object that determines the normal separator and the last separator.+  CommaValues s ->+  -- | The 'Foldable' of string-like elements to join.+  f s ->+  -- | The result that has joined the elements with commas as specified by the given 'CommaValues'.+  s+commaEmptyWith e ~(CommaValues c ca) = combineWithEmpty e c ca
test/Text/CommaSpec.hs view
@@ -3,7 +3,7 @@ import Data.Default.Class(Default(def))  import Test.Hspec(Spec, describe, it, shouldBe)-import Text.Comma(CommaStyle(OxfordComma, NoComma), comma, commaAs, commaEmpty, commaEmptyAs, lastJoin, noComma, noCommaEmpty)+import Text.Comma(CommaStyle(OxfordComma, NoComma), CommaValues(commaText, commaAndText), comma, commaAs, commaEmpty, commaEmptyAs, commaEmptyWith, commaWith, lastJoin, noComma, noCommaEmpty, toCommaValues)  spec :: Spec spec = describe "and" $ do@@ -45,6 +45,24 @@       commaEmptyAs "and" NoComma ["red"] `shouldBe` "red"       commaEmptyAs "and" NoComma ["red", "green"] `shouldBe` "red and green"       commaEmptyAs "and" NoComma ["red", "green", "blue"] `shouldBe` "red, green and blue"+    it "commaWith" $ do+      commaWith (toCommaValues OxfordComma) [] `shouldBe` ""+      commaWith (toCommaValues OxfordComma) ["red"] `shouldBe` "red"+      commaWith (toCommaValues OxfordComma) ["red", "green"] `shouldBe` "red, and green"+      commaWith (toCommaValues OxfordComma) ["red", "green", "blue"] `shouldBe` "red, green, and blue"+      commaWith (toCommaValues NoComma) [] `shouldBe` ""+      commaWith (toCommaValues NoComma) ["red"] `shouldBe` "red"+      commaWith (toCommaValues NoComma) ["red", "green"] `shouldBe` "red and green"+      commaWith (toCommaValues NoComma) ["red", "green", "blue"] `shouldBe` "red, green and blue"+    it "commaEmptyWith" $ do+      commaEmptyWith "and" (toCommaValues OxfordComma) [] `shouldBe` "and"+      commaEmptyWith "and" (toCommaValues OxfordComma) ["red"] `shouldBe` "red"+      commaEmptyWith "and" (toCommaValues OxfordComma) ["red", "green"] `shouldBe` "red, and green"+      commaEmptyWith "and" (toCommaValues OxfordComma) ["red", "green", "blue"] `shouldBe` "red, green, and blue"+      commaEmptyWith "and" (toCommaValues NoComma) [] `shouldBe` "and"+      commaEmptyWith "and" (toCommaValues NoComma) ["red"] `shouldBe` "red"+      commaEmptyWith "and" (toCommaValues NoComma) ["red", "green"] `shouldBe` "red and green"+      commaEmptyWith "and" (toCommaValues NoComma) ["red", "green", "blue"] `shouldBe` "red, green and blue"     it "lastJoin" $ do       lastJoin OxfordComma `shouldBe` ", and "       lastJoin NoComma `shouldBe` " and "@@ -54,3 +72,7 @@       maxBound `shouldBe` NoComma       succ OxfordComma `shouldBe` NoComma       compare OxfordComma NoComma `shouldBe` LT+    it "CommaValues" $ do+      toCommaValues def `shouldBe` def+      commaText (toCommaValues def) `shouldBe` commaText def+      commaAndText (toCommaValues def) `shouldBe` commaAndText def