From e935ccae82f72e37f32a7d1ccab254ca2b664620 Mon Sep 17 00:00:00 2001
From: Phil Hagelberg <technomancy@gmail.com>
Date: Wed, 8 Dec 2010 22:52:57 -0800
Subject: [PATCH] subs should count backwards when given a negative argument.

---
 src/clj/clojure/core.clj             |   11 ++++++++---
 test/clojure/test_clojure/string.clj |    7 +++++++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 2664d0d..52261f4 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -4316,11 +4316,16 @@
 
 (defn subs
   "Returns the substring of s beginning at start inclusive, and ending
-  at end (defaults to length of string), exclusive."
+  at end (defaults to length of string), exclusive. Negative offsets count
+  from the end of the string."
   {:added "1.0"
    :static true}
-  (^String [^String s start] (. s (substring start)))
-  (^String [^String s start end] (. s (substring start end))))
+  (^String [^String s start] (subs s start (count s)))
+  (^String [^String s start end]
+    (let [count-back #(if (neg? %)
+                        (+ (count s) %)
+                        %)]
+      (.substring s (count-back start) (count-back end)))))
 
 (defn max-key
   "Returns the x for which (k x), a number, is greatest."
diff --git a/test/clojure/test_clojure/string.clj b/test/clojure/test_clojure/string.clj
index d6f6469..f08f847 100644
--- a/test/clojure/test_clojure/string.clj
+++ b/test/clojure/test_clojure/string.clj
@@ -118,3 +118,10 @@
     (is (vector? result)))
   (is (= (list "foo") (s/split-lines "foo"))))
 
+(deftest t-subs
+  (let [string "Nel mezzo del cammin di nostra vita."]
+    (is (= "del cammin di nostra vita." (subs string 10)))
+    (is (= "vita." (subs string -5)))
+    (is (= string (subs string 0)))
+    (is (= "di nostra vit" (subs string -15 -2)))
+    (is (= "Nel mezzo del cammin di nost" (subs string 0 -8)))))
-- 
1.7.1

