Skip to content

Commit 82b5b9a

Browse files
committed
Add CLI option to parallelize file processing
The files processed by the 'fix' and 'check' commands can be processed in an arbitrary order and each file can be processed independently, so the whole process can be parallelized. To make sure threads aren't writing to stdout/stderr at the same time, the result for each file is captured and then printed in order once every file is done. The 'check' command already did this via print-file-status, the 'fix' command now uses the same mechanism.
1 parent a6c2100 commit 82b5b9a

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

cljfmt/src/cljfmt/main.clj

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080
(when-let [ex (:exception status)]
8181
(warn "Failed to format file:" path)
8282
(print-stack-trace ex))
83+
(when (:reformatted status)
84+
(println "Reformatting" path))
8385
(when-let [diff (:diff status)]
8486
(warn path "has incorrect formatting")
8587
(warn diff))))
@@ -111,34 +113,40 @@
111113
([paths]
112114
(check paths {}))
113115
([paths options]
114-
(let [counts (transduce
115-
(comp (mapcat (partial find-files options))
116-
(map (partial check-one options))
117-
(map (fn [status]
118-
(print-file-status options status)
119-
(:counts status))))
120-
(completing merge-counts)
121-
paths)]
116+
(let [map* (if (:parallel? options) pmap map)
117+
counts (->> paths
118+
(mapcat (partial find-files options))
119+
(map* (partial check-one options))
120+
(map (fn [status]
121+
(print-file-status options status)
122+
(:counts status)))
123+
(reduce merge-counts))]
122124
(print-final-count counts)
123125
(exit counts))))
124126

127+
(defn- fix-one [options file]
128+
(let [original (slurp file)]
129+
(try
130+
(let [revised (reformat-string options original)]
131+
(if (not= original revised)
132+
(do (spit file revised)
133+
{:file file :reformatted true})
134+
{:file file}))
135+
(catch Exception e
136+
{:file file :exception e}))))
137+
125138
(defn fix
126139
"Applies the formatting (as per `options`) to the Clojure files
127140
contained in `paths`."
128141
([paths]
129142
(fix paths {}))
130143
([paths options]
131-
(let [files (mapcat (partial find-files options) paths)]
132-
(doseq [^java.io.File f files]
133-
(let [original (slurp f)]
134-
(try
135-
(let [revised (reformat-string options original)]
136-
(when (not= original revised)
137-
(println "Reformatting" (project-path options f))
138-
(spit f revised)))
139-
(catch Exception e
140-
(warn "Failed to format file:" (project-path options f))
141-
(print-stack-trace e))))))))
144+
(let [map* (if (:parallel? options) pmap map)]
145+
(->> paths
146+
(mapcat (partial find-files options))
147+
(map* (partial fix-one options))
148+
(map (partial print-file-status options))
149+
dorun))))
142150

143151
(defn- cli-file-reader [filepath]
144152
(let [contents (slurp filepath)]
@@ -149,7 +157,8 @@
149157
(def default-options
150158
{:project-root "."
151159
:file-pattern #"\.clj[csx]?$"
152-
:ansi? true})
160+
:ansi? true
161+
:parallel? false})
153162

154163
(defn merge-default-options [options]
155164
(-> (merge default-options options)
@@ -160,6 +169,8 @@
160169

161170
(def ^:private cli-options
162171
[[nil "--help"]
172+
[nil "--parallel"
173+
:id :parallel?]
163174
[nil "--file-pattern FILE_PATTERN"
164175
:default (:file-pattern default-options)
165176
:parse-fn re-pattern]
@@ -207,7 +218,9 @@
207218
(if (or (nil? cmd) (:help options))
208219
(do (println "cljfmt [OPTIONS] COMMAND [PATHS ...]")
209220
(println (:summary parsed-opts)))
210-
(case cmd
211-
"check" (check paths options)
212-
"fix" (fix paths options)
213-
(abort "Unknown cljfmt command:" cmd))))))
221+
(do (case cmd
222+
"check" (check paths options)
223+
"fix" (fix paths options)
224+
(abort "Unknown cljfmt command:" cmd))
225+
(when (:parallel? options)
226+
(shutdown-agents)))))))

0 commit comments

Comments
 (0)