Skip to content
This repository has been archived by the owner on Oct 2, 2020. It is now read-only.

Commit

Permalink
Merge pull request #47 from guns/preserve-comment-headers
Browse files Browse the repository at this point in the history
Preserve file comment headers
  • Loading branch information
technomancy committed Sep 13, 2013
2 parents a3cf425 + 3c058a0 commit 1087042
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
45 changes: 38 additions & 7 deletions src/slam/hound.clj
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
(ns slam.hound
(:require [clojure.java.io :as io]
[clojure.string :as string]
[slam.hound.asplode :refer [asplode]]
[slam.hound.regrow :refer [regrow]]
[slam.hound.stitch :refer [stitch-up]])
(:import (java.io File FileReader PushbackReader)))
(:import (java.io File PushbackReader)))

(defn reconstruct [filename]
;; Reconstructing consists of three distinct phases:
Expand All @@ -13,21 +14,51 @@
regrow
stitch-up))

(defn read-comment-header
"Read leading blank and comment lines from rdr."
[^PushbackReader rdr]
;; An implementation using bufferedReader#readLine would be simpler, but
;; would have to make an assumption about what kind of line terminators the
;; file actually contains.
(loop [buf (StringBuilder.) state :ws]
(let [c (.read rdr)]
(if (= c -1) ; EOF
(str buf)
(let [ch (char c)]
(case state
:comment (recur (.append buf ch)
;; CRLF and LF both end with LF
(if (= ch \newline) :ws :comment))
:ws (cond (= ch \;) (recur (.append buf ch) :comment)
(Character/isWhitespace ch) (recur (.append buf ch) :ws)
:else (do (.unread rdr c) (str buf)))))))))

(defn- tidy-comment-header [s]
(-> s
(string/replace-first #"(?s)\A\s*\n" "")
(string/trimr)
(str "\n\n")))

(defn swap-in-reconstructed-ns-form
"Reconstruct file's ns form and rewrite the file on disk with the new form."
[file]
(let [tmp-file (doto (File/createTempFile "slamhound_tmp" ".clj")
.deleteOnExit)
_ (io/copy file tmp-file)
_ (do (io/copy file tmp-file)
(io/copy "" file))
new-ns (.trim (reconstruct tmp-file))]
(with-open [rdr (PushbackReader. (io/reader tmp-file))]
(with-open [rdr (PushbackReader. (io/reader tmp-file))
writer (io/writer file :append true)]
;; Preserve comment header
(let [header (read-comment-header rdr)]
(when-not (string/blank? header)
(io/copy (tidy-comment-header header) writer)))
;; move the reader past the namespace form; discard value
(read rdr)
;; copy in the reconstructed ns form
(io/copy new-ns file)
;; append the reconstructed ns form
(io/copy new-ns writer)
;; append the body
(with-open [writer (io/writer file :append true)]
(io/copy rdr writer)))))
(io/copy rdr writer))))

(defn -main
"Takes a file or dir and rewrites the .clj files with reconstructed ns forms."
Expand Down
19 changes: 17 additions & 2 deletions test/slam/hound_test.clj
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
(ns slam.hound-test
(:require [clojure.java.io :as io]
[clojure.test :refer [deftest is testing]]
[slam.hound :refer [reconstruct -main]])
(:import (java.io File StringReader)))
[slam.hound :refer [read-comment-header reconstruct -main]])
(:import (java.io File PushbackReader StringReader)))

(deftest ^:unit test-read-comment-header
(testing "preserves comments at top of file"
(is (= ";;\n;; Copyright © Phil Hagelberg\n;;\n\n"
(read-comment-header
(PushbackReader.
(StringReader.
";;\n;; Copyright © Phil Hagelberg\n;;\n\n(ns test)"))))))
(testing "returns headers faithfully"
(is (= "\n\r\n\t;; COPYRIGHT \n\r\n\t;; LICENSE \n\r\n"
(read-comment-header
(PushbackReader.
(StringReader.
(str "\n\r\n\t;; COPYRIGHT \n\r\n"
"\t;; LICENSE \n\r\n(ns test)"))))))))

(def basic-ns (str '(ns slamhound.sample
"Testing some things going on here."
Expand Down

0 comments on commit 1087042

Please sign in to comment.