diff --git a/CHANGELOG.md b/CHANGELOG.md index c3bf386..7a948dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Notable changes to this project are documented in this file. The format is based Breaking changes: New features: +- Added `startsWith` and `endsWith` (#147) Bugfixes: diff --git a/src/Data/String/CodePoints.purs b/src/Data/String/CodePoints.purs index 65e0b55..bd962f3 100644 --- a/src/Data/String/CodePoints.purs +++ b/src/Data/String/CodePoints.purs @@ -34,7 +34,7 @@ import Data.Array as Array import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), defaultPred, defaultSucc, fromEnum, toEnum, toEnumWithDefaults) import Data.Int (hexadecimal, toStringAs) import Data.Maybe (Maybe(..)) -import Data.String.CodeUnits (contains, stripPrefix, stripSuffix) as Exports +import Data.String.CodeUnits (contains, stripPrefix, stripSuffix, startsWith, endsWith) as Exports import Data.String.CodeUnits as CU import Data.String.Common (toUpper) import Data.String.Pattern (Pattern) diff --git a/src/Data/String/CodeUnits.purs b/src/Data/String/CodeUnits.purs index fbc1803..ec277ce 100644 --- a/src/Data/String/CodeUnits.purs +++ b/src/Data/String/CodeUnits.purs @@ -22,6 +22,8 @@ module Data.String.CodeUnits , dropWhile , slice , splitAt + , startsWith + , endsWith ) where import Prelude @@ -31,9 +33,10 @@ import Data.String.Pattern (Pattern(..)) import Data.String.Unsafe as U ------------------------------------------------------------------------------- --- `stripPrefix`, `stripSuffix`, and `contains` are CodeUnit/CodePoint agnostic --- as they are based on patterns rather than lengths/indices, but they need to --- be defined in here to avoid a circular module dependency +-- `stripPrefix`, `stripSuffix`, `startsWith`, `endsWith`, and `contains` are +-- CodeUnit/CodePoint agnostic as they are based on patterns rather than +-- lengths/indices, but they need to be defined in here to avoid a circular +-- module dependency ------------------------------------------------------------------------------- -- | If the string starts with the given prefix, return the portion of the @@ -61,6 +64,30 @@ stripSuffix (Pattern suffix) str = let { before, after } = splitAt (length str - length suffix) str in if after == suffix then Just before else Nothing +-- | Checks whether the given string starts with the pattern. +-- | +-- | **NOTE**: if you also want to get the string stripped of the pattern, see +-- | `stripPrefix`. +-- | +-- | ```purescript +-- | startsWith (Pattern "foo") "foobar" == true +-- | startsWith (Pattern "bar") "foobar" == false +-- | ``` +startsWith :: Pattern -> String -> Boolean +startsWith pat = isJust <<< stripPrefix pat + +-- | Checks whether the given string ends with the pattern. +-- | +-- | **NOTE**: if you also want to get the string stripped of the pattern, see +-- | `stripSuffix`. +-- | +-- | ```purescript +-- | endsWith (Pattern "bar") "foobar" == true +-- | endsWith (Pattern "foo") "foobar" == false +-- | ``` +endsWith :: Pattern -> String -> Boolean +endsWith pat = isJust <<< stripSuffix pat + -- | Checks whether the pattern appears in the given string. -- | -- | ```purescript diff --git a/src/Data/String/NonEmpty.purs b/src/Data/String/NonEmpty.purs index 6b6210c..72e10b3 100644 --- a/src/Data/String/NonEmpty.purs +++ b/src/Data/String/NonEmpty.purs @@ -4,6 +4,6 @@ module Data.String.NonEmpty , module Data.String.NonEmpty.CodePoints ) where -import Data.String.NonEmpty.Internal (NonEmptyString, class MakeNonEmpty, NonEmptyReplacement(..), appendString, contains, fromString, join1With, joinWith, joinWith1, localeCompare, nes, prependString, replace, replaceAll, stripPrefix, stripSuffix, toLower, toString, toUpper, trim, unsafeFromString) +import Data.String.NonEmpty.Internal (NonEmptyString, class MakeNonEmpty, NonEmptyReplacement(..), appendString, contains, fromString, join1With, joinWith, joinWith1, localeCompare, nes, prependString, replace, replaceAll, stripPrefix, stripSuffix, startsWith, endsWith, toLower, toString, toUpper, trim, unsafeFromString) import Data.String.Pattern (Pattern(..)) import Data.String.NonEmpty.CodePoints diff --git a/src/Data/String/NonEmpty/Internal.purs b/src/Data/String/NonEmpty/Internal.purs index 707b779..f08869c 100644 --- a/src/Data/String/NonEmpty/Internal.purs +++ b/src/Data/String/NonEmpty/Internal.purs @@ -123,6 +123,31 @@ stripPrefix pat = fromString <=< liftS (String.stripPrefix pat) stripSuffix :: Pattern -> NonEmptyString -> Maybe NonEmptyString stripSuffix pat = fromString <=< liftS (String.stripSuffix pat) + +-- | Checks whether the given string starts with the pattern. +-- | +-- | **NOTE**: if you also want to get the string stripped of the pattern, see +-- | `stripPrefix`. +-- | +-- | ```purescript +-- | startsWith (Pattern "foo") (NonEmptyString "foobar") == true +-- | startsWith (Pattern "bar") (NonEmptyString "foobar") == false +-- | ``` +startsWith :: Pattern -> NonEmptyString -> Boolean +startsWith = liftS <<< String.startsWith + +-- | Checks whether the given string ends with the pattern. +-- | +-- | **NOTE**: if you also want to get the string stripped of the pattern, see +-- | `stripSuffix`. +-- | +-- | ```purescript +-- | endsWith (Pattern "bar") (NonEmptyString "foobar") == true +-- | endsWith (Pattern "foo") (NonEmptyString "foobar") == false +-- | ``` +endsWith :: Pattern -> NonEmptyString -> Boolean +endsWith = liftS <<< String.endsWith + -- | Checks whether the pattern appears in the given string. -- | -- | ```purescript diff --git a/test/Test/Data/String/CodeUnits.purs b/test/Test/Data/String/CodeUnits.purs index 9cf010b..8472f20 100644 --- a/test/Test/Data/String/CodeUnits.purs +++ b/test/Test/Data/String/CodeUnits.purs @@ -64,6 +64,20 @@ testStringCodeUnits = do , expected: Just "" } + log "startsWith" + assert $ SCU.startsWith (Pattern "foo") "foobar" + assert $ SCU.startsWith (Pattern "foo") "foo" + assert $ SCU.startsWith (Pattern "") "" + assert $ SCU.startsWith (Pattern "") "foo" + assert $ not $ SCU.startsWith (Pattern "foo") "" + + log "endsWith" + assert $ SCU.endsWith (Pattern "bar") "foobar" + assert $ SCU.endsWith (Pattern "bar") "bar" + assert $ SCU.endsWith (Pattern "") "" + assert $ SCU.endsWith (Pattern "") "bar" + assert $ not $ SCU.endsWith (Pattern "bar") "" + log "charAt" assertEqual { actual: SCU.charAt 0 "" diff --git a/test/Test/Data/String/NonEmpty.purs b/test/Test/Data/String/NonEmpty.purs index a4103ec..46f2cd0 100644 --- a/test/Test/Data/String/NonEmpty.purs +++ b/test/Test/Data/String/NonEmpty.purs @@ -144,6 +144,19 @@ testNonEmptyString = do , expected: Nothing } + log "startsWith" + assert $ NES.startsWith (Pattern "foo") (nes (Proxy :: Proxy "foobar")) + assert $ NES.startsWith (Pattern "foo") (nes (Proxy :: Proxy "foo")) + assert $ NES.startsWith (Pattern "") (nes (Proxy :: Proxy "foo")) + assert $ not $ NES.startsWith (Pattern "foo") (nes (Proxy :: Proxy "f")) + + log "endsWith" + assert $ NES.endsWith (Pattern "bar") (nes (Proxy :: Proxy "foobar")) + assert $ NES.endsWith (Pattern "bar") (nes (Proxy :: Proxy "bar")) + assert $ NES.endsWith (Pattern "") (nes (Proxy :: Proxy "f")) + assert $ NES.endsWith (Pattern "") (nes (Proxy :: Proxy "bar")) + assert $ not $ NES.endsWith (Pattern "bar") (nes (Proxy :: Proxy "b")) + log "toLower" assertEqual { actual: NES.toLower (nes (Proxy :: Proxy "bAtMaN"))