packages feed

comma-and (empty) → 0.1.0.0

raw patch · 8 files changed

+242/−0 lines, 8 filesdep +QuickCheckdep +basedep +comma-andsetup-changed

Dependencies added: QuickCheck, base, comma-and, data-default-class, hspec

Files

+ CHANGELOG.md view
@@ -0,0 +1,7 @@+# `comma-and` changelog++Convert a list of items to text by adding commas and an "and" at the end.++## Version 0.1.0.0++The first working version of `comma-and`.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Willem Van Onsem (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Willem Van Onsem nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,27 @@+# comma-and+[![Build Status of the package by GitHub actions](https://github.com/hapytex/comma-and/actions/workflows/build-ci.yml/badge.svg)](https://github.com/hapytex/comma-and/actions/workflows/build-ci.yml)+[![Build Status of the package by Hackage](https://matrix.hackage.haskell.org/api/v2/packages/comma-and/badge)](https://matrix.hackage.haskell.org/#/package/comma-and)+[![Hackage version badge](https://img.shields.io/hackage/v/comma-and.svg)](https://hackage.haskell.org/package/comma-and)++Joins text items together by separating these with commas, and "and" at the end.++## Usage++We can combine elements with:++```+ghci> comma ["red", "green", "blue"]+"red, green, and blue"+```++The package has tooling for the two different comma styles, and can work with any *string-like* type.++## `comma-and` is *safe* Haskell++The module is compiled with `Safe` and does not depend on unsafe modules.++## Contribute++You can contribute by making a pull request on the [*GitHub repository*](https://github.com/hapytex/comma-and).++You can contact the package maintainer by sending a mail to [`hapytexeu+gh@gmail.com`](mailto:hapytexeu+gh@gmail.com).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ comma-and.cabal view
@@ -0,0 +1,53 @@+name:                comma-and+version:             0.1.0.0+synopsis: Join text together with commas, and "and".+description: Convert a 'Text' object into a visually pleasant URL component.+homepage:            https://github.com/hapytex/comma-and#readme+license:             BSD3+license-file:        LICENSE+author:              Willem Van Onsem+maintainer:          hapytexeu+gh@gmail.com+copyright:           2020 Willem Van Onsem+category:            utils+build-type:          Simple+extra-source-files:+    README.md+  , CHANGELOG.md+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:+      Text.Comma+  build-depends:+      base >= 4.7 && < 5+    , data-default-class >=0.1 && <0.2+  default-language:    Haskell2010++test-suite gulsify+  type:                exitcode-stdio-1.0+  main-is:             Main.hs+  hs-source-dirs:      test+  other-modules:+      Text.CommaSpec+  build-depends:+      base+    , comma-and+    , data-default-class >=0.1 && <0.2+    , hspec ==2.*+    , QuickCheck >=2.8+  build-tool-depends: hspec-discover:hspec-discover == 2.*+  default-language:    Haskell2010+  default-extensions:+      BlockArguments+    , OverloadedStrings+  ghc-options:+    -Wall -Wcompat -Wcompat+    -Wincomplete-record-updates+    -Wincomplete-uni-patterns+    -Wredundant-constraints+++source-repository head+  type:     git+  location: https://github.com/hapytex/comma-and
+ src/Text/Comma.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE Safe #-}++{-|+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 (+    comma_, and_, commaAnd_+  , CommaStyle(OxfordComma, NoComma)+  , lastJoin+  , commaAs, commaEmptyAs, comma, noComma, commaEmpty, noCommaEmpty+  , combineWith, combineWithEmpty+  ) 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_ = fromString ", "++-- | The /string-like/ value for an "and", so @" and "@.+and_+  :: IsString s+  => s  -- ^ A /string-like/ type.+and_ = fromString " and "++-- | The /string-like/ value for a comma and an "and", so @", and "@.+commaAnd_+  :: IsString s+  => s  -- ^ A /string-like/ type.+commaAnd_ = fromString ", 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/.+  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 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 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 c0 c1 = _combine mempty c0 c1 . toList++_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++-- | 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+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+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 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 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+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 e = combineWithEmpty e comma_ . lastJoin
+ test/Main.hs view
@@ -0,0 +1,3 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+-- cabal v2-test --test-show-details=direct+-- cabal v2-test --test-show-details=direct --test-options="--color --format=progress"
+ test/Text/CommaSpec.hs view
@@ -0,0 +1,12 @@+module Text.CommaSpec where++import Test.Hspec(Spec, describe, it, shouldBe)+import Text.Comma(comma)++spec :: Spec+spec = describe "comma" $ do+    it "comma" $ do+      comma [] `shouldBe` ""+      comma ["red"] `shouldBe` "red"+      comma ["red", "green"] `shouldBe` "red, and green"+      comma ["red", "green", "blue"] `shouldBe` "red, green, and blue"