packages feed

ascii-th 1.1.1.0 → 1.2.0.0

raw patch · 5 files changed

+74/−45 lines, 5 filesdep ~ascii-supersetPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: ascii-superset

API changes (from Hackage documentation)

+ ASCII.TemplateHaskell: lowerStringExp :: [CaselessChar] -> Q Exp
+ ASCII.TemplateHaskell: upperStringExp :: [CaselessChar] -> Q Exp

Files

ascii-th.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: ascii-th-version: 1.1.1.0+version: 1.2.0.0 synopsis: Template Haskell support for ASCII category: Data, Text @@ -31,13 +31,15 @@         ascii-case ^>= 1.0       , ascii-caseless ^>= 0.0       , ascii-char ^>= 1.0-      , ascii-superset ^>= 1.1.0+      , ascii-superset ^>= 1.2.4       , base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17  library     import: base     hs-source-dirs: library-    default-extensions: NoImplicitPrelude TemplateHaskell ViewPatterns+    default-extensions: AllowAmbiguousTypes DataKinds FlexibleContexts+        KindSignatures NoImplicitPrelude ScopedTypeVariables+        TemplateHaskell TypeApplications ViewPatterns     build-depends:         template-haskell ^>= 2.16 || ^>= 2.17 || ^>= 2.18 || ^>= 2.19     exposed-modules:
changelog.md view
@@ -1,3 +1,17 @@+### 1.2.0.0 (2023-01-06)++The constraints on `lower` and `upper` quasi-quotations in an expression context+are changes from `FromString` to `ToCasefulString 'LowerCase` and+`ToCasefulString 'UpperCase` respectively. This expands the range of types+inhabited by lower/uppercase quotes to include `ASCII'lower` and `ASCII'upper`,+which were previously not able to be expressed using quasi-quotations.++Additions to `ASCII.TemplateHaskell`:++```haskell+upperStringExp, lowerStringExp :: [CaselessChar] -> Q Exp+```+ ### 1.1.1.0 (2023-01-03)  New in `ASCII.QuasiQuoters`:
library/ASCII/QuasiQuoters.hs view
@@ -19,16 +19,13 @@ import ASCII.Char (Char) import Control.Monad (return, (>=>)) import Control.Monad.Fail (MonadFail, fail)-import Data.Functor ((<$>)) import Data.Maybe (Maybe (..)) import Language.Haskell.TH.Quote (QuasiQuoter (..)) import Language.Haskell.TH.Syntax (Exp, Pat, Q) -import qualified ASCII.Case as Case import qualified ASCII.Superset as S import qualified ASCII.TemplateHaskell as TH import qualified Data.Char as Unicode-import qualified Data.List as List import qualified Data.String as Unicode  {-| An expression pattern corresponding to an ASCII character@@ -148,11 +145,14 @@  === In an expression context -The expression can become any type belonging to the 'ASCII.Superset.FromString'-class. Any letters in the quoted content will be converted to lower case.+The expression can become any type satisfying the+@('ASCII.Superset.ToCasefulString' ''LowerCase')@ constraint.+Any letters in the quoted content will be converted to lower case.  @-[lower|Hello!|] == ("hello!" :: 'Text')+[lower|Hello!|] == ("hello!" :: 'Data.Text.Text')++[lower|Hello!|] == ("hello!" :: 'ASCII'lower' 'Data.ByteString.ByteString') @  === In a pattern context@@ -176,7 +176,8 @@  -} lower :: QuasiQuoter-lower = ofCase LowerCase+lower = expPatQQ requireAsciiListCI TH.lowerStringExp+    (\x -> TH.isStringPat (S.toCasefulString @'LowerCase x))  {-| An expression or pattern corresponding to an ASCII string where all the letters are of upper case@@ -186,11 +187,14 @@  === In an expression context -The expression can become any type belonging to the 'ASCII.Superset.FromString'-class. Any letters in the quoted content will be converted to upper case.+The expression can become any type satisfying the+@('ASCII.Superset.ToCasefulString' ''UpperCase')@ constraint.+Any letters in the quoted content will be converted to upper case.  @ [upper|Hello!|] == ("HELLO!" :: 'Text')++[upper|Hello!|] == ("HELLO!" :: 'ASCII'upper' 'Data.ByteString.ByteString') @  === In a pattern context@@ -214,10 +218,8 @@  -} upper :: QuasiQuoter-upper = ofCase UpperCase--ofCase :: Case -> QuasiQuoter-ofCase c = expPatQQ (requireAsciiToCase c) TH.isStringExp TH.isStringPat+upper = expPatQQ requireAsciiListCI TH.upperStringExp+    (\x -> TH.isStringPat (S.toCasefulString @'UpperCase x))  {-| Require the string to consist of exactly one ASCII character -} requireOneAscii :: Unicode.String -> Q Char@@ -243,11 +245,6 @@ and return them with letter case discarded -} requireAsciiListCI :: Unicode.String -> Q [CaselessChar] requireAsciiListCI = S.toCaselessCharListMaybe || "Must be only ASCII characters."--{-| Require the string to consist of all ASCII characters,-and return them converted to the given case -}-requireAsciiToCase :: Case -> Unicode.String -> Q [Char]-requireAsciiToCase c s = List.map (Case.toCase c) <$> requireAsciiList s  (||) :: (a -> Maybe b) -> Unicode.String -> a -> Q b f || msg = \a -> case f a of Just b -> return b; Nothing -> fail msg
library/ASCII/TemplateHaskell.hs view
@@ -9,12 +9,14 @@     {- ** Character -} isCharExp, isCharPat,     {- ** String -} isStringExp, isStringPat,     {- ** Caseless string -} caselessIsStringPat,+    {- ** Single-case string -} upperStringExp, lowerStringExp,   )   where  import qualified ASCII.Char as ASCII import qualified ASCII.Superset as S +import ASCII.Case (Case (..)) import ASCII.Caseless (CaselessChar) import Data.Data (Data) import Data.Maybe (Maybe (..))@@ -132,3 +134,17 @@ class, as if it were a list of 'CaselessChar' -} caselessIsStringPat :: [CaselessChar] -> Q Pat caselessIsStringPat xs = [p| (S.toCaselessCharListMaybe -> Just $(caselessListPat xs)) |]++{-| Expression with a @'ASCII.Superset.ToCasefulString 'UpperCase'@ constraint -}+upperStringExp :: [CaselessChar] -> Q Exp+upperStringExp xs = [| toUpper $(caselessListExp xs) |]++{-| Expression with a @'ASCII.Superset.ToCasefulString 'LowerCase'@ constraint -}+lowerStringExp :: [CaselessChar] -> Q Exp+lowerStringExp xs = [| toLower $(caselessListExp xs) |]++toUpper :: S.ToCasefulString 'UpperCase string => [CaselessChar] -> string+toUpper = S.toCasefulString @'UpperCase++toLower :: S.ToCasefulString 'LowerCase string => [CaselessChar] -> string+toLower = S.toCasefulString @'LowerCase
test/Main.hs view
@@ -3,9 +3,11 @@ import qualified ASCII.QuasiQuoters as QQ import qualified ASCII.TemplateHaskell as TH +import ASCII.CaseRefinement (ASCII'lower, ASCII'upper, asciiCaseUnsafe) import ASCII.Char (Char (..)) import ASCII.Refinement (ASCII, asciiUnsafe) +import Data.ByteString (ByteString) import Data.Function (($)) import Data.String (String) import Data.Text (Text)@@ -13,7 +15,7 @@ import Prelude (Integer) import System.IO (IO) -import qualified ASCII.Caseless as Caseless+import qualified ASCII.Caseless as CI import qualified Data.ByteString.Builder as BS.Builder import qualified Data.ByteString.Lazy as LBS @@ -46,10 +48,10 @@          describe "caseless" $ do             it "can be [CaselessChar]" $ shouldBe [QQ.caseless|Hello!|]-                [Caseless.LetterH, Caseless.LetterE, Caseless.LetterL,-                Caseless.LetterL, Caseless.LetterO, Caseless.ExclamationMark]+                [CI.LetterH, CI.LetterE, CI.LetterL,+                CI.LetterL, CI.LetterO, CI.ExclamationMark]             it "can be a pattern over [CaselessChar]" $ do-                let x = case [Caseless.LetterH, Caseless.LetterI] of+                let x = case [CI.LetterH, CI.LetterI] of                           [QQ.caseless|Bye|] -> 1; [QQ.caseless|Hi|] -> 2; _ -> 3                 shouldBe @Integer x 2             it "can be a pattern over Text" $ do@@ -63,30 +65,26 @@          describe "upper" $ do             it "can be Text" $ shouldBe [QQ.upper|Hello!|] ("HELLO!" :: Text)+            it "can be case-refined" $ shouldBe [QQ.upper|Hello!|]+                (asciiCaseUnsafe "HELLO!" :: ASCII'upper ByteString)             it "can match Text" $ do                 let x = case "HI!" :: Text of-                          [QQ.upper|wow|] -> 1-                          [QQ.upper|Hi!|] -> 2-                          _ -> 3+                          [QQ.upper|wow|] -> 1; [QQ.upper|Hi!|] -> 2; _ -> 3                 shouldBe @Integer x 2             it "only matches all upper-case Text" $ do-                let x = case "Hi!" :: Text of-                          [QQ.upper|Hi!|] -> 1-                          _ -> 2+                let x = case "Hi!" :: Text of [QQ.upper|Hi!|] -> 1; _ -> 2                 shouldBe @Integer x 2          describe "lower" $ do             it "can be Text" $ shouldBe [QQ.lower|Hello!|] ("hello!" :: Text)+            it "can be case-refined" $ shouldBe [QQ.lower|Hello!|]+                (asciiCaseUnsafe "hello!" :: ASCII'lower ByteString)             it "can match Text" $ do                 let x = case "hi!" :: Text of-                          [QQ.lower|wow|] -> 1-                          [QQ.lower|Hi!|] -> 2-                          _ -> 3+                          [QQ.lower|wow|] -> 1; [QQ.lower|Hi!|] -> 2; _ -> 3                 shouldBe @Integer x 2             it "only matches all lower-case Text" $ do-                let x = case "Hi!" :: Text of-                          [QQ.lower|Hi!|] -> 1-                          _ -> 2+                let x = case "Hi!" :: Text of [QQ.lower|Hi!|] -> 1; _ -> 2                 shouldBe @Integer x 2      describe "ASCII.TemplateHaskell" $ do@@ -97,9 +95,10 @@          describe "charPat" $ do             it "is a Char pattern" $ do-                let x = case SmallLetterS of $(TH.charPat SmallLetterR) -> 1;-                                             $(TH.charPat SmallLetterS) -> 2;-                                             _ -> 3+                let x = case SmallLetterS of+                          $(TH.charPat SmallLetterR) -> 1;+                          $(TH.charPat SmallLetterS) -> 2;+                          _ -> 3                 shouldBe @Integer x 2          describe "charListExp" $ do@@ -126,15 +125,16 @@          describe "isCharPat" $ do             it "can be a Word8 pattern" $ do-                let x = case (66 :: Word8) of $(TH.isCharPat CapitalLetterA) -> 1-                                              $(TH.isCharPat CapitalLetterB) -> 2-                                              _ -> 3+                let x = case (66 :: Word8) of+                          $(TH.isCharPat CapitalLetterA) -> 1+                          $(TH.isCharPat CapitalLetterB) -> 2+                          _ -> 3                 shouldBe @Integer x 2          describe "caselessIsStringPat" $ do             it "matches a cased string regardless of its case" $ do                 let x = case [QQ.string|Hi!|] :: Text of-                      $(TH.caselessIsStringPat [Caseless.LetterG, Caseless.LetterO, Caseless.FullStop]) -> 1-                      $(TH.caselessIsStringPat [Caseless.LetterH, Caseless.LetterI, Caseless.ExclamationMark]) -> 2+                      $(TH.caselessIsStringPat [CI.LetterG, CI.LetterO, CI.FullStop]) -> 1+                      $(TH.caselessIsStringPat [CI.LetterH, CI.LetterI, CI.ExclamationMark]) -> 2                       _ -> 3                 shouldBe @Integer x 2