aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChouser <chouser@n01se.net>2009-01-04 03:44:47 +0000
committerChouser <chouser@n01se.net>2009-01-04 03:44:47 +0000
commit66b47eebd17ddd1caa3601eb1af829e6fdb128df (patch)
treeda12b8bf0a607b717bc132448031583590387ff0
parent6b776578e93b8fa694a6126fc9ece4b150821ed4 (diff)
re-sub and re-gsub now accept replacement fns. Patch from Juergen Gmeiner.
-rw-r--r--src/clojure/contrib/str_utils.clj34
-rw-r--r--src/clojure/contrib/test_contrib/str_utils.clj33
2 files changed, 61 insertions, 6 deletions
diff --git a/src/clojure/contrib/str_utils.clj b/src/clojure/contrib/str_utils.clj
index f6a59002..74a5266e 100644
--- a/src/clojure/contrib/str_utils.clj
+++ b/src/clojure/contrib/str_utils.clj
@@ -43,17 +43,39 @@
(list (.subSequence string prevend (.length string))))))
0)))
-(defn re-gsub
+(defn re-gsub
"Replaces all instances of 'pattern' in 'string' with
- 'replacement'. Like Ruby's 'String#gsub'."
- [#^Pattern regex replacement #^String string]
- (.. regex (matcher string) (replaceAll replacement)))
+ 'replacement'. Like Ruby's 'String#gsub'.
+
+ If (ifn? replacment) is true, the replacement is called with the
+ match.
+ "
+ [#^java.util.regex.Pattern regex replacement #^String string]
+ (if (ifn? replacement)
+ (let [parts (vec (re-partition regex string))]
+ (apply str
+ (reduce (fn [parts match-idx]
+ (update-in parts [match-idx] replacement))
+ parts (range 1 (count parts) 2))))
+ (.. regex (matcher string) (replaceAll replacement))))
(defn re-sub
"Replaces the first instance of 'pattern' in 'string' with
- 'replacement'. Like Ruby's 'String#sub'."
+ 'replacement'. Like Ruby's 'String#sub'.
+
+ If (ifn? replacement) is true, the replacement is called with
+ the match.
+ "
[#^Pattern regex replacement #^String string]
- (.. regex (matcher string) (replaceFirst replacement)))
+ (if (ifn? replacement)
+ (let [m (re-matcher regex string)]
+ (if (.find m)
+ (str (.subSequence string 0 (.start m))
+ (replacement (re-groups m))
+ (.subSequence string (.end m) (.length string)))
+ string))
+ (.. regex (matcher string) (replaceFirst replacement))))
+
(defn str-join
"Returns a string of all elements in 'sequence', separated by
diff --git a/src/clojure/contrib/test_contrib/str_utils.clj b/src/clojure/contrib/test_contrib/str_utils.clj
new file mode 100644
index 00000000..812821dc
--- /dev/null
+++ b/src/clojure/contrib/test_contrib/str_utils.clj
@@ -0,0 +1,33 @@
+(ns clojure.contrib.test-contrib.str-utils
+ (:use clojure.contrib.test-is
+ clojure.contrib.str-utils))
+
+
+(deftest test-re-gsub
+ (let [re #"\%([0-9a-fA-F]{2})"
+ replacement (fn [match]
+ (char (Integer/parseInt
+ (match 1) 16)))]
+ (is (= (re-gsub re replacement "") ""))
+ (is (= (re-gsub re replacement "%20") " "))
+ (is (= (re-gsub re replacement "x%20") "x "))
+ (is (= (re-gsub re replacement "x%20%0a") "x \n"))
+ (is (= (re-gsub re replacement "x%20y") "x y"))
+ (is (= (re-gsub re "?" "") ""))
+ (is (= (re-gsub re "?" "%21") "?"))
+ (is (= (re-gsub re "?" "x%22") "x?"))
+ (is (= (re-gsub re "?" "x%23y") "x?y"))))
+
+(deftest test-re-sub
+ (let [re #"\%([0-9a-fA-F]{2})"
+ replacement (fn [match]
+ (char (Integer/parseInt
+ (match 1) 16)))]
+ (is (= (re-sub re replacement "") ""))
+ (is (= (re-sub re replacement "%20") " "))
+ (is (= (re-sub re replacement "x%20%20") "x %20"))
+ (is (= (re-sub re replacement "x%20y") "x y"))
+ (is (= (re-sub re "?" "") ""))
+ (is (= (re-sub re "?" "%21") "?"))
+ (is (= (re-sub re "?" "x%22%25") "x?%25"))
+ (is (= (re-gsub re "?" "x%23y") "x?y"))))