From 94e450d20448bf3d1c32233e438e3b85b1f051dc Mon Sep 17 00:00:00 2001 From: David Chambers Date: Tue, 21 Jul 2020 22:22:53 +0200 Subject: [PATCH] regexp: add S.replace --- .circleci/config.yml | 6 +++--- index.js | 47 ++++++++++++++++++++++++++++++++++++++++++++ test/.eslintrc.json | 2 ++ test/replace.js | 19 ++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 test/replace.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 2ee728dda..b45eb01ad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,7 +28,7 @@ jobs: nvm exec $1 npm test } case $CIRCLE_NODE_INDEX in - 0) test_with_version 8 ;; - 1) test_with_version 10 ;; - 2) npm install && npm test ;; + 0) test_with_version 10 ;; + 1) npm install && npm test ;; + 2) test_with_version 14 ;; esac diff --git a/index.js b/index.js index fe5a28819..0a699bb80 100644 --- a/index.js +++ b/index.js @@ -4403,6 +4403,53 @@ impl: matchAll }; + //# replace :: (Array (Maybe String) -> String) -> RegExp -> String -> String + //. + //. Replaces occurrences of the given pattern within the given string + //. in accordance with the given replacement function, which receives an + //. array of captured values. Replaces all occurrences of the pattern if + //. its `g` flag is set; just the first occurrence otherwise. + //. + //. ```javascript + //. > S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/) ('foo') + //. 'Foo' + //. + //. > S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/g) ('foo') + //. 'FOO' + //. + //. > S.replace (S.show) (/(foo)(bar)?/) ('<>') + //. '<>' + //. + //. > S.replace (S.show) (/(foo)(bar)?/) ('') + //. '<[Just ("foo"), Nothing]>' + //. + //. > S.replace (S.show) (/(foo)(bar)?/) ('') + //. '<[Just ("foo"), Just ("bar")]>' + //. ``` + function replace(substitute) { + return function(pattern) { + return function(text) { + return text.replace (pattern, function() { + var groups = []; + var group, idx = 1; + // eslint-disable-next-line no-plusplus + while (typeof (group = arguments[idx++]) !== 'number') { + groups.push (group == null ? Nothing : Just (group)); + } + return substitute (groups); + }); + }; + }; + } + _.replace = { + consts: {}, + types: [$.Fn ($.Array ($.Maybe ($.String))) ($.String), + $.RegExp, + $.String, + $.String], + impl: replace + }; + //. ### String //# toUpper :: String -> String diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 35afa6267..cb249598b 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -1,9 +1,11 @@ { "root": true, "extends": ["../node_modules/sanctuary-style/eslint-es6.json"], + "parserOptions": {"ecmaVersion": 2018}, "env": {"node": true}, "globals": {"suite": false, "test": false}, "rules": { + "comma-dangle": ["error", {"arrays": "always-multiline", "objects": "always-multiline", "functions": "never"}], "max-len": ["off"] } } diff --git a/test/replace.js b/test/replace.js new file mode 100644 index 000000000..f0d26ce78 --- /dev/null +++ b/test/replace.js @@ -0,0 +1,19 @@ +'use strict'; + +const S = require ('..'); + +const eq = require ('./internal/eq'); + + +test ('replace', () => { + + eq (S.show (S.replace)) ('replace :: (Array (Maybe String) -> String) -> RegExp -> String -> String'); + + eq (S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/) ('foo')) ('Foo'); + eq (S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/g) ('foo')) ('FOO'); + eq (S.replace (S.show) (/(foo)(bar)?/) ('<>')) ('<>'); + eq (S.replace (S.show) (/(foo)(bar)?/) ('')) ('<[Just ("foo"), Nothing]>'); + eq (S.replace (S.show) (/(foo)(bar)?/) ('')) ('<[Just ("foo"), Just ("bar")]>'); + eq (S.replace (S.show) (/@(?[-\w]+)/) ('@sanctuary-js')) ('[Just ("sanctuary-js")]'); + +});