diff --git a/.eslintrc.json b/.eslintrc.json index 84cef4f..1c6afb9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,11 +1,9 @@ { "parserOptions": { - "ecmaVersion": 5 + "ecmaVersion": 6, + "sourceType": "module" }, "extends": "eslint:recommended", - "env": { - "commonjs": true - }, "rules": { "strict": [2, "global"], "block-scoped-var": 2, diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4435abb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +**Description of the change** + +Clearly and concisely describe the purpose of the pull request. If this PR relates to an existing issue or change proposal, please link to it. Include any other background context that would help reviewers understand the motivation for this PR. + +--- + +**Checklist:** + +- [ ] Added the change to the changelog's "Unreleased" section with a reference to this PR (e.g. "- Made a change (#0000)") +- [ ] Linked any existing issues or proposals that this pull request should close +- [ ] Updated or added relevant documentation +- [ ] Added a test for the contribution (if applicable) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c69237a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: purescript-contrib/setup-purescript@main + with: + purescript: "unstable" + + - uses: actions/setup-node@v2 + with: + node-version: "14.x" + + - name: Install dependencies + run: | + npm install -g bower + npm install + bower install --production + + - name: Build source + run: npm run-script build + + - name: Run tests + run: | + bower install + npm run-script test --if-present diff --git a/.gitignore b/.gitignore index 332b6cf..b846b63 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ /.* !/.gitignore !/.eslintrc.json -!/.travis.yml +!/.github/ /bower_components/ /node_modules/ /output/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8daa38c..0000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: node_js -dist: trusty -sudo: required -node_js: stable -env: - - PATH=$HOME/purescript:$PATH -install: - - TAG=$(basename $(curl --location --silent --output /dev/null -w %{url_effective} https://github.com/purescript/purescript/releases/latest)) - - curl --location --output $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz - - tar -xvf $HOME/purescript.tar.gz -C $HOME/ - - chmod a+x $HOME/purescript - - npm install -g bower - - npm install -script: - - bower install --production - - npm run -s build - - bower install - - npm -s test -after_success: -- >- - test $TRAVIS_TAG && - echo $GITHUB_TOKEN | pulp login && - echo y | pulp publish --no-push diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..878d55d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,251 @@ +# Changelog + +Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +Breaking changes: + +New features: + +Bugfixes: + +Other improvements: +- Redefine `Data.String.NonEmpty.CodeUnits.fromFoldable1` in terms of `singleton` (#168 by @postsolar) + +## [v6.0.1](https://github.com/purescript/purescript-strings/releases/tag/v6.0.1) - 2022-08-16 + +Bugfixes: +- Fix `Char`'s `toEnum` implementation (#163 by @JordanMartinez) + +## [v6.0.0](https://github.com/purescript/purescript-strings/releases/tag/v6.0.0) - 2022-04-27 + +Breaking changes: +- Migrate FFI to ES modules (#158 by @kl0tl and @JordanMartinez) +- Replaced polymorphic proxies with monomorphic `Proxy` (#158 by @JordanMartinez) +- In `slice`, drop bounds checking and `Maybe` return type (#145 by Quelklef) + +New features: + +Bugfixes: + +Other improvements: +- Surround code with backticks in documentation (#148) +- Make `RegexFlags` a `newtype` and a `Newtype` instance for it(#159 by @mhmdanas) + +## [v5.0.0](https://github.com/purescript/purescript-strings/releases/tag/v5.0.0) - 2021-02-26 + +Breaking changes: +- Added support for PureScript 0.14 and dropped support for all previous versions (#129) +- Updated `replace'` to reflect the existence of optional capturing groups (#126) + +New features: +- Replaced `unsafeCoerce` with `coerce` where appropriate (#130) +- Replaced monomorphic proxies with `Type.Proxy.Proxy` and polymorphic variables (#134) +- Added a dotAll regexp flag (#133) + +Bugfixes: +- Removed the bounds check from the foreign implementation of `lastIndexOf'` (#137) + +Other improvements: +- Fix line endings to match overall project style (#132) +- Removed references to `codePointToInt`, which no longer exists (#135) +- Migrated CI to GitHub Actions and updated installation instructions to use Spago (#136) +- Added a changelog and pull request template (#140, #141) + +## [v4.0.2](https://github.com/purescript/purescript-strings/releases/tag/v4.0.2) - 2020-05-13 + +- Improved performance for `stripPrefix` / `stripSuffix` (#123, @michaelficarra) + +## [v4.0.1](https://github.com/purescript/purescript-strings/releases/tag/v4.0.1) - 2018-11-11 + +- Fixed out of bounds access in `unsafeCodePointAt0Fallback` (@zyla) +- Fixed `slice` when end index equals string length (@abaco) + +## [v4.0.0](https://github.com/purescript/purescript-strings/releases/tag/v4.0.0) - 2018-05-23 + +- Updated for PureScript 0.12 +- `splitAt` now always returns a value (#78, @MonoidMusician) +- Added `slice` (@themattchan) +- Added more `String` `Gen`s to correspond with `Char` `Gen`s (@matthewleon) +- `Regex` `match` now returns `NonEmptyArray` +- All string functions now operate on code points now rather than code units. The old functions are available via the `.CodeUnits` modules +- `fromCharCode` can return `Nothing` now if given a value out of range + +## [v3.5.0](https://github.com/purescript/purescript-strings/releases/tag/v3.5.0) - 2018-02-12 + +- Added `Data.String.NonEmpty` + +## [v3.4.0](https://github.com/purescript/purescript-strings/releases/tag/v3.4.0) - 2017-12-28 + +- Add `Show CodePoint` instance (@csicar) +- Add `codePointFromChar` (@csicar) +- Expanded docs for most functions in `Data.String` and `Data.String.CodePoints` (@csicar) + +## [v3.3.2](https://github.com/purescript/purescript-strings/releases/tag/v3.3.2) - 2017-11-19 + +- Performance improvement in `Data.String.Regex.match` (@fehrenbach) + +## [v3.3.1](https://github.com/purescript/purescript-strings/releases/tag/v3.3.1) - 2017-08-06 + +- Fix some `Show` instances (@Rufflewind) + +## [v3.3.0](https://github.com/purescript/purescript-strings/releases/tag/v3.3.0) - 2017-07-10 + +- Add a new module `Data.String.CodePoints`, which treats strings as sequences of Unicode code points rather than sequences of UTF-16 code units. In the future we may swap this module with `Data.String`. (@michaelficarra) +- Fix a typo in the documentation (@ijks) + +## [v3.2.1](https://github.com/purescript/purescript-strings/releases/tag/v3.2.1) - 2017-06-06 + +- Ensure `genString` behaves the same regardless of the `MonadGen` implementation of `chooseInt` when `max < min` + +## [v3.2.0](https://github.com/purescript/purescript-strings/releases/tag/v3.2.0) - 2017-06-05 + +- Generated strings from `genString` now vary in length +- Added additional `Char` generators + +## [v3.1.0](https://github.com/purescript/purescript-strings/releases/tag/v3.1.0) - 2017-04-28 + +- Added some generator functions - introduced `Data.String.Gen` and `Data.Char.Gen` + +## [v3.0.0](https://github.com/purescript/purescript-strings/releases/tag/v3.0.0) - 2017-03-26 + +- Updated for PureScript 0.11 + +## [v2.1.0](https://github.com/purescript/purescript-strings/releases/tag/v2.1.0) - 2016-12-25 + +- Added `unsafeRegex` (@rightfold) + +## [v2.0.2](https://github.com/purescript/purescript-strings/releases/tag/v2.0.2) - 2016-10-26 + +- Documentation fix for `split` #70 (@leighman) + +## [v2.0.1](https://github.com/purescript/purescript-strings/releases/tag/v2.0.1) - 2016-10-08 + +- Improved `null` check implementation (@Risto-Stevcev) + +## [v2.0.0](https://github.com/purescript/purescript-strings/releases/tag/v2.0.0) - 2016-10-08 + +- Updated dependencies +- `Pattern` and `Replacement` newtypes are now used to distinguish between arguments when a function accepts multiple strings +- `RegexFlags` have been reworked as a monoid (@Risto-Stevcev) + +## [v1.1.0](https://github.com/purescript/purescript-strings/releases/tag/v1.1.0) - 2016-07-20 + +- Restored export of the `count` function. + +## [v1.0.0](https://github.com/purescript/purescript-strings/releases/tag/v1.0.0) - 2016-06-01 + +This release is intended for the PureScript 0.9.1 compiler and newer. + +**Note**: The v1.0.0 tag is not meant to indicate the library is β€œfinished”, the core libraries are all being bumped to this for the 0.9 compiler release so as to use semver more correctly. + +## [v0.7.1](https://github.com/purescript/purescript-strings/releases/tag/v0.7.1) - 2015-11-20 + +- Removed unused imports (@tfausak) + +## [v0.7.0](https://github.com/purescript/purescript-strings/releases/tag/v0.7.0) - 2015-08-13 + +- Removed orphan (and incorrect) `Bounded Char` instance + +## [v0.6.0](https://github.com/purescript/purescript-strings/releases/tag/v0.6.0) - 2015-08-02 + +- Added `toLower` and `toUpper` to `Data.Char` +- `search` in `Data.String.Regex` now returns `Maybe` result rather than using -1 for failure +- Added test suite + +All updates by @LiamGoodacre + +## [v0.5.5](https://github.com/purescript/purescript-strings/releases/tag/v0.5.5) - 2015-07-28 + +Add `stripSuffix`. + +## [v0.5.4](https://github.com/purescript/purescript-strings/releases/tag/v0.5.4) - 2015-07-18 + +- Removed duplicate `Show` instance for `Char` (@anttih) + +## [v0.5.3](https://github.com/purescript/purescript-strings/releases/tag/v0.5.3) - 2015-07-10 + +Add `stripPrefix` (@hdgarrood) + +## [v0.5.2](https://github.com/purescript/purescript-strings/releases/tag/v0.5.2) - 2015-07-07 + +- Fixed `char` and `charCodeAt` in `Data.String.Unsafe` #36 (@stkb) + +## [v0.5.1](https://github.com/purescript/purescript-strings/releases/tag/v0.5.1) - 2015-07-06 + +- Fixed missing `count` implementation (@qxjit) + +## [v0.5.0](https://github.com/purescript/purescript-strings/releases/tag/v0.5.0) - 2015-06-30 + +This release works with versions 0.7.\* of the PureScript compiler. It will not work with older versions. If you are using an older version, you should require an older, compatible version of this library. + +- Fixed various FFI exports (@sharkdp) +- Fixed `localeCompare` + +## [v0.4.5](https://github.com/purescript/purescript-strings/releases/tag/v0.4.5) - 2015-03-23 + +- Added `char` to `Data.String.Unsafe` (@brainrape) +- Functions in `Data.String.Unsafe` now throw errors immediately when given unacceptable inputs (@brainrape) + +## [v0.4.4](https://github.com/purescript/purescript-strings/releases/tag/v0.4.4) - 2015-03-22 + +- Updated docs + +## [v0.4.3](https://github.com/purescript/purescript-strings/releases/tag/v0.4.3) - 2015-02-18 + +- Added `noFlags` record for default regex flags (@fresheyeball) + +## [v0.4.2](https://github.com/purescript/purescript-strings/releases/tag/v0.4.2) - 2014-11-28 + +- Added `null`, `singleton`, `uncons`, `takeWhile`, and `dropWhile` to `Data.String` (@NightRa) + +## [v0.4.1](https://github.com/purescript/purescript-strings/releases/tag/v0.4.1) - 2014-11-06 + +- Use ternary operator in JavaScript output (@davidchambers) + +## [v0.4.0](https://github.com/purescript/purescript-strings/releases/tag/v0.4.0) - 2014-10-27 + +- Made `charCodeAt` safe, added unsafe versions of `charAt`, `charCodeAt` (@garyb) + +## [v0.3.3](https://github.com/purescript/purescript-strings/releases/tag/v0.3.3) - 2014-10-24 + +- Added `split` to `Data.String.Regex` (@davidchambers) + +## [v0.3.2](https://github.com/purescript/purescript-strings/releases/tag/v0.3.2) - 2014-10-16 + +- Added essential instances for `Char` (@jdegoes) + +## [v0.3.1](https://github.com/purescript/purescript-strings/releases/tag/v0.3.1) - 2014-10-15 + +- Fixed typo in `fromCharArray` FFI implementation (@jdegoes) + +## [v0.3.0](https://github.com/purescript/purescript-strings/releases/tag/v0.3.0) - 2014-10-14 + +- Introduced `Char` newtype and corresponding functions (@jdegoes) +- Made `charAt` safe - breaking change (@jdegoes) + +## [v0.2.1](https://github.com/purescript/purescript-strings/releases/tag/v0.2.1) - 2014-07-21 + +- Fix typo in FFI definition for `flags` (@garyb) + +## [v0.2.0](https://github.com/purescript/purescript-strings/releases/tag/v0.2.0) - 2014-07-20 + +- `Show` instance for `Regex` (@michaelficarra) +- `Regex` now has `RegexFlags` rather than a string for options (@michaelficarra) + +## [v0.1.3](https://github.com/purescript/purescript-strings/releases/tag/v0.1.3) - 2014-05-04 + +- Renamed `Data.String.Regex.replaceR` to `replace`, added `replace'` which uses a function to construct replacements for matches. + +## [v0.1.2](https://github.com/purescript/purescript-strings/releases/tag/v0.1.2) - 2014-04-30 + +- Added `indexOf'` and `lastIndexOf'` (paf31) + +## [v0.1.1](https://github.com/purescript/purescript-strings/releases/tag/v0.1.1) - 2014-04-27 + +- Swapped `joinWith` arguments for better style + +## [v0.1.0](https://github.com/purescript/purescript-strings/releases/tag/v0.1.0) - 2014-04-25 + +- Initial release diff --git a/README.md b/README.md index 0565699..73292c1 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ # purescript-strings [![Latest release](http://img.shields.io/github/release/purescript/purescript-strings.svg)](https://github.com/purescript/purescript-strings/releases) -[![Build status](https://travis-ci.org/purescript/purescript-strings.svg?branch=master)](https://travis-ci.org/purescript/purescript-strings) +[![Build status](https://github.com/purescript/purescript-strings/workflows/CI/badge.svg?branch=master)](https://github.com/purescript/purescript-strings/actions?query=workflow%3ACI+branch%3Amaster) +[![Pursuit](https://pursuit.purescript.org/packages/purescript-strings/badge)](https://pursuit.purescript.org/packages/purescript-strings) String and char utility functions, regular expressions. ## Installation ``` -bower install purescript-strings +spago install strings ``` ## Documentation diff --git a/bower.json b/bower.json index ec7fb7f..85a17c5 100644 --- a/bower.json +++ b/bower.json @@ -4,7 +4,7 @@ "license": "BSD-3-Clause", "repository": { "type": "git", - "url": "git://github.com/purescript/purescript-strings.git" + "url": "https://github.com/purescript/purescript-strings.git" }, "ignore": [ "**/.*", @@ -16,26 +16,26 @@ "package.json" ], "dependencies": { - "purescript-arrays": "^5.0.0", - "purescript-control": "^4.0.0", - "purescript-either": "^4.0.0", - "purescript-enums": "^4.0.0", - "purescript-foldable-traversable": "^4.0.0", - "purescript-gen": "^2.0.0", - "purescript-integers": "^4.0.0", - "purescript-maybe": "^4.0.0", - "purescript-newtype": "^3.0.0", - "purescript-nonempty": "^5.0.0", - "purescript-partial": "^2.0.0", - "purescript-prelude": "^4.0.0", - "purescript-tailrec": "^4.0.0", - "purescript-tuples": "^5.0.0", - "purescript-unfoldable": "^4.0.0", - "purescript-unsafe-coerce": "^4.0.0" + "purescript-arrays": "^7.0.0", + "purescript-control": "^6.0.0", + "purescript-either": "^6.0.0", + "purescript-enums": "^6.0.1", + "purescript-foldable-traversable": "^6.0.0", + "purescript-gen": "^4.0.0", + "purescript-integers": "^6.0.0", + "purescript-maybe": "^6.0.0", + "purescript-newtype": "^5.0.0", + "purescript-nonempty": "^7.0.0", + "purescript-partial": "^4.0.0", + "purescript-prelude": "^6.0.0", + "purescript-tailrec": "^6.0.0", + "purescript-tuples": "^7.0.0", + "purescript-unfoldable": "^6.0.0", + "purescript-unsafe-coerce": "^6.0.0" }, "devDependencies": { - "purescript-assert": "^4.0.0", - "purescript-console": "^4.0.0", - "purescript-minibench": "^2.0.0" + "purescript-assert": "^6.0.0", + "purescript-console": "^6.0.0", + "purescript-minibench": "^4.0.0" } } diff --git a/package.json b/package.json index 28a3fd3..cffd45e 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,15 @@ "clean": "rimraf output && rimraf .pulp-cache", "build": "eslint src && pulp build -- --censor-lib --strict", "test": "pulp test && npm run test:run:without_codePointAt", - "test:run:without_codePointAt": "node -e \"delete String.prototype.codePointAt; require('./output/Test.Main/index.js').main();\"", + "test:run:without_codePointAt": "node -e \"delete String.prototype.codePointAt; import('./output/Test.Main/index.js').then(m => m.main());\"", "bench:build": "purs compile 'bench/**/*.purs' 'src/**/*.purs' 'bower_components/*/src/**/*.purs'", "bench:run": "node --expose-gc -e 'require(\"./output/Bench.Main/index.js\").main()'", "bench": "npm run bench:build && npm run bench:run" }, "devDependencies": { - "eslint": "^4.19.1", - "pulp": "^12.2.0", - "purescript-psa": "^0.6.0", - "rimraf": "^2.6.2" + "eslint": "^7.15.0", + "pulp": "16.0.0-0", + "purescript-psa": "^0.8.2", + "rimraf": "^3.0.2" } } diff --git a/src/Data/String/CodePoints.js b/src/Data/String/CodePoints.js index eead7f6..ebd9e39 100644 --- a/src/Data/String/CodePoints.js +++ b/src/Data/String/CodePoints.js @@ -1,4 +1,3 @@ -"use strict"; /* global Symbol */ var hasArrayFrom = typeof Array.from === "function"; @@ -10,13 +9,13 @@ var hasStringIterator = var hasFromCodePoint = typeof String.prototype.fromCodePoint === "function"; var hasCodePointAt = typeof String.prototype.codePointAt === "function"; -exports._unsafeCodePointAt0 = function (fallback) { +export const _unsafeCodePointAt0 = function (fallback) { return hasCodePointAt ? function (str) { return str.codePointAt(0); } : fallback; }; -exports._codePointAt = function (fallback) { +export const _codePointAt = function (fallback) { return function (Just) { return function (Nothing) { return function (unsafeCodePointAt0) { @@ -40,7 +39,7 @@ exports._codePointAt = function (fallback) { }; }; -exports._countPrefix = function (fallback) { +export const _countPrefix = function (fallback) { return function (unsafeCodePointAt0) { if (hasStringIterator) { return function (pred) { @@ -59,7 +58,7 @@ exports._countPrefix = function (fallback) { }; }; -exports._fromCodePointArray = function (singleton) { +export const _fromCodePointArray = function (singleton) { return hasFromCodePoint ? function (cps) { // Function.prototype.apply will fail for very large second parameters, @@ -74,11 +73,11 @@ exports._fromCodePointArray = function (singleton) { }; }; -exports._singleton = function (fallback) { +export const _singleton = function (fallback) { return hasFromCodePoint ? String.fromCodePoint : fallback; }; -exports._take = function (fallback) { +export const _take = function (fallback) { return function (n) { if (hasStringIterator) { return function (str) { @@ -96,7 +95,7 @@ exports._take = function (fallback) { }; }; -exports._toCodePointArray = function (fallback) { +export const _toCodePointArray = function (fallback) { return function (unsafeCodePointAt0) { if (hasArrayFrom) { return function (str) { diff --git a/src/Data/String/CodePoints.purs b/src/Data/String/CodePoints.purs index 9083c10..610e497 100644 --- a/src/Data/String/CodePoints.purs +++ b/src/Data/String/CodePoints.purs @@ -42,7 +42,7 @@ import Data.String.Unsafe as Unsafe import Data.Tuple (Tuple(..)) import Data.Unfoldable (unfoldr) --- | CodePoint is an Int bounded between 0 and 0x10FFFF, corresponding to +-- | CodePoint is an `Int` bounded between `0` and `0x10FFFF`, corresponding to -- | Unicode code points. newtype CodePoint = CodePoint Int @@ -67,7 +67,7 @@ instance boundedEnumCodePoint :: BoundedEnum CodePoint where | n >= 0 && n <= 0x10FFFF = Just (CodePoint n) | otherwise = Nothing --- | Creates a CodePoint from a given Char. +-- | Creates a `CodePoint` from a given `Char`. -- | -- | ```purescript -- | >>> codePointFromChar 'B' @@ -178,7 +178,7 @@ codePointAtFallback n s = case uncons s of _ -> Nothing -- | Returns a record with the first code point and the remaining code points --- | of the string. Returns Nothing if the string is empty. Operates in +-- | of the string. Returns `Nothing` if the string is empty. Operates in -- | constant space and time. -- | -- | ```purescript @@ -220,7 +220,7 @@ length = Array.length <<< toCodePointArray -- | time linear to the length of the string. -- | -- | ```purescript --- | >>> countPrefix (\c -> codePointToInt c == 0x1D400) "𝐀𝐀 b c 𝐀" +-- | >>> countPrefix (\c -> fromEnum c == 0x1D400) "𝐀𝐀 b c 𝐀" -- | 2 -- | ``` -- | @@ -243,7 +243,7 @@ countTail p s accum = case uncons s of _ -> accum -- | Returns the number of code points preceding the first match of the given --- | pattern in the string. Returns Nothing when no matches are found. +-- | pattern in the string. Returns `Nothing` when no matches are found. -- | -- | ```purescript -- | >>> indexOf (Pattern "𝐀") "b 𝐀𝐀 c 𝐀" @@ -257,7 +257,7 @@ indexOf p s = (\i -> length (CU.take i s)) <$> CU.indexOf p s -- | Returns the number of code points preceding the first match of the given -- | pattern in the string. Pattern matches preceding the given index will be --- | ignored. Returns Nothing when no matches are found. +-- | ignored. Returns `Nothing` when no matches are found. -- | -- | ```purescript -- | >>> indexOf' (Pattern "𝐀") 4 "b 𝐀𝐀 c 𝐀" @@ -272,7 +272,7 @@ indexOf' p i s = (\k -> i + length (CU.take k s')) <$> CU.indexOf p s' -- | Returns the number of code points preceding the last match of the given --- | pattern in the string. Returns Nothing when no matches are found. +-- | pattern in the string. Returns `Nothing` when no matches are found. -- | -- | ```purescript -- | >>> lastIndexOf (Pattern "𝐀") "b 𝐀𝐀 c 𝐀" @@ -286,11 +286,23 @@ lastIndexOf p s = (\i -> length (CU.take i s)) <$> CU.lastIndexOf p s -- | Returns the number of code points preceding the first match of the given -- | pattern in the string. Pattern matches following the given index will be --- | ignored. Returns Nothing when no matches are found. +-- | ignored. +-- | +-- | Giving a negative index is equivalent to giving 0 and giving an index +-- | greater than the number of code points in the string is equivalent to +-- | searching in the whole string. +-- | +-- | Returns `Nothing` when no matches are found. -- | -- | ```purescript +-- | >>> lastIndexOf' (Pattern "𝐀") (-1) "b 𝐀𝐀 c 𝐀" +-- | Nothing +-- | >>> lastIndexOf' (Pattern "𝐀") 0 "b 𝐀𝐀 c 𝐀" +-- | Nothing -- | >>> lastIndexOf' (Pattern "𝐀") 5 "b 𝐀𝐀 c 𝐀" -- | Just 3 +-- | >>> lastIndexOf' (Pattern "𝐀") 8 "b 𝐀𝐀 c 𝐀" +-- | Just 7 -- | >>> lastIndexOf' (Pattern "o") 5 "b 𝐀𝐀 c 𝐀" -- | Nothing -- | ``` @@ -302,7 +314,7 @@ lastIndexOf' p i s = -- | Returns a string containing the given number of code points from the -- | beginning of the given string. If the string does not have that many code --- | points, returns the empty string. Operates in constant space and in time +-- | points, returns the entire string. Operates in constant space and in time -- | linear to the given number. -- | -- | ```purescript @@ -329,7 +341,7 @@ takeFallback n s = case uncons s of -- | in time linear to the length of the string. -- | -- | ```purescript --- | >>> takeWhile (\c -> codePointToInt c == 0x1D400) "𝐀𝐀 b c 𝐀" +-- | >>> takeWhile (\c -> fromEnum c == 0x1D400) "𝐀𝐀 b c 𝐀" -- | "𝐀𝐀" -- | ``` -- | @@ -356,7 +368,7 @@ drop n s = CU.drop (CU.length (take n s)) s -- | to the length of the string. -- | -- | ```purescript --- | >>> dropWhile (\c -> codePointToInt c == 0x1D400) "𝐀𝐀 b c 𝐀" +-- | >>> dropWhile (\c -> fromEnum c == 0x1D400) "𝐀𝐀 b c 𝐀" -- | " b c 𝐀" -- | ``` -- | diff --git a/src/Data/String/CodeUnits.js b/src/Data/String/CodeUnits.js index 870b96f..2608384 100644 --- a/src/Data/String/CodeUnits.js +++ b/src/Data/String/CodeUnits.js @@ -1,18 +1,16 @@ -"use strict"; - -exports.fromCharArray = function (a) { +export const fromCharArray = function (a) { return a.join(""); }; -exports.toCharArray = function (s) { +export const toCharArray = function (s) { return s.split(""); }; -exports.singleton = function (c) { +export const singleton = function (c) { return c; }; -exports._charAt = function (just) { +export const _charAt = function (just) { return function (nothing) { return function (i) { return function (s) { @@ -22,7 +20,7 @@ exports._charAt = function (just) { }; }; -exports._toChar = function (just) { +export const _toChar = function (just) { return function (nothing) { return function (s) { return s.length === 1 ? just(s) : nothing; @@ -30,11 +28,11 @@ exports._toChar = function (just) { }; }; -exports.length = function (s) { +export const length = function (s) { return s.length; }; -exports.countPrefix = function (p) { +export const countPrefix = function (p) { return function (s) { var i = 0; while (i < s.length && p(s.charAt(i))) i++; @@ -42,7 +40,7 @@ exports.countPrefix = function (p) { }; }; -exports._indexOf = function (just) { +export const _indexOf = function (just) { return function (nothing) { return function (x) { return function (s) { @@ -53,7 +51,7 @@ exports._indexOf = function (just) { }; }; -exports._indexOfStartingAt = function (just) { +export const _indexOfStartingAt = function (just) { return function (nothing) { return function (x) { return function (startAt) { @@ -67,7 +65,7 @@ exports._indexOfStartingAt = function (just) { }; }; -exports._lastIndexOf = function (just) { +export const _lastIndexOf = function (just) { return function (nothing) { return function (x) { return function (s) { @@ -78,12 +76,11 @@ exports._lastIndexOf = function (just) { }; }; -exports._lastIndexOfStartingAt = function (just) { +export const _lastIndexOfStartingAt = function (just) { return function (nothing) { 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); }; @@ -92,19 +89,19 @@ exports._lastIndexOfStartingAt = function (just) { }; }; -exports.take = function (n) { +export const take = function (n) { return function (s) { return s.substr(0, n); }; }; -exports.drop = function (n) { +export const drop = function (n) { return function (s) { return s.substring(n); }; }; -exports._slice = function (b) { +export const slice = function (b) { return function (e) { return function (s) { return s.slice(b,e); @@ -112,7 +109,7 @@ exports._slice = function (b) { }; }; -exports.splitAt = function (i) { +export const splitAt = function (i) { return function (s) { return { before: s.substring(0, i), after: s.substring(i) }; }; diff --git a/src/Data/String/CodeUnits.purs b/src/Data/String/CodeUnits.purs index cc919e0..5fed21f 100644 --- a/src/Data/String/CodeUnits.purs +++ b/src/Data/String/CodeUnits.purs @@ -37,7 +37,7 @@ import Data.String.Unsafe as U ------------------------------------------------------------------------------- -- | If the string starts with the given prefix, return the portion of the --- | string left after removing it, as a Just value. Otherwise, return Nothing. +-- | string left after removing it, as a `Just` value. Otherwise, return `Nothing`. -- | -- | ```purescript -- | stripPrefix (Pattern "http:") "http://purescript.org" == Just "//purescript.org" @@ -215,14 +215,21 @@ foreign import _lastIndexOf -> Maybe Int -- | Returns the index of the last occurrence of the pattern in the --- | given string, starting at the specified index --- | and searching backwards towards the beginning of the string. +-- | given string, starting at the specified index and searching +-- | backwards towards the beginning of the string. +-- | +-- | Starting at a negative index is equivalent to starting at 0 and +-- | starting at an index greater than the string length is equivalent +-- | to searching in the whole string. +-- | -- | Returns `Nothing` if there is no match. -- | -- | ```purescript +-- | lastIndexOf' (Pattern "a") (-1) "ababa" == Just 0 -- | lastIndexOf' (Pattern "a") 1 "ababa" == Just 0 -- | lastIndexOf' (Pattern "a") 3 "ababa" == Just 2 -- | lastIndexOf' (Pattern "a") 4 "ababa" == Just 4 +-- | lastIndexOf' (Pattern "a") 5 "ababa" == Just 4 -- | ``` -- | lastIndexOf' :: Pattern -> Int -> String -> Maybe Int @@ -291,30 +298,17 @@ dropWhile p s = drop (countPrefix p s) s -- | Returns the substring at indices `[begin, end)`. -- | If either index is negative, it is normalised to `length s - index`, --- | where `s` is the input string. `Nothing` is returned if either +-- | where `s` is the input string. `""` is returned if either -- | index is out of bounds or if `begin > end` after normalisation. -- | -- | ```purescript --- | slice 0 0 "purescript" == Just "" --- | slice 0 1 "purescript" == Just "p" --- | slice 3 6 "purescript" == Just "esc" --- | slice (-4) (-1) "purescript" == Just "rip" --- | slice (-4) 3 "purescript" == Nothing +-- | slice 0 0 "purescript" == "" +-- | slice 0 1 "purescript" == "p" +-- | slice 3 6 "purescript" == "esc" +-- | slice (-4) (-1) "purescript" == "rip" +-- | slice (-4) 3 "purescript" == "" -- | ``` -slice :: Int -> Int -> String -> Maybe String -slice b e s = if b' < 0 || b' >= l || - e' < 0 || e' > l || - b' > e' - then Nothing - else Just (_slice b e s) - where - l = length s - norm x | x < 0 = l + x - | otherwise = x - b' = norm b - e' = norm e - -foreign import _slice :: Int -> Int -> String -> String +foreign import slice :: Int -> Int -> String -> String -- | Splits a string into two substrings, where `before` contains the -- | characters up to (but not including) the given index, and `after` contains diff --git a/src/Data/String/Common.js b/src/Data/String/Common.js index 111c02e..5693585 100644 --- a/src/Data/String/Common.js +++ b/src/Data/String/Common.js @@ -1,6 +1,4 @@ -"use strict"; - -exports._localeCompare = function (lt) { +export const _localeCompare = function (lt) { return function (eq) { return function (gt) { return function (s1) { @@ -13,7 +11,7 @@ exports._localeCompare = function (lt) { }; }; -exports.replace = function (s1) { +export const replace = function (s1) { return function (s2) { return function (s3) { return s3.replace(s1, s2); @@ -21,7 +19,7 @@ exports.replace = function (s1) { }; }; -exports.replaceAll = function (s1) { +export const replaceAll = function (s1) { return function (s2) { return function (s3) { return s3.replace(new RegExp(s1.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"), "g"), s2); // eslint-disable-line no-useless-escape @@ -29,25 +27,25 @@ exports.replaceAll = function (s1) { }; }; -exports.split = function (sep) { +export const split = function (sep) { return function (s) { return s.split(sep); }; }; -exports.toLower = function (s) { +export const toLower = function (s) { return s.toLowerCase(); }; -exports.toUpper = function (s) { +export const toUpper = function (s) { return s.toUpperCase(); }; -exports.trim = function (s) { +export const trim = function (s) { return s.trim(); }; -exports.joinWith = function (s) { +export const joinWith = function (s) { return function (xs) { return xs.join(s); }; diff --git a/src/Data/String/NonEmpty/CodePoints.purs b/src/Data/String/NonEmpty/CodePoints.purs index 5357851..7b5328a 100644 --- a/src/Data/String/NonEmpty/CodePoints.purs +++ b/src/Data/String/NonEmpty/CodePoints.purs @@ -33,19 +33,21 @@ import Data.Semigroup.Foldable (class Foldable1) import Data.Semigroup.Foldable as F1 import Data.String.CodePoints (CodePoint) import Data.String.CodePoints as CP -import Data.String.NonEmpty.Internal (NonEmptyString, fromString) +import Data.String.NonEmpty.Internal (NonEmptyString(..), fromString) import Data.String.Pattern (Pattern) import Partial.Unsafe (unsafePartial) -import Unsafe.Coerce (unsafeCoerce) +-- For internal use only. Do not export. toNonEmptyString :: String -> NonEmptyString -toNonEmptyString = unsafeCoerce +toNonEmptyString = NonEmptyString +-- For internal use only. Do not export. fromNonEmptyString :: NonEmptyString -> String -fromNonEmptyString = unsafeCoerce +fromNonEmptyString (NonEmptyString s) = s +-- For internal use only. Do not export. liftS :: forall r. (String -> r) -> NonEmptyString -> r -liftS = unsafeCoerce +liftS f (NonEmptyString s) = f s fromCodePointArray :: Array CodePoint -> Maybe NonEmptyString fromCodePointArray = case _ of diff --git a/src/Data/String/NonEmpty/CodeUnits.purs b/src/Data/String/NonEmpty/CodeUnits.purs index 2aa0a6c..4e97244 100644 --- a/src/Data/String/NonEmpty/CodeUnits.purs +++ b/src/Data/String/NonEmpty/CodeUnits.purs @@ -33,20 +33,22 @@ import Data.Maybe (Maybe(..), fromJust) import Data.Semigroup.Foldable (class Foldable1) import Data.Semigroup.Foldable as F1 import Data.String.CodeUnits as CU -import Data.String.NonEmpty.Internal (NonEmptyString, fromString) +import Data.String.NonEmpty.Internal (NonEmptyString(..), fromString) import Data.String.Pattern (Pattern) import Data.String.Unsafe as U import Partial.Unsafe (unsafePartial) -import Unsafe.Coerce (unsafeCoerce) +-- For internal use only. Do not export. toNonEmptyString :: String -> NonEmptyString -toNonEmptyString = unsafeCoerce +toNonEmptyString = NonEmptyString +-- For internal use only. Do not export. fromNonEmptyString :: NonEmptyString -> String -fromNonEmptyString = unsafeCoerce +fromNonEmptyString (NonEmptyString s) = s +-- For internal use only. Do not export. liftS :: forall r. (String -> r) -> NonEmptyString -> r -liftS = unsafeCoerce +liftS f (NonEmptyString s) = f s -- | Creates a `NonEmptyString` from a character array `String`, returning -- | `Nothing` if the input is empty. @@ -88,10 +90,7 @@ snoc c s = toNonEmptyString (s <> CU.singleton c) -- | Creates a `NonEmptyString` from a `Foldable1` container carrying -- | characters. fromFoldable1 :: forall f. Foldable1 f => f Char -> NonEmptyString -fromFoldable1 = F1.fold1 <<< coe - where - coe ∷ f Char -> f NonEmptyString - coe = unsafeCoerce +fromFoldable1 = F1.foldMap1 singleton -- | Converts the `NonEmptyString` into an array of characters. -- | @@ -156,14 +155,21 @@ lastIndexOf :: Pattern -> NonEmptyString -> Maybe Int lastIndexOf = liftS <<< CU.lastIndexOf -- | Returns the index of the last occurrence of the pattern in the --- | given string, starting at the specified index --- | and searching backwards towards the beginning of the string. +-- | given string, starting at the specified index and searching +-- | backwards towards the beginning of the string. +-- | +-- | Starting at a negative index is equivalent to starting at 0 and +-- | starting at an index greater than the string length is equivalent +-- | to searching in the whole string. +-- | -- | Returns `Nothing` if there is no match. -- | -- | ```purescript +-- | lastIndexOf' (Pattern "a") (-1) (NonEmptyString "ababa") == Just 0 -- | lastIndexOf' (Pattern "a") 1 (NonEmptyString "ababa") == Just 0 -- | lastIndexOf' (Pattern "a") 3 (NonEmptyString "ababa") == Just 2 -- | lastIndexOf' (Pattern "a") 4 (NonEmptyString "ababa") == Just 4 +-- | lastIndexOf' (Pattern "a") 5 (NonEmptyString "ababa") == Just 4 -- | ``` lastIndexOf' :: Pattern -> Int -> NonEmptyString -> Maybe Int lastIndexOf' pat = liftS <<< CU.lastIndexOf' pat diff --git a/src/Data/String/NonEmpty/Internal.purs b/src/Data/String/NonEmpty/Internal.purs index bfd2984..8722654 100644 --- a/src/Data/String/NonEmpty/Internal.purs +++ b/src/Data/String/NonEmpty/Internal.purs @@ -1,3 +1,9 @@ +-- | While most of the code in this module is safe, this module does +-- | export a few partial functions and the `NonEmptyString` constructor. +-- | While the partial functions are obvious from the `Partial` constraint in +-- | their type signature, the `NonEmptyString` constructor can be overlooked +-- | when searching for issues in one's code. See the constructor's +-- | documentation for more information. module Data.String.NonEmpty.Internal where import Prelude @@ -8,11 +14,18 @@ import Data.Maybe (Maybe(..), fromJust) import Data.Semigroup.Foldable (class Foldable1) import Data.String as String import Data.String.Pattern (Pattern) -import Data.Symbol (class IsSymbol, SProxy, reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Prim.TypeError as TE +import Type.Proxy (Proxy) import Unsafe.Coerce (unsafeCoerce) -- | A string that is known not to be empty. +-- | +-- | You can use this constructor to create a `NonEmptyString` that isn't +-- | non-empty, breaking the guarantee behind this newtype. It is +-- | provided as an escape hatch mainly for the `Data.NonEmpty.CodeUnits` +-- | and `Data.NonEmpty.CodePoints` modules. Use this at your own risk +-- | when you know what you are doing. newtype NonEmptyString = NonEmptyString String derive newtype instance eqNonEmptyString ∷ Eq NonEmptyString @@ -26,10 +39,10 @@ instance showNonEmptyString :: Show NonEmptyString where -- | -- | ``` purescript -- | something :: NonEmptyString --- | something = nes (SProxy :: SProxy "something") +-- | something = nes (Proxy :: Proxy "something") -- | ``` class MakeNonEmpty (s :: Symbol) where - nes :: SProxy s -> NonEmptyString + nes :: Proxy s -> NonEmptyString instance makeNonEmptyBad :: TE.Fail (TE.Text "Cannot create an NonEmptyString from an empty Symbol") => MakeNonEmpty "" where nes _ = NonEmptyString "" diff --git a/src/Data/String/Regex.js b/src/Data/String/Regex.js index ae40c11..3196034 100644 --- a/src/Data/String/Regex.js +++ b/src/Data/String/Regex.js @@ -1,10 +1,8 @@ -"use strict"; - -exports.showRegexImpl = function (r) { +export const showRegexImpl = function (r) { return "" + r; }; -exports.regexImpl = function (left) { +export const regexImpl = function (left) { return function (right) { return function (s1) { return function (s2) { @@ -18,21 +16,22 @@ exports.regexImpl = function (left) { }; }; -exports.source = function (r) { +export const source = function (r) { return r.source; }; -exports.flagsImpl = function (r) { +export const flagsImpl = function (r) { return { multiline: r.multiline, ignoreCase: r.ignoreCase, global: r.global, + dotAll: r.dotAll, sticky: !!r.sticky, unicode: !!r.unicode }; }; -exports.test = function (r) { +export const test = function (r) { return function (s) { var lastIndex = r.lastIndex; var result = r.test(s); @@ -41,7 +40,7 @@ exports.test = function (r) { }; }; -exports._match = function (just) { +export const _match = function (just) { return function (nothing) { return function (r) { return function (s) { @@ -59,7 +58,7 @@ exports._match = function (just) { }; }; -exports.replace = function (r) { +export const replace = function (r) { return function (s1) { return function (s2) { return s2.replace(r, s1); @@ -67,17 +66,26 @@ exports.replace = function (r) { }; }; -exports.replaceBy = function (r) { - return function (f) { - return function (s2) { - return s2.replace(r, function (match) { - return f(match)(Array.prototype.splice.call(arguments, 1, arguments.length - 3)); - }); +export const _replaceBy = function (just) { + return function (nothing) { + return function (r) { + return function (f) { + return function (s) { + return s.replace(r, function (match) { + var groups = []; + var group, i = 1; + while (typeof (group = arguments[i++]) !== "number") { + groups.push(group == null ? nothing : just(group)); + } + return f(match)(groups); + }); + }; + }; }; }; }; -exports._search = function (just) { +export const _search = function (just) { return function (nothing) { return function (r) { return function (s) { @@ -88,7 +96,7 @@ exports._search = function (just) { }; }; -exports.split = function (r) { +export const split = function (r) { return function (s) { return s.split(r); }; diff --git a/src/Data/String/Regex.purs b/src/Data/String/Regex.purs index 4f2e74f..aae56e1 100644 --- a/src/Data/String/Regex.purs +++ b/src/Data/String/Regex.purs @@ -1,5 +1,5 @@ -- | Wraps Javascript's `RegExp` object that enables matching strings with --- | patternes defined by regular expressions. +-- | patterns defined by regular expressions. -- | For details of the underlying implementation, see [RegExp Reference at MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp). module Data.String.Regex ( Regex(..) @@ -61,6 +61,7 @@ renderFlags (RegexFlags f) = (if f.global then "g" else "") <> (if f.ignoreCase then "i" else "") <> (if f.multiline then "m" else "") <> + (if f.dotAll then "s" else "") <> (if f.sticky then "y" else "") <> (if f.unicode then "u" else "") @@ -70,6 +71,7 @@ parseFlags s = RegexFlags { global: contains (Pattern "g") s , ignoreCase: contains (Pattern "i") s , multiline: contains (Pattern "m") s + , dotAll: contains (Pattern "s") s , sticky: contains (Pattern "y") s , unicode: contains (Pattern "u") s } @@ -93,18 +95,25 @@ foreign import _match match :: Regex -> String -> Maybe (NonEmptyArray (Maybe String)) match = _match Just Nothing --- | Replaces occurences of the `Regex` with the first string. The replacement +-- | Replaces occurrences of the `Regex` with the first string. The replacement -- | string can include special replacement patterns escaped with `"$"`. -- | See [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace). foreign import replace :: Regex -> String -> String -> String --- | Transforms occurences of the `Regex` using a function of the matched --- | substring and a list of submatch strings. --- | See the [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter). -replace' :: Regex -> (String -> Array String -> String) -> String -> String -replace' = replaceBy +foreign import _replaceBy + :: (forall r. r -> Maybe r) + -> (forall r. Maybe r) + -> Regex + -> (String -> Array (Maybe String) -> String) + -> String + -> String -foreign import replaceBy :: Regex -> (String -> Array String -> String) -> String -> String +-- | Transforms occurrences of the `Regex` using a function of the matched +-- | substring and a list of captured substrings of type `Maybe String`, +-- | where `Nothing` represents an unmatched optional capturing group. +-- | See the [reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter). +replace' :: Regex -> (String -> Array (Maybe String) -> String) -> String -> String +replace' = _replaceBy Just Nothing foreign import _search :: (forall r. r -> Maybe r) @@ -118,5 +127,5 @@ foreign import _search search :: Regex -> String -> Maybe Int search = _search Just Nothing --- | Split the string into an array of substrings along occurences of the `Regex`. +-- | Split the string into an array of substrings along occurrences of the `Regex`. foreign import split :: Regex -> String -> Array String diff --git a/src/Data/String/Regex/Flags.purs b/src/Data/String/Regex/Flags.purs index bd14d8c..6d7dd71 100644 --- a/src/Data/String/Regex/Flags.purs +++ b/src/Data/String/Regex/Flags.purs @@ -3,18 +3,22 @@ module Data.String.Regex.Flags where import Prelude import Control.MonadPlus (guard) +import Data.Newtype (class Newtype) import Data.String (joinWith) type RegexFlagsRec = { global :: Boolean , ignoreCase :: Boolean , multiline :: Boolean + , dotAll :: Boolean , sticky :: Boolean , unicode :: Boolean } -- | Flags that control matching. -data RegexFlags = RegexFlags RegexFlagsRec +newtype RegexFlags = RegexFlags RegexFlagsRec + +derive instance newtypeRegexFlags :: Newtype RegexFlags _ -- | All flags set to false. noFlags :: RegexFlags @@ -22,6 +26,7 @@ noFlags = RegexFlags { global: false , ignoreCase: false , multiline: false + , dotAll: false , sticky: false , unicode: false } @@ -32,6 +37,7 @@ global = RegexFlags { global: true , ignoreCase: false , multiline: false + , dotAll: false , sticky: false , unicode: false } @@ -42,6 +48,7 @@ ignoreCase = RegexFlags { global: false , ignoreCase: true , multiline: false + , dotAll: false , sticky: false , unicode: false } @@ -52,6 +59,7 @@ multiline = RegexFlags { global: false , ignoreCase: false , multiline: true + , dotAll: false , sticky: false , unicode: false } @@ -62,6 +70,7 @@ sticky = RegexFlags { global: false , ignoreCase: false , multiline: false + , dotAll: false , sticky: true , unicode: false } @@ -72,15 +81,28 @@ unicode = RegexFlags { global: false , ignoreCase: false , multiline: false + , dotAll: false , sticky: false , unicode: true } +-- | Only dotAll flag set to true +dotAll :: RegexFlags +dotAll = RegexFlags + { global: false + , ignoreCase: false + , multiline: false + , dotAll: true + , sticky: false + , unicode: false + } + instance semigroupRegexFlags :: Semigroup RegexFlags where append (RegexFlags x) (RegexFlags y) = RegexFlags { global: x.global || y.global , ignoreCase: x.ignoreCase || y.ignoreCase , multiline: x.multiline || y.multiline + , dotAll: x.dotAll || y.dotAll , sticky: x.sticky || y.sticky , unicode: x.unicode || y.unicode } @@ -88,13 +110,7 @@ instance semigroupRegexFlags :: Semigroup RegexFlags where instance monoidRegexFlags :: Monoid RegexFlags where mempty = noFlags -instance eqRegexFlags :: Eq RegexFlags where - eq (RegexFlags x) (RegexFlags y) - = x.global == y.global - && x.ignoreCase == y.ignoreCase - && x.multiline == y.multiline - && x.sticky == y.sticky - && x.unicode == y.unicode +derive newtype instance eqRegexFlags :: Eq RegexFlags instance showRegexFlags :: Show RegexFlags where show (RegexFlags flags) = @@ -104,6 +120,7 @@ instance showRegexFlags :: Show RegexFlags where <> (guard flags.global $> "global") <> (guard flags.ignoreCase $> "ignoreCase") <> (guard flags.multiline $> "multiline") + <> (guard flags.dotAll $> "dotAll") <> (guard flags.sticky $> "sticky") <> (guard flags.unicode $> "unicode") in diff --git a/src/Data/String/Regex/Unsafe.purs b/src/Data/String/Regex/Unsafe.purs index 0a982c6..8afd1a2 100644 --- a/src/Data/String/Regex/Unsafe.purs +++ b/src/Data/String/Regex/Unsafe.purs @@ -1,14 +1,14 @@ -module Data.String.Regex.Unsafe -( unsafeRegex -) where - -import Data.Either (fromRight) -import Data.String.Regex (Regex, regex) -import Data.String.Regex.Flags (RegexFlags) - -import Partial.Unsafe (unsafePartial) - --- | Constructs a `Regex` from a pattern string and flags. Fails with --- | an exception if the pattern contains a syntax error. -unsafeRegex :: String -> RegexFlags -> Regex -unsafeRegex s f = unsafePartial fromRight (regex s f) +module Data.String.Regex.Unsafe + ( unsafeRegex + ) where + +import Control.Category (identity) +import Data.Either (either) +import Data.String.Regex (Regex, regex) +import Data.String.Regex.Flags (RegexFlags) +import Partial.Unsafe (unsafeCrashWith) + +-- | Constructs a `Regex` from a pattern string and flags. Fails with +-- | an exception if the pattern contains a syntax error. +unsafeRegex :: String -> RegexFlags -> Regex +unsafeRegex s f = either unsafeCrashWith identity (regex s f) diff --git a/src/Data/String/Unsafe.js b/src/Data/String/Unsafe.js index d7a17ca..75772aa 100644 --- a/src/Data/String/Unsafe.js +++ b/src/Data/String/Unsafe.js @@ -1,13 +1,11 @@ -"use strict"; - -exports.charAt = function (i) { +export const charAt = function (i) { return function (s) { if (i >= 0 && i < s.length) return s.charAt(i); throw new Error("Data.String.Unsafe.charAt: Invalid index."); }; }; -exports.char = function (s) { +export const char = function (s) { if (s.length === 1) return s.charAt(0); throw new Error("Data.String.Unsafe.char: Expected string of length 1."); }; diff --git a/test/Test/Data/String/CodePoints.purs b/test/Test/Data/String/CodePoints.purs index 310321b..587ec89 100644 --- a/test/Test/Data/String/CodePoints.purs +++ b/test/Test/Data/String/CodePoints.purs @@ -366,6 +366,10 @@ testStringCodePoints = do { actual: SCP.lastIndexOf' (Pattern str) 1 str , expected: Just 0 } + assertEqual + { actual: SCP.lastIndexOf' (Pattern "a") (-1) str + , expected: Just 0 + } assertEqual { actual: SCP.lastIndexOf' (Pattern "a") 0 str , expected: Just 0 @@ -374,6 +378,10 @@ testStringCodePoints = do { actual: SCP.lastIndexOf' (Pattern "a") 7 str , expected: Just 0 } + assertEqual + { actual: SCP.lastIndexOf' (Pattern "a") (SCP.length str) str + , expected: Just 0 + } assertEqual { actual: SCP.lastIndexOf' (Pattern "z") 0 str , expected: Nothing diff --git a/test/Test/Data/String/CodeUnits.purs b/test/Test/Data/String/CodeUnits.purs index 249a639..ddd512b 100644 --- a/test/Test/Data/String/CodeUnits.purs +++ b/test/Test/Data/String/CodeUnits.purs @@ -270,7 +270,7 @@ testStringCodeUnits = do } assertEqual { actual: SCU.lastIndexOf' (Pattern "") (-1) "ab" - , expected: Nothing + , expected: Just 0 } assertEqual { actual: SCU.lastIndexOf' (Pattern "") 0 "ab" @@ -286,7 +286,7 @@ testStringCodeUnits = do } assertEqual { actual: SCU.lastIndexOf' (Pattern "") 3 "ab" - , expected: Nothing + , expected: Just 2 } assertEqual { actual: SCU.lastIndexOf' (Pattern "bc") 0 "abcd" @@ -472,41 +472,45 @@ testStringCodeUnits = do log "slice" assertEqual { actual: SCU.slice 0 0 "purescript" - , expected: Just "" + , expected: "" } assertEqual { actual: SCU.slice 0 1 "purescript" - , expected: Just "p" + , expected: "p" } assertEqual { actual: SCU.slice 3 6 "purescript" - , expected: Just "esc" + , expected: "esc" } assertEqual { actual: SCU.slice 3 10 "purescript" - , expected: Just "escript" + , expected: "escript" + } + assertEqual + { actual: SCU.slice 10 10 "purescript" + , expected: "" } assertEqual { actual: SCU.slice (-4) (-1) "purescript" - , expected: Just "rip" + , expected: "rip" } assertEqual { actual: SCU.slice (-4) 3 "purescript" - , expected: Nothing -- b' > e' + , expected: "" } assertEqual { actual: SCU.slice 1000 3 "purescript" - , expected: Nothing -- b' > e' (subsumes b > l) + , expected: "" } assertEqual { actual: SCU.slice 2 (-15) "purescript" - , expected: Nothing -- e' < 0 + , expected: "" } assertEqual { actual: SCU.slice (-15) 9 "purescript" - , expected: Nothing -- b' < 0 + , expected: "purescrip" } assertEqual { actual: SCU.slice 3 1000 "purescript" - , expected: Nothing -- e > l + , expected: "escript" } diff --git a/test/Test/Data/String/NonEmpty.purs b/test/Test/Data/String/NonEmpty.purs index 59a8f22..a4103ec 100644 --- a/test/Test/Data/String/NonEmpty.purs +++ b/test/Test/Data/String/NonEmpty.purs @@ -6,11 +6,11 @@ import Data.Array.NonEmpty as NEA import Data.Maybe (Maybe(..), fromJust) import Data.String.NonEmpty (Pattern(..), nes) import Data.String.NonEmpty as NES -import Data.Symbol (SProxy(..)) import Effect (Effect) import Effect.Console (log) import Partial.Unsafe (unsafePartial) import Test.Assert (assert, assertEqual) +import Type.Proxy (Proxy(..)) testNonEmptyString :: Effect Unit testNonEmptyString = do @@ -22,7 +22,7 @@ testNonEmptyString = do } assertEqual { actual: NES.fromString "hello" - , expected: Just (nes (SProxy :: SProxy "hello")) + , expected: Just (nes (Proxy :: Proxy "hello")) } log "toString" @@ -33,136 +33,136 @@ testNonEmptyString = do log "appendString" assertEqual - { actual: NES.appendString (nes (SProxy :: SProxy "Hello")) " world" - , expected: nes (SProxy :: SProxy "Hello world") + { actual: NES.appendString (nes (Proxy :: Proxy "Hello")) " world" + , expected: nes (Proxy :: Proxy "Hello world") } assertEqual - { actual: NES.appendString (nes (SProxy :: SProxy "Hello")) "" - , expected: nes (SProxy :: SProxy "Hello") + { actual: NES.appendString (nes (Proxy :: Proxy "Hello")) "" + , expected: nes (Proxy :: Proxy "Hello") } log "prependString" assertEqual - { actual: NES.prependString "be" (nes (SProxy :: SProxy "fore")) - , expected: nes (SProxy :: SProxy "before") + { actual: NES.prependString "be" (nes (Proxy :: Proxy "fore")) + , expected: nes (Proxy :: Proxy "before") } assertEqual - { actual: NES.prependString "" (nes (SProxy :: SProxy "fore")) - , expected: nes (SProxy :: SProxy "fore") + { actual: NES.prependString "" (nes (Proxy :: Proxy "fore")) + , expected: nes (Proxy :: Proxy "fore") } log "contains" - assert $ NES.contains (Pattern "") (nes (SProxy :: SProxy "abcd")) - assert $ NES.contains (Pattern "bc") (nes (SProxy :: SProxy "abcd")) - assert $ not NES.contains (Pattern "cb") (nes (SProxy :: SProxy "abcd")) - assert $ NES.contains (Pattern "needle") (nes (SProxy :: SProxy "haystack with needle")) - assert $ not NES.contains (Pattern "needle") (nes (SProxy :: SProxy "haystack")) + assert $ NES.contains (Pattern "") (nes (Proxy :: Proxy "abcd")) + assert $ NES.contains (Pattern "bc") (nes (Proxy :: Proxy "abcd")) + assert $ not NES.contains (Pattern "cb") (nes (Proxy :: Proxy "abcd")) + assert $ NES.contains (Pattern "needle") (nes (Proxy :: Proxy "haystack with needle")) + assert $ not NES.contains (Pattern "needle") (nes (Proxy :: Proxy "haystack")) log "localeCompare" assertEqual - { actual: NES.localeCompare (nes (SProxy :: SProxy "a")) (nes (SProxy :: SProxy "a")) + { actual: NES.localeCompare (nes (Proxy :: Proxy "a")) (nes (Proxy :: Proxy "a")) , expected: EQ } assertEqual - { actual: NES.localeCompare (nes (SProxy :: SProxy "a")) (nes (SProxy :: SProxy "b")) + { actual: NES.localeCompare (nes (Proxy :: Proxy "a")) (nes (Proxy :: Proxy "b")) , expected: LT } assertEqual - { actual: NES.localeCompare (nes (SProxy :: SProxy "b")) (nes (SProxy :: SProxy "a")) + { actual: NES.localeCompare (nes (Proxy :: Proxy "b")) (nes (Proxy :: Proxy "a")) , expected: GT } log "replace" assertEqual - { actual: NES.replace (Pattern "b") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "abc")) - , expected: nes (SProxy :: SProxy "a!c") + { actual: NES.replace (Pattern "b") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "abc")) + , expected: nes (Proxy :: Proxy "a!c") } assertEqual - { actual: NES.replace (Pattern "b") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "abbc")) - , expected: nes (SProxy :: SProxy "a!bc") + { actual: NES.replace (Pattern "b") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "abbc")) + , expected: nes (Proxy :: Proxy "a!bc") } assertEqual - { actual: NES.replace (Pattern "d") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "abc")) - , expected: nes (SProxy :: SProxy "abc") + { actual: NES.replace (Pattern "d") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "abc")) + , expected: nes (Proxy :: Proxy "abc") } log "replaceAll" assertEqual - { actual: NES.replaceAll (Pattern "[b]") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "a[b]c")) - , expected: nes (SProxy :: SProxy "a!c") + { actual: NES.replaceAll (Pattern "[b]") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "a[b]c")) + , expected: nes (Proxy :: Proxy "a!c") } assertEqual - { actual: NES.replaceAll (Pattern "[b]") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "a[b]c[b]")) - , expected: nes (SProxy :: SProxy "a!c!") + { actual: NES.replaceAll (Pattern "[b]") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "a[b]c[b]")) + , expected: nes (Proxy :: Proxy "a!c!") } assertEqual - { actual: NES.replaceAll (Pattern "x") (NES.NonEmptyReplacement (nes (SProxy :: SProxy "!"))) (nes (SProxy :: SProxy "abc")) - , expected: nes (SProxy :: SProxy "abc") + { actual: NES.replaceAll (Pattern "x") (NES.NonEmptyReplacement (nes (Proxy :: Proxy "!"))) (nes (Proxy :: Proxy "abc")) + , expected: nes (Proxy :: Proxy "abc") } log "stripPrefix" assertEqual - { actual: NES.stripPrefix (Pattern "") (nes (SProxy :: SProxy "abc")) - , expected: Just (nes (SProxy :: SProxy "abc")) + { actual: NES.stripPrefix (Pattern "") (nes (Proxy :: Proxy "abc")) + , expected: Just (nes (Proxy :: Proxy "abc")) } assertEqual - { actual: NES.stripPrefix (Pattern "a") (nes (SProxy :: SProxy "abc")) - , expected: Just (nes (SProxy :: SProxy "bc")) + { actual: NES.stripPrefix (Pattern "a") (nes (Proxy :: Proxy "abc")) + , expected: Just (nes (Proxy :: Proxy "bc")) } assertEqual - { actual: NES.stripPrefix (Pattern "abc") (nes (SProxy :: SProxy "abc")) + { actual: NES.stripPrefix (Pattern "abc") (nes (Proxy :: Proxy "abc")) , expected: Nothing } assertEqual - { actual: NES.stripPrefix (Pattern "!") (nes (SProxy :: SProxy "abc")) + { actual: NES.stripPrefix (Pattern "!") (nes (Proxy :: Proxy "abc")) , expected: Nothing } assertEqual - { actual: NES.stripPrefix (Pattern "http:") (nes (SProxy :: SProxy "http://purescript.org")) - , expected: Just (nes (SProxy :: SProxy "//purescript.org")) + { actual: NES.stripPrefix (Pattern "http:") (nes (Proxy :: Proxy "http://purescript.org")) + , expected: Just (nes (Proxy :: Proxy "//purescript.org")) } assertEqual - { actual: NES.stripPrefix (Pattern "http:") (nes (SProxy :: SProxy "https://purescript.org")) + { actual: NES.stripPrefix (Pattern "http:") (nes (Proxy :: Proxy "https://purescript.org")) , expected: Nothing } assertEqual - { actual: NES.stripPrefix (Pattern "Hello!") (nes (SProxy :: SProxy "Hello!")) + { actual: NES.stripPrefix (Pattern "Hello!") (nes (Proxy :: Proxy "Hello!")) , expected: Nothing } log "stripSuffix" assertEqual - { actual: NES.stripSuffix (Pattern ".exe") (nes (SProxy :: SProxy "purs.exe")) - , expected: Just (nes (SProxy :: SProxy "purs")) + { actual: NES.stripSuffix (Pattern ".exe") (nes (Proxy :: Proxy "purs.exe")) + , expected: Just (nes (Proxy :: Proxy "purs")) } assertEqual - { actual: NES.stripSuffix (Pattern ".exe") (nes (SProxy :: SProxy "purs")) + { actual: NES.stripSuffix (Pattern ".exe") (nes (Proxy :: Proxy "purs")) , expected: Nothing } assertEqual - { actual: NES.stripSuffix (Pattern "Hello!") (nes (SProxy :: SProxy "Hello!")) + { actual: NES.stripSuffix (Pattern "Hello!") (nes (Proxy :: Proxy "Hello!")) , expected: Nothing } log "toLower" assertEqual - { actual: NES.toLower (nes (SProxy :: SProxy "bAtMaN")) - , expected: nes (SProxy :: SProxy "batman") + { actual: NES.toLower (nes (Proxy :: Proxy "bAtMaN")) + , expected: nes (Proxy :: Proxy "batman") } log "toUpper" assertEqual - { actual: NES.toUpper (nes (SProxy :: SProxy "bAtMaN")) - , expected: nes (SProxy :: SProxy "BATMAN") + { actual: NES.toUpper (nes (Proxy :: Proxy "bAtMaN")) + , expected: nes (Proxy :: Proxy "BATMAN") } log "trim" assertEqual - { actual: NES.trim (nes (SProxy :: SProxy " abc ")) - , expected: Just (nes (SProxy :: SProxy "abc")) + { actual: NES.trim (nes (Proxy :: Proxy " abc ")) + , expected: Just (nes (Proxy :: Proxy "abc")) } assertEqual - { actual: NES.trim (nes (SProxy :: SProxy " \n")) + { actual: NES.trim (nes (Proxy :: Proxy " \n")) , expected: Nothing } @@ -172,48 +172,48 @@ testNonEmptyString = do , expected: "" } assertEqual - { actual: NES.joinWith "" [nes (SProxy :: SProxy "a"), nes (SProxy :: SProxy "b")] + { actual: NES.joinWith "" [nes (Proxy :: Proxy "a"), nes (Proxy :: Proxy "b")] , expected: "ab" } assertEqual - { actual: NES.joinWith "--" [nes (SProxy :: SProxy "a"), nes (SProxy :: SProxy "b"), nes (SProxy :: SProxy "c")] + { actual: NES.joinWith "--" [nes (Proxy :: Proxy "a"), nes (Proxy :: Proxy "b"), nes (Proxy :: Proxy "c")] , expected: "a--b--c" } log "join1With" assertEqual - { actual: NES.join1With "" (nea [nes (SProxy :: SProxy "a"), nes (SProxy :: SProxy "b")]) - , expected: nes (SProxy :: SProxy "ab") + { actual: NES.join1With "" (nea [nes (Proxy :: Proxy "a"), nes (Proxy :: Proxy "b")]) + , expected: nes (Proxy :: Proxy "ab") } assertEqual - { actual: NES.join1With "--" (nea [nes (SProxy :: SProxy "a"), nes (SProxy :: SProxy "b"), nes (SProxy :: SProxy "c")]) - , expected: nes (SProxy :: SProxy "a--b--c") + { actual: NES.join1With "--" (nea [nes (Proxy :: Proxy "a"), nes (Proxy :: Proxy "b"), nes (Proxy :: Proxy "c")]) + , expected: nes (Proxy :: Proxy "a--b--c") } assertEqual - { actual: NES.join1With ", " (nea [nes (SProxy :: SProxy "apple"), nes (SProxy :: SProxy "banana")]) - , expected: nes (SProxy :: SProxy "apple, banana") + { actual: NES.join1With ", " (nea [nes (Proxy :: Proxy "apple"), nes (Proxy :: Proxy "banana")]) + , expected: nes (Proxy :: Proxy "apple, banana") } assertEqual - { actual: NES.join1With "" (nea [nes (SProxy :: SProxy "apple"), nes (SProxy :: SProxy "banana")]) - , expected: nes (SProxy :: SProxy "applebanana") + { actual: NES.join1With "" (nea [nes (Proxy :: Proxy "apple"), nes (Proxy :: Proxy "banana")]) + , expected: nes (Proxy :: Proxy "applebanana") } log "joinWith1" assertEqual - { actual: NES.joinWith1 (nes (SProxy :: SProxy " ")) (nea ["a", "b"]) - , expected: nes (SProxy :: SProxy "a b") + { actual: NES.joinWith1 (nes (Proxy :: Proxy " ")) (nea ["a", "b"]) + , expected: nes (Proxy :: Proxy "a b") } assertEqual - { actual: NES.joinWith1 (nes (SProxy :: SProxy "--")) (nea ["a", "b", "c"]) - , expected: nes (SProxy :: SProxy "a--b--c") + { actual: NES.joinWith1 (nes (Proxy :: Proxy "--")) (nea ["a", "b", "c"]) + , expected: nes (Proxy :: Proxy "a--b--c") } assertEqual - { actual: NES.joinWith1 (nes (SProxy :: SProxy ", ")) (nea ["apple", "banana"]) - , expected: nes (SProxy :: SProxy "apple, banana") + { actual: NES.joinWith1 (nes (Proxy :: Proxy ", ")) (nea ["apple", "banana"]) + , expected: nes (Proxy :: Proxy "apple, banana") } assertEqual - { actual: NES.joinWith1 (nes (SProxy :: SProxy "/")) (nea ["a", "b", "", "c", ""]) - , expected: nes (SProxy :: SProxy "a/b//c/") + { actual: NES.joinWith1 (nes (Proxy :: Proxy "/")) (nea ["a", "b", "", "c", ""]) + , expected: nes (Proxy :: Proxy "a/b//c/") } nea :: Array ~> NEA.NonEmptyArray diff --git a/test/Test/Data/String/NonEmpty/CodeUnits.purs b/test/Test/Data/String/NonEmpty/CodeUnits.purs index fee9b51..e810dd9 100644 --- a/test/Test/Data/String/NonEmpty/CodeUnits.purs +++ b/test/Test/Data/String/NonEmpty/CodeUnits.purs @@ -7,11 +7,11 @@ import Data.Enum (fromEnum) import Data.Maybe (Maybe(..), fromJust) import Data.String.NonEmpty (Pattern(..), nes) import Data.String.NonEmpty.CodeUnits as NESCU -import Data.Symbol (SProxy(..)) import Effect (Effect) import Effect.Console (log) import Partial.Unsafe (unsafePartial) import Test.Assert (assertEqual) +import Type.Proxy (Proxy(..)) testNonEmptyStringCodeUnits :: Effect Unit testNonEmptyStringCodeUnits = do @@ -23,7 +23,7 @@ testNonEmptyStringCodeUnits = do } assertEqual { actual: NESCU.fromCharArray ['a', 'b'] - , expected: Just (nes (SProxy :: SProxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } log "fromNonEmptyCharArray" @@ -35,415 +35,415 @@ testNonEmptyStringCodeUnits = do log "singleton" assertEqual { actual: NESCU.singleton 'a' - , expected: nes (SProxy :: SProxy "a") + , expected: nes (Proxy :: Proxy "a") } log "cons" assertEqual { actual: NESCU.cons 'a' "bc" - , expected: nes (SProxy :: SProxy "abc") + , expected: nes (Proxy :: Proxy "abc") } assertEqual { actual: NESCU.cons 'a' "" - , expected: nes (SProxy :: SProxy "a") + , expected: nes (Proxy :: Proxy "a") } log "snoc" assertEqual { actual: NESCU.snoc 'c' "ab" - , expected: nes (SProxy :: SProxy "abc") + , expected: nes (Proxy :: Proxy "abc") } assertEqual { actual: NESCU.snoc 'a' "" - , expected: nes (SProxy :: SProxy "a") + , expected: nes (Proxy :: Proxy "a") } log "fromFoldable1" assertEqual { actual: NESCU.fromFoldable1 (nea ['a']) - , expected: nes (SProxy :: SProxy "a") + , expected: nes (Proxy :: Proxy "a") } assertEqual { actual: NESCU.fromFoldable1 (nea ['a', 'b', 'c']) - , expected: nes (SProxy :: SProxy "abc") + , expected: nes (Proxy :: Proxy "abc") } log "charAt" assertEqual - { actual: NESCU.charAt 0 (nes (SProxy :: SProxy "a")) + { actual: NESCU.charAt 0 (nes (Proxy :: Proxy "a")) , expected: Just 'a' } assertEqual - { actual: NESCU.charAt 1 (nes (SProxy :: SProxy "a")) + { actual: NESCU.charAt 1 (nes (Proxy :: Proxy "a")) , expected: Nothing } assertEqual - { actual: NESCU.charAt 0 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.charAt 0 (nes (Proxy :: Proxy "ab")) , expected: Just 'a' } assertEqual - { actual: NESCU.charAt 1 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.charAt 1 (nes (Proxy :: Proxy "ab")) , expected: Just 'b' } assertEqual - { actual: NESCU.charAt 2 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.charAt 2 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.charAt 2 (nes (SProxy :: SProxy "Hello")) + { actual: NESCU.charAt 2 (nes (Proxy :: Proxy "Hello")) , expected: Just 'l' } assertEqual - { actual: NESCU.charAt 10 (nes (SProxy :: SProxy "Hello")) + { actual: NESCU.charAt 10 (nes (Proxy :: Proxy "Hello")) , expected: Nothing } log "charCodeAt" assertEqual - { actual: fromEnum <$> NESCU.charAt 0 (nes (SProxy :: SProxy "a")) + { actual: fromEnum <$> NESCU.charAt 0 (nes (Proxy :: Proxy "a")) , expected: Just 97 } assertEqual - { actual: fromEnum <$> NESCU.charAt 1 (nes (SProxy :: SProxy "a")) + { actual: fromEnum <$> NESCU.charAt 1 (nes (Proxy :: Proxy "a")) , expected: Nothing } assertEqual - { actual: fromEnum <$> NESCU.charAt 0 (nes (SProxy :: SProxy "ab")) + { actual: fromEnum <$> NESCU.charAt 0 (nes (Proxy :: Proxy "ab")) , expected: Just 97 } assertEqual - { actual: fromEnum <$> NESCU.charAt 1 (nes (SProxy :: SProxy "ab")) + { actual: fromEnum <$> NESCU.charAt 1 (nes (Proxy :: Proxy "ab")) , expected: Just 98 } assertEqual - { actual: fromEnum <$> NESCU.charAt 2 (nes (SProxy :: SProxy "ab")) + { actual: fromEnum <$> NESCU.charAt 2 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: fromEnum <$> NESCU.charAt 2 (nes (SProxy :: SProxy "5 €")) + { actual: fromEnum <$> NESCU.charAt 2 (nes (Proxy :: Proxy "5 €")) , expected: Just 0x20AC } assertEqual - { actual: fromEnum <$> NESCU.charAt 10 (nes (SProxy :: SProxy "5 €")) + { actual: fromEnum <$> NESCU.charAt 10 (nes (Proxy :: Proxy "5 €")) , expected: Nothing } log "toChar" assertEqual - { actual: NESCU.toChar (nes (SProxy :: SProxy "a")) + { actual: NESCU.toChar (nes (Proxy :: Proxy "a")) , expected: Just 'a' } assertEqual - { actual: NESCU.toChar (nes (SProxy :: SProxy "ab")) + { actual: NESCU.toChar (nes (Proxy :: Proxy "ab")) , expected: Nothing } log "toCharArray" assertEqual - { actual: NESCU.toCharArray (nes (SProxy :: SProxy "a")) + { actual: NESCU.toCharArray (nes (Proxy :: Proxy "a")) , expected: ['a'] } assertEqual - { actual: NESCU.toCharArray (nes (SProxy :: SProxy "ab")) + { actual: NESCU.toCharArray (nes (Proxy :: Proxy "ab")) , expected: ['a', 'b'] } assertEqual - { actual: NESCU.toCharArray (nes (SProxy :: SProxy "Hello☺\n")) + { actual: NESCU.toCharArray (nes (Proxy :: Proxy "Hello☺\n")) , expected: ['H','e','l','l','o','☺','\n'] } log "toNonEmptyCharArray" assertEqual - { actual: NESCU.toNonEmptyCharArray (nes (SProxy :: SProxy "ab")) + { actual: NESCU.toNonEmptyCharArray (nes (Proxy :: Proxy "ab")) , expected: nea ['a', 'b'] } log "uncons" assertEqual - { actual: NESCU.uncons (nes (SProxy :: SProxy "a")) + { actual: NESCU.uncons (nes (Proxy :: Proxy "a")) , expected: { head: 'a', tail: Nothing } } assertEqual - { actual: NESCU.uncons (nes (SProxy :: SProxy "Hello World")) - , expected: { head: 'H', tail: Just (nes (SProxy :: SProxy "ello World")) } + { actual: NESCU.uncons (nes (Proxy :: Proxy "Hello World")) + , expected: { head: 'H', tail: Just (nes (Proxy :: Proxy "ello World")) } } log "takeWhile" assertEqual - { actual: NESCU.takeWhile (\c -> true) (nes (SProxy :: SProxy "abc")) - , expected: Just (nes (SProxy :: SProxy "abc")) + { actual: NESCU.takeWhile (\_ -> true) (nes (Proxy :: Proxy "abc")) + , expected: Just (nes (Proxy :: Proxy "abc")) } assertEqual - { actual: NESCU.takeWhile (\c -> false) (nes (SProxy :: SProxy "abc")) + { actual: NESCU.takeWhile (\_ -> false) (nes (Proxy :: Proxy "abc")) , expected: Nothing } assertEqual - { actual: NESCU.takeWhile (\c -> c /= 'b') (nes (SProxy :: SProxy "aabbcc")) - , expected: Just (nes (SProxy :: SProxy "aa")) + { actual: NESCU.takeWhile (\c -> c /= 'b') (nes (Proxy :: Proxy "aabbcc")) + , expected: Just (nes (Proxy :: Proxy "aa")) } assertEqual - { actual: NESCU.takeWhile (_ /= ':') (nes (SProxy :: SProxy "http://purescript.org")) - , expected: Just (nes (SProxy :: SProxy "http")) + { actual: NESCU.takeWhile (_ /= ':') (nes (Proxy :: Proxy "http://purescript.org")) + , expected: Just (nes (Proxy :: Proxy "http")) } assertEqual - { actual: NESCU.takeWhile (_ == 'a') (nes (SProxy :: SProxy "xyz")) + { actual: NESCU.takeWhile (_ == 'a') (nes (Proxy :: Proxy "xyz")) , expected: Nothing } log "dropWhile" assertEqual - { actual: NESCU.dropWhile (\c -> true) (nes (SProxy :: SProxy "abc")) + { actual: NESCU.dropWhile (\_ -> true) (nes (Proxy :: Proxy "abc")) , expected: Nothing } assertEqual - { actual: NESCU.dropWhile (\c -> false) (nes (SProxy :: SProxy "abc")) - , expected: Just (nes (SProxy :: SProxy "abc")) + { actual: NESCU.dropWhile (\_ -> false) (nes (Proxy :: Proxy "abc")) + , expected: Just (nes (Proxy :: Proxy "abc")) } assertEqual - { actual: NESCU.dropWhile (\c -> c /= 'b') (nes (SProxy :: SProxy "aabbcc")) - , expected: Just (nes (SProxy :: SProxy "bbcc")) + { actual: NESCU.dropWhile (\c -> c /= 'b') (nes (Proxy :: Proxy "aabbcc")) + , expected: Just (nes (Proxy :: Proxy "bbcc")) } assertEqual - { actual: NESCU.dropWhile (_ /= '.') (nes (SProxy :: SProxy "Test.purs")) - , expected: Just (nes (SProxy :: SProxy ".purs")) + { actual: NESCU.dropWhile (_ /= '.') (nes (Proxy :: Proxy "Test.purs")) + , expected: Just (nes (Proxy :: Proxy ".purs")) } log "indexOf" assertEqual - { actual: NESCU.indexOf (Pattern "") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf (Pattern "") (nes (Proxy :: Proxy "abcd")) , expected: Just 0 } assertEqual - { actual: NESCU.indexOf (Pattern "bc") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf (Pattern "bc") (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.indexOf (Pattern "cb") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf (Pattern "cb") (nes (Proxy :: Proxy "abcd")) , expected: Nothing } log "indexOf'" assertEqual - { actual: NESCU.indexOf' (Pattern "") (-1) (nes (SProxy :: SProxy "ab")) + { actual: NESCU.indexOf' (Pattern "") (-1) (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.indexOf' (Pattern "") 0 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.indexOf' (Pattern "") 0 (nes (Proxy :: Proxy "ab")) , expected: Just 0 } assertEqual - { actual: NESCU.indexOf' (Pattern "") 1 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.indexOf' (Pattern "") 1 (nes (Proxy :: Proxy "ab")) , expected: Just 1 } assertEqual - { actual: NESCU.indexOf' (Pattern "") 2 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.indexOf' (Pattern "") 2 (nes (Proxy :: Proxy "ab")) , expected: Just 2 } assertEqual - { actual: NESCU.indexOf' (Pattern "") 3 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.indexOf' (Pattern "") 3 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.indexOf' (Pattern "bc") 0 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf' (Pattern "bc") 0 (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.indexOf' (Pattern "bc") 1 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf' (Pattern "bc") 1 (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.indexOf' (Pattern "bc") 2 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf' (Pattern "bc") 2 (nes (Proxy :: Proxy "abcd")) , expected: Nothing } assertEqual - { actual: NESCU.indexOf' (Pattern "cb") 0 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.indexOf' (Pattern "cb") 0 (nes (Proxy :: Proxy "abcd")) , expected: Nothing } log "lastIndexOf" assertEqual - { actual: NESCU.lastIndexOf (Pattern "") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf (Pattern "") (nes (Proxy :: Proxy "abcd")) , expected: Just 4 } assertEqual - { actual: NESCU.lastIndexOf (Pattern "bc") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf (Pattern "bc") (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.lastIndexOf (Pattern "cb") (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf (Pattern "cb") (nes (Proxy :: Proxy "abcd")) , expected: Nothing } log "lastIndexOf'" assertEqual - { actual: NESCU.lastIndexOf' (Pattern "") (-1) (nes (SProxy :: SProxy "ab")) - , expected: Nothing + { actual: NESCU.lastIndexOf' (Pattern "") (-1) (nes (Proxy :: Proxy "ab")) + , expected: Just 0 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "") 0 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.lastIndexOf' (Pattern "") 0 (nes (Proxy :: Proxy "ab")) , expected: Just 0 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "") 1 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.lastIndexOf' (Pattern "") 1 (nes (Proxy :: Proxy "ab")) , expected: Just 1 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "") 2 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.lastIndexOf' (Pattern "") 2 (nes (Proxy :: Proxy "ab")) , expected: Just 2 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "") 3 (nes (SProxy :: SProxy "ab")) - , expected: Nothing + { actual: NESCU.lastIndexOf' (Pattern "") 3 (nes (Proxy :: Proxy "ab")) + , expected: Just 2 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "bc") 0 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf' (Pattern "bc") 0 (nes (Proxy :: Proxy "abcd")) , expected: Nothing } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "bc") 1 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf' (Pattern "bc") 1 (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "bc") 2 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf' (Pattern "bc") 2 (nes (Proxy :: Proxy "abcd")) , expected: Just 1 } assertEqual - { actual: NESCU.lastIndexOf' (Pattern "cb") 0 (nes (SProxy :: SProxy "abcd")) + { actual: NESCU.lastIndexOf' (Pattern "cb") 0 (nes (Proxy :: Proxy "abcd")) , expected: Nothing } log "length" assertEqual - { actual: NESCU.length (nes (SProxy :: SProxy "a")) + { actual: NESCU.length (nes (Proxy :: Proxy "a")) , expected: 1 } assertEqual - { actual: NESCU.length (nes (SProxy :: SProxy "ab")) + { actual: NESCU.length (nes (Proxy :: Proxy "ab")) , expected: 2 } log "take" assertEqual - { actual: NESCU.take 0 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.take 0 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.take 1 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "a")) + { actual: NESCU.take 1 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "a")) } assertEqual - { actual: NESCU.take 2 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.take 2 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.take 3 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.take 3 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.take (-1) (nes (SProxy :: SProxy "ab")) + { actual: NESCU.take (-1) (nes (Proxy :: Proxy "ab")) , expected: Nothing } log "takeRight" assertEqual - { actual: NESCU.takeRight 0 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.takeRight 0 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.takeRight 1 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "b")) + { actual: NESCU.takeRight 1 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "b")) } assertEqual - { actual: NESCU.takeRight 2 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.takeRight 2 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.takeRight 3 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.takeRight 3 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.takeRight (-1) (nes (SProxy :: SProxy "ab")) + { actual: NESCU.takeRight (-1) (nes (Proxy :: Proxy "ab")) , expected: Nothing } log "drop" assertEqual - { actual: NESCU.drop 0 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.drop 0 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.drop 1 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "b")) + { actual: NESCU.drop 1 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "b")) } assertEqual - { actual: NESCU.drop 2 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.drop 2 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.drop 3 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.drop 3 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.drop (-1) (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.drop (-1) (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } log "dropRight" assertEqual - { actual: NESCU.dropRight 0 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.dropRight 0 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } assertEqual - { actual: NESCU.dropRight 1 (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "a")) + { actual: NESCU.dropRight 1 (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "a")) } assertEqual - { actual: NESCU.dropRight 2 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.dropRight 2 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.dropRight 3 (nes (SProxy :: SProxy "ab")) + { actual: NESCU.dropRight 3 (nes (Proxy :: Proxy "ab")) , expected: Nothing } assertEqual - { actual: NESCU.dropRight (-1) (nes (SProxy :: SProxy "ab")) - , expected: Just (nes (SProxy :: SProxy "ab")) + { actual: NESCU.dropRight (-1) (nes (Proxy :: Proxy "ab")) + , expected: Just (nes (Proxy :: Proxy "ab")) } log "countPrefix" assertEqual - { actual: NESCU.countPrefix (_ == 'a') (nes (SProxy :: SProxy "ab")) + { actual: NESCU.countPrefix (_ == 'a') (nes (Proxy :: Proxy "ab")) , expected: 1 } assertEqual - { actual: NESCU.countPrefix (_ == 'a') (nes (SProxy :: SProxy "aaab")) + { actual: NESCU.countPrefix (_ == 'a') (nes (Proxy :: Proxy "aaab")) , expected: 3 } assertEqual - { actual: NESCU.countPrefix (_ == 'a') (nes (SProxy :: SProxy "abaa")) + { actual: NESCU.countPrefix (_ == 'a') (nes (Proxy :: Proxy "abaa")) , expected: 1 } assertEqual - { actual: NESCU.countPrefix (_ == 'c') (nes (SProxy :: SProxy "abaa")) + { actual: NESCU.countPrefix (_ == 'c') (nes (Proxy :: Proxy "abaa")) , expected: 0 } log "splitAt" assertEqual - { actual: NESCU.splitAt 0 (nes (SProxy :: SProxy "a")) - , expected: { before: Nothing, after: Just (nes (SProxy :: SProxy "a")) } + { actual: NESCU.splitAt 0 (nes (Proxy :: Proxy "a")) + , expected: { before: Nothing, after: Just (nes (Proxy :: Proxy "a")) } } assertEqual - { actual: NESCU.splitAt 1 (nes (SProxy :: SProxy "ab")) - , expected: { before: Just (nes (SProxy :: SProxy "a")), after: Just (nes (SProxy :: SProxy "b")) } + { actual: NESCU.splitAt 1 (nes (Proxy :: Proxy "ab")) + , expected: { before: Just (nes (Proxy :: Proxy "a")), after: Just (nes (Proxy :: Proxy "b")) } } assertEqual - { actual: NESCU.splitAt 3 (nes (SProxy :: SProxy "aabcc")) - , expected: { before: Just (nes (SProxy :: SProxy "aab")), after: Just (nes (SProxy :: SProxy "cc")) } + { actual: NESCU.splitAt 3 (nes (Proxy :: Proxy "aabcc")) + , expected: { before: Just (nes (Proxy :: Proxy "aab")), after: Just (nes (Proxy :: Proxy "cc")) } } assertEqual - { actual: NESCU.splitAt (-1) (nes (SProxy :: SProxy "abc")) - , expected: { before: Nothing, after: Just (nes (SProxy :: SProxy "abc")) } + { actual: NESCU.splitAt (-1) (nes (Proxy :: Proxy "abc")) + , expected: { before: Nothing, after: Just (nes (Proxy :: Proxy "abc")) } } nea :: Array ~> NEA.NonEmptyArray diff --git a/test/Test/Data/String/Regex.purs b/test/Test/Data/String/Regex.purs index 326b35e..01d583b 100644 --- a/test/Test/Data/String/Regex.purs +++ b/test/Test/Data/String/Regex.purs @@ -5,12 +5,12 @@ import Data.String.Regex import Data.Array.NonEmpty (NonEmptyArray, fromArray) import Data.Either (isLeft) import Data.Maybe (Maybe(..), fromJust) -import Data.String.Regex.Flags (global, ignoreCase, noFlags) +import Data.String.Regex.Flags (dotAll, global, ignoreCase, noFlags) import Data.String.Regex.Unsafe (unsafeRegex) import Effect (Effect) import Effect.Console (log) import Partial.Unsafe (unsafePartial) -import Prelude (type (~>), Unit, discard, not, ($), (<<<), (<>), (==)) +import Prelude (type (~>), Unit, discard, not, show, ($), (<<<), (<>), (==)) import Test.Assert (assert) testStringRegex :: Effect Unit @@ -24,6 +24,7 @@ testStringRegex = do assert $ "quxbarfoobaz" == replace (unsafeRegex "foo" noFlags) "qux" "foobarfoobaz" assert $ "quxbarquxbaz" == replace (unsafeRegex "foo" global) "qux" "foobarfoobaz" assert $ "quxbarquxbaz" == replace (unsafeRegex "foo" (global <> ignoreCase)) "qux" "foobarFOObaz" + assert $ "quxbarfoobaz" == replace (unsafeRegex ".foo" dotAll) "qux" "\nfoobarfoobaz" log "match" assert $ match (unsafeRegex "^abc$" noFlags) "abc" == Just (nea [Just "abc"]) @@ -34,6 +35,10 @@ testStringRegex = do log "replace'" assert $ replace' (unsafeRegex "-" noFlags) (\s xs -> "!") "a-b-c" == "a!b-c" + assert $ replace' (unsafeRegex "(foo)(bar)?" noFlags) (\s xs -> show xs) "<>" == "<>" + assert $ replace' (unsafeRegex "(foo)(bar)?" noFlags) (\s xs -> show xs) "" == "<[(Just \"foo\"),Nothing]>" + assert $ replace' (unsafeRegex "(foo)(bar)?" noFlags) (\s xs -> show xs) "" == "<[(Just \"foo\"),(Just \"bar\")]>" + assert $ replace' (unsafeRegex "@(?\\w+)" noFlags) (\s xs -> show xs) "@purescript" == "[(Just \"purescript\")]" log "search" assert $ search (unsafeRegex "b" noFlags) "abc" == Just 1