 ;; vector of the names of files where the filter term appears on a changed line.
 ;; If no filter term is given, a changed file automatically matches.
 
-(defn matching-files [r1 r2 item term]
+(defn matching-files [r1 r2 item filt]
   (let [blocks (rest (split (:out (diff r1 r2 item)) #"^Index: |\nIndex: "))]
     (remove nil?
             (into []
                   (for [block blocks]
-                    (let [lines (split-lines block)
-                          filename (trim (first lines))
-                          changes (filter #(re-matches #"^[+-][^+-].*" %) lines)
-                          re (re-pattern (str ".*" term ".*"))
-                          matching-line-in #(re-matches re %)]
-                      (if (some matching-line-in changes) filename)))))))
+                    (let [matching-line-in? #(re-matches (re-pattern filt) %)
+                          diff-line? #(re-matches #"^[+-][^+-].*" %)
+                          strip+- #(clojure.string/replace % #"^[+-]" "")
+                          all-lines (split-lines block)
+                          diff-lines (filter diff-line? all-lines)
+                          changes (map strip+- diff-lines)
+                          filename (trim (first all-lines))]
+                      (if (some matching-line-in? changes) filename)))))))
 
-;; Run "svn diff" on the file/pathname in index. The format of the file/path
+;; Run "svn diff" on the file/pathname in object. The format of the file/path
 ;; name following "Index:" in diff's output depends on the argument: If the
-;; argument is a filesystem pathname, the index name is absolute, and we can
-;; simply use that. If the argument is a uri, the index name is relative to the
+;; argument is a filesystem pathname, the object name is absolute, and we can
+;; simply use that. If the argument is a uri, the object name is relative to the
 ;; base item name. If the base item name was the uri to a file (and therefore a
 ;; complete pathname) we can use item; if it was the uri to a directory, we have
-;; to concatenate the item and index to form a complete pathname.
+;; to concatenate the item and object to form a complete pathname.
 
-(defn svndiff [r1 r2 index item]
-  (let [r (re-pattern (str "^.*/" index "$"))
+(defn svndiff [r1 r2 object item]
+  (let [item (baseitem item)
+        r (re-pattern (str "^.*/" object "$"))
         p (if (uri? item)
-            (if (re-matches r item) item (str item "/" index))
-            index)
+            (if (re-matches r item) item (str item "/" object))
+            object)
         v (vpaths r1 r2 p item)]
     (sh "svn" "diff" (first v) (second v))))
 
-;; Given a list of revision pairs, diff those for which the given filter term (if
-;; any) is present on a changed line in that pair. If no filter term is given,
-;; diff all changed files from all revision pairs.
+;; Given a list of revision pairs, diff those for which the given filter term
+;; (if any) is present on a changed line in that pair. If no filter term is
+;; given, diff all changed files from all revision pairs.
 
-(defn diffrevpairs [item term revpairs]
+(defn diffrevpairs [item filt revpairs]
   (when (seq revpairs)
     (let [r1 (first revpairs)
           r2 (first (rest revpairs))
-          mf (matching-files r1 r2 item term)]
+          mf (matching-files r1 r2 item filt)]
       (println (str "Checking: r" r1 " vs r" r2))
-      (doseq [index mf] (svndiff r1 r2 index item))
-      (diffrevpairs item term (rest (rest revpairs))))))
+      (doseq [object mf] (svndiff r1 r2 object item))
+      (diffrevpairs item filt (rest (rest revpairs))))))
 
 (defn usage []
-  (println (str "\nUsage: revdiff item [term]\n"))
-  (println "  item : svn uri or name of versioned working-copy object")
-  (println "  term : only show diffs with term present on a changed line\n"))
+  (println (str "\nUsage: revdiff item [regex]\n"))
+  (println "  item  : svn uri or name of versioned working-copy object")
+  (println "  regex : only show diffs where a changed line matches regex\n"))
 
 (defn -main [& args]
-  (let [item (first args) term (second args)]
+  (let [item (first args) filt (or (second args) ".*")]
     (if (not item)
       (usage)
-      (diffrevpairs item term (revpairs (revlist item) item)))))
+      (do
+        (diffrevpairs item filt (revpairs (revlist item) item))
+        (shutdown-agents)))))

    (list (str path "@" r1) (str path "@" r2))
    (list (str "-r" r1 ":" r2) path)))
  
;; A string containing the output of "diff" on the two svn revision of item.

(defn diff [r1 r2 item]
  (let [v (vpaths r1 r2 item item)]
    (sh "svn" "diff" "--diff-cmd" "diff" "-x" "-u0" shhh (first v) (second v))))

;; Obtain a diff from svn for the given item between the specified revisions.

;; copy to avoid following the history of a differently-named object.

(defn log [item] (:out (sh "svn" "log" shhh "--stop-on-copy" "--xml" item)))

;; Try to explain why this has failed.

