diff --git a/bower.json b/bower.json index b4c32dc..f9aed89 100644 --- a/bower.json +++ b/bower.json @@ -20,5 +20,9 @@ ], "dependencies": { "purescript-maybe": "^0.3.0" + }, + "devDependencies": { + "purescript-assert": "~0.1.0", + "purescript-console": "~0.1.0" } } diff --git a/docs/Data/Char.md b/docs/Data/Char.md index c143a21..8a63047 100644 --- a/docs/Data/Char.md +++ b/docs/Data/Char.md @@ -26,4 +26,20 @@ fromCharCode :: Int -> Char Constructs a character from the given Unicode numeric value. +#### `toLower` + +``` purescript +toLower :: Char -> Char +``` + +Converts a character to lowercase. + +#### `toUpper` + +``` purescript +toUpper :: Char -> Char +``` + +Converts a character to uppercase. + diff --git a/docs/Data/String.md b/docs/Data/String.md index b5f4771..d9ad647 100644 --- a/docs/Data/String.md +++ b/docs/Data/String.md @@ -198,8 +198,9 @@ of the string for which the predicate holds. split :: String -> String -> Array String ``` -Returns the substrings of the first string separated along occurences -of the second string. +Returns the substrings of the second string separated along occurences +of the first string. +* `split " " "hello world" == ["hello", "world"]` #### `toCharArray` diff --git a/docs/Data/String/Regex.md b/docs/Data/String/Regex.md index 95a6150..bcc0427 100644 --- a/docs/Data/String/Regex.md +++ b/docs/Data/String/Regex.md @@ -115,11 +115,11 @@ See the [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe #### `search` ``` purescript -search :: Regex -> String -> Int +search :: Regex -> String -> Maybe Int ``` -Returns the index of the first match of the `Regex` in the string, or -`-1` if there is no match. +Returns `Just` the index of the first match of the `Regex` in the string, +or `Nothing` if there is no match. #### `split` diff --git a/package.json b/package.json index e129c49..2d38aab 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "scripts": { "postinstall": "pulp dep install", - "build": "jshint src && jscs src && pulp build && rimraf docs && pulp docs" + "build": "jshint src && jscs src && pulp build && pulp test && rimraf docs && pulp docs" }, "devDependencies": { "jscs": "^1.13.1", diff --git a/src/Data/Char.js b/src/Data/Char.js index b4885a6..7a929c6 100644 --- a/src/Data/Char.js +++ b/src/Data/Char.js @@ -14,3 +14,11 @@ exports.toCharCode = function (c) { exports.fromCharCode = function (c) { return String.fromCharCode(c); }; + +exports.toLower = function (c) { + return c.toLowerCase(); +}; + +exports.toUpper = function (c) { + return c.toUpperCase(); +}; diff --git a/src/Data/Char.purs b/src/Data/Char.purs index 207890d..17dd992 100644 --- a/src/Data/Char.purs +++ b/src/Data/Char.purs @@ -3,6 +3,8 @@ module Data.Char ( toString , fromCharCode , toCharCode + , toLower + , toUpper ) where import Prelude @@ -16,11 +18,13 @@ foreign import toCharCode :: Char -> Int -- | Constructs a character from the given Unicode numeric value. foreign import fromCharCode :: Int -> Char +-- | Converts a character to lowercase. +foreign import toLower :: Char -> Char + +-- | Converts a character to uppercase. +foreign import toUpper :: Char -> Char + -- | Characters fall within the Unicode range. instance boundedChar :: Bounded Char where top = fromCharCode zero bottom = fromCharCode 65535 - --- | Characters can be rendered as a string with `show`. -instance showChar :: Show Char where - show c = "Char " ++ show (toString c) diff --git a/src/Data/String.js b/src/Data/String.js index 5e47ced..bf50543 100644 --- a/src/Data/String.js +++ b/src/Data/String.js @@ -51,6 +51,7 @@ exports["_indexOf'"] = function (just) { return function (x) { return function (startAt) { return function (s) { + if (startAt < 0 || startAt > s.length) return nothing; var i = s.indexOf(x, startAt); return i === -1 ? nothing : just(i); }; @@ -75,6 +76,7 @@ exports["_lastIndexOf'"] = function (just) { return function (x) { return function (startAt) { return function (s) { + if (startAt < 0 || startAt > s.length) return nothing; var i = s.lastIndexOf(x, startAt); return i === -1 ? nothing : just(i); }; @@ -93,7 +95,7 @@ exports._localeCompare = function (lt) { return function (s1) { return function (s2) { var result = s1.localeCompare(s2); - return result < 0 ? lt : result > 1 ? gt : eq; + return result < 0 ? lt : result > 0 ? gt : eq; }; }; }; diff --git a/src/Data/String.purs b/src/Data/String.purs index 652d077..7af4fed 100644 --- a/src/Data/String.purs +++ b/src/Data/String.purs @@ -33,7 +33,7 @@ module Data.String ) where import Prelude -import Data.Char +import qualified Data.Char as C import Data.Maybe (Maybe(..), isJust) import Data.Monoid (Monoid) import qualified Data.String.Unsafe as U @@ -50,7 +50,7 @@ foreign import _charAt :: (forall a. a -> Maybe a) -- | Returns a string of length `1` containing the given character. fromChar :: Char -> String -fromChar = toString +fromChar = C.toString -- | Returns a string of length `1` containing the given character. -- | Same as `fromChar`. diff --git a/src/Data/String/Regex.js b/src/Data/String/Regex.js index 01e8a2e..f70bef3 100644 --- a/src/Data/String/Regex.js +++ b/src/Data/String/Regex.js @@ -70,9 +70,14 @@ exports["replace'"] = function (r) { }; }; -exports.search = function (r) { - return function (s) { - return s.search(r); +exports._search = function (just) { + return function (nothing) { + return function (r) { + return function (s) { + var result = s.search(r); + return result === -1 ? nothing : just(result); + }; + }; }; }; diff --git a/src/Data/String/Regex.purs b/src/Data/String/Regex.purs index 3bec5b9..d0bf1ea 100644 --- a/src/Data/String/Regex.purs +++ b/src/Data/String/Regex.purs @@ -104,9 +104,16 @@ foreign import replace :: Regex -> String -> String -> String -- | See the [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter). foreign import replace' :: Regex -> (String -> Array String -> String) -> String -> String --- | Returns the index of the first match of the `Regex` in the string, or --- | `-1` if there is no match. -foreign import search :: Regex -> String -> Int +foreign import _search :: (forall r. r -> Maybe r) + -> (forall r. Maybe r) + -> Regex + -> String + -> Maybe Int + +-- | Returns `Just` the index of the first match of the `Regex` in the string, +-- | or `Nothing` if there is no match. +search :: Regex -> String -> Maybe Int +search = _search Just Nothing -- | Split the string into an array of substrings along occurences of the `Regex`. foreign import split :: Regex -> String -> Array String diff --git a/test/Test/Data/Char.purs b/test/Test/Data/Char.purs new file mode 100644 index 0000000..5063b74 --- /dev/null +++ b/test/Test/Data/Char.purs @@ -0,0 +1,27 @@ +module Test.Data.Char (testChar) where + +import Prelude +import Control.Monad.Eff.Console (log) +import Data.Char +import Test.Assert (assert) + +testChar = do + log "toString" + assert $ toString 'a' == "a" + + log "toCharCode" + assert $ toCharCode 'a' == 97 + assert $ toCharCode '\n' == 10 + + log "fromCharCode" + assert $ fromCharCode 97 == 'a' + assert $ fromCharCode 10 == '\n' + + log "toLower" + assert $ toLower 'A' == 'a' + assert $ toLower 'a' == 'a' + + log "toUpper" + assert $ toUpper 'a' == 'A' + assert $ toUpper 'A' == 'A' + diff --git a/test/Test/Data/String.purs b/test/Test/Data/String.purs new file mode 100644 index 0000000..4f43ac3 --- /dev/null +++ b/test/Test/Data/String.purs @@ -0,0 +1,175 @@ +module Test.Data.String (testString) where + +import Prelude +import Data.Maybe +import Control.Monad.Eff.Console (log) +import Data.String +import Test.Assert (assert) + +testString = do + log "charAt" + assert $ charAt 0 "" == Nothing + assert $ charAt 0 "a" == Just 'a' + assert $ charAt 1 "a" == Nothing + assert $ charAt 0 "ab" == Just 'a' + assert $ charAt 1 "ab" == Just 'b' + assert $ charAt 2 "ab" == Nothing + + log "fromChar" + assert $ fromChar 'a' == "a" + + log "singleton" + assert $ singleton 'a' == "a" + + log "charCodeAt" + assert $ charCodeAt 0 "" == Nothing + assert $ charCodeAt 0 "a" == Just 97 + assert $ charCodeAt 1 "a" == Nothing + assert $ charCodeAt 0 "ab" == Just 97 + assert $ charCodeAt 1 "ab" == Just 98 + assert $ charCodeAt 2 "ab" == Nothing + + log "toChar" + assert $ toChar "" == Nothing + assert $ toChar "a" == Just 'a' + assert $ toChar "ab" == Nothing + + log "null" + assert $ null "" + assert $ not (null "a") + + log "uncons" + assert $ isNothing (uncons "") + assert $ case uncons "a" of + Nothing -> false + Just m -> m.head == 'a' && m.tail == "" + assert $ case uncons "ab" of + Nothing -> false + Just m -> m.head == 'a' && m.tail == "b" + + log "takeWhile" + assert $ takeWhile (\c -> true) "abc" == "abc" + assert $ takeWhile (\c -> false) "abc" == "" + assert $ takeWhile (\c -> c /= 'b') "aabbcc" == "aa" + + log "dropWhile" + assert $ dropWhile (\c -> true) "abc" == "" + assert $ dropWhile (\c -> false) "abc" == "abc" + assert $ dropWhile (\c -> c /= 'b') "aabbcc" == "bbcc" + + log "stripPrefix" + assert $ stripPrefix "" "" == Just "" + assert $ stripPrefix "" "abc" == Just "abc" + assert $ stripPrefix "a" "abc" == Just "bc" + assert $ stripPrefix "!" "abc" == Nothing + assert $ stripPrefix "!" "" == Nothing + + log "fromCharArray" + assert $ fromCharArray [] == "" + assert $ fromCharArray ['a', 'b'] == "ab" + + log "contains" + assert $ contains "" "" + assert $ contains "" "abcd" + assert $ contains "bc" "abcd" + assert $ not (contains "cb" "abcd") + + log "indexOf" + assert $ indexOf "" "" == Just 0 + assert $ indexOf "" "abcd" == Just 0 + assert $ indexOf "bc" "abcd" == Just 1 + assert $ indexOf "cb" "abcd" == Nothing + + log "indexOf'" + assert $ indexOf' "" 0 "" == Just 0 + assert $ indexOf' "" (-1) "ab" == Nothing + assert $ indexOf' "" 0 "ab" == Just 0 + assert $ indexOf' "" 1 "ab" == Just 1 + assert $ indexOf' "" 2 "ab" == Just 2 + assert $ indexOf' "" 3 "ab" == Nothing + assert $ indexOf' "bc" 0 "abcd" == Just 1 + assert $ indexOf' "bc" 1 "abcd" == Just 1 + assert $ indexOf' "bc" 2 "abcd" == Nothing + assert $ indexOf' "cb" 0 "abcd" == Nothing + + log "lastIndexOf" + assert $ lastIndexOf "" "" == Just 0 + assert $ lastIndexOf "" "abcd" == Just 4 + assert $ lastIndexOf "bc" "abcd" == Just 1 + assert $ lastIndexOf "cb" "abcd" == Nothing + + log "lastIndexOf'" + assert $ lastIndexOf' "" 0 "" == Just 0 + assert $ lastIndexOf' "" (-1) "ab" == Nothing + assert $ lastIndexOf' "" 0 "ab" == Just 0 + assert $ lastIndexOf' "" 1 "ab" == Just 1 + assert $ lastIndexOf' "" 2 "ab" == Just 2 + assert $ lastIndexOf' "" 3 "ab" == Nothing + assert $ lastIndexOf' "bc" 0 "abcd" == Nothing + assert $ lastIndexOf' "bc" 1 "abcd" == Just 1 + assert $ lastIndexOf' "bc" 2 "abcd" == Just 1 + assert $ lastIndexOf' "cb" 0 "abcd" == Nothing + + log "length" + assert $ length "" == 0 + assert $ length "a" == 1 + assert $ length "ab" == 2 + + log "localeCompare" + assert $ localeCompare "" "" == EQ + assert $ localeCompare "a" "a" == EQ + assert $ localeCompare "a" "b" == LT + assert $ localeCompare "b" "a" == GT + + log "replace" + assert $ replace "b" "" "abc" == "ac" + assert $ replace "b" "!" "abc" == "a!c" + assert $ replace "d" "!" "abc" == "abc" + + log "take" + assert $ take 0 "ab" == "" + assert $ take 1 "ab" == "a" + assert $ take 2 "ab" == "ab" + assert $ take 3 "ab" == "ab" + + log "drop" + assert $ drop 0 "ab" == "ab" + assert $ drop 1 "ab" == "b" + assert $ drop 2 "ab" == "" + assert $ drop 3 "ab" == "" + + log "count" + assert $ count (\c -> true) "" == 0 + assert $ count (\c -> true) "ab" == 2 + assert $ count (\c -> false) "ab" == 0 + assert $ count (\c -> c == 'a') "aabbcc" == 2 + assert $ count (\c -> c == 'b') "aabbcc" == 0 + assert $ count (\c -> c /= 'a') "aabbcc" == 0 + assert $ count (\c -> c /= 'b') "aabbcc" == 2 + + log "split" + assert $ split "" "" == [] + assert $ split "" "a" == ["a"] + assert $ split "" "ab" == ["a", "b"] + assert $ split "b" "aabcc" == ["aa", "cc"] + assert $ split "d" "abc" == ["abc"] + + log "toCharArray" + assert $ toCharArray "" == [] + assert $ toCharArray "a" == ['a'] + assert $ toCharArray "ab" == ['a', 'b'] + + log "toLower" + assert $ toLower "bAtMaN" == "batman" + + log "toUpper" + assert $ toUpper "bAtMaN" == "BATMAN" + + log "trim" + assert $ trim " abc " == "abc" + + log "joinWith" + assert $ joinWith "" [] == "" + assert $ joinWith "" ["a", "b"] == "ab" + assert $ joinWith "--" ["a", "b", "c"] == "a--b--c" + diff --git a/test/Test/Data/String/Regex.purs b/test/Test/Data/String/Regex.purs new file mode 100644 index 0000000..bcf708a --- /dev/null +++ b/test/Test/Data/String/Regex.purs @@ -0,0 +1,31 @@ +module Test.Data.String.Regex (testStringRegex) where + +import Prelude +import Data.Maybe +import Control.Monad.Eff.Console (log) +import Data.String.Regex +import Test.Assert (assert) + +testStringRegex = do + log "regex" + assert $ test (regex "^a" noFlags) "abc" + assert $ not (test (regex "^b" noFlags) "abc") + + log "match" + assert $ match (regex "^abc$" noFlags) "abc" == Just [Just "abc"] + + log "replace" + assert $ replace (regex "-" noFlags) "!" "a-b-c" == "a!b-c" + + log "replace'" + assert $ replace' (regex "-" noFlags) (\s xs -> "!") "a-b-c" == "a!b-c" + + log "search" + assert $ search (regex "b" noFlags) "abc" == Just 1 + assert $ search (regex "d" noFlags) "abc" == Nothing + + log "split" + assert $ split (regex "" noFlags) "" == [] + assert $ split (regex "" noFlags) "abc" == ["a", "b", "c"] + assert $ split (regex "b" noFlags) "" == [""] + assert $ split (regex "b" noFlags) "abc" == ["a", "c"] diff --git a/test/Test/Data/String/Unsafe.purs b/test/Test/Data/String/Unsafe.purs new file mode 100644 index 0000000..de9a53c --- /dev/null +++ b/test/Test/Data/String/Unsafe.purs @@ -0,0 +1,18 @@ +module Test.Data.String.Unsafe (testStringUnsafe) where + +import Prelude +import Control.Monad.Eff.Console (log) +import Data.String.Unsafe +import Test.Assert (assert) + +testStringUnsafe = do + log "charCodeAt" + assert $ charCodeAt 0 "ab" == 97 + assert $ charCodeAt 1 "ab" == 98 + + log "charAt" + assert $ charAt 0 "ab" == 'a' + assert $ charAt 1 "ab" == 'b' + + log "char" + assert $ char "a" == 'a' diff --git a/test/Test/Main.purs b/test/Test/Main.purs new file mode 100644 index 0000000..78bbcf2 --- /dev/null +++ b/test/Test/Main.purs @@ -0,0 +1,13 @@ +module Test.Main where + +import Prelude +import Test.Data.Char +import Test.Data.String +import Test.Data.String.Unsafe +import Test.Data.String.Regex + +main = do + testChar + testString + testStringUnsafe + testStringRegex