Clojureでタスクランナーを書く
code:sh
clojure tasks.clj help
rlwrap -c -b "(){}[],^%$#@\"\";:''|\\" clojure tasks.clj repl
code:deps.edn
{:deps {
cljfmt {:mvn/version "0.6.7"}
org.clojure/core.async {:mvn/version "1.1.587"}}}
code:tasks.clj
;#!/usr/bin/env clojure
(require '[clojure.core.async :as async :refer >!!])
(def tasks (ref {}))
(dosync (alter tasks assoc task-name {:doc doc :body (conj body 'do)}))
nil)
(let [tasks @tasks
task-name (symbol task-name)]
(if (contains? tasks task-name)
(->> tasks task-name :body eval)
(do (println (format "Task %s not found." task-name))
(System/exit 1)))))
(defn help []
(println (format "%-16s\t%s" 'help "Show this help."))
(println (format "%-16s\t%s" 'repl "Start a REPL."))
(println (format "%-16s\t%s" task-name (:doc task)))))
(defn repl []
(println "(help) to print a help.")
(println "(act :TASK-NAME) to run the task.")
(help)
(clojure.main/repl))
(defn sh args
(println (clojure.string/join " " (conj args "+")))
(if (= 0 exit)
(print err out)
(do (print (format "Exit with %d\n" exit) out err)
(System/exit exit)))))
(let [nproc (.availableProcessors (Runtime/getRuntime))
chan (async/chan (* nproc 2))
threads (into []
(let [on-exit (async/chan)
(if data
(do (consumer data)
(async/close! on-exit)))]
{:on-exit on-exit :thread thread}))
(range (* nproc 2))))]
(provider chan)
(async/close! chan)
(<!! on-exit)
(async/close! thread))))
(deftask format
"Format all stuffs."
(println "+ clojure -m cljfmt.main fix .")
(cljfmt/fix "." (cljfmt/merge-default-options {})) (sh "npx" "prettier" "--write" "package.json")
(sh "npx" "prettier" "--parser" "yaml" "--write" ".yamllint" ".github/workflows/*.yml")
(>!! chan "./README.md")
(doseq [dir (filter (fn file (and (.isDirectory file) (not (re-find #"^." (.getPath file))))) (.listFiles (io/file ".")))
path (filter (fn file (and (.isFile file) (string/ends-with? (.getPath file) ".md"))) (file-seq dir))]
(>!! chan (.getPath path))))
(sh "npx" "prettier" "--write" path)
(sh "npx" "textlint" "--fix" path))))
(cond
(or (empty? argv) (some #(= % "help") argv)) (help) (some #(= % "repl") argv) (repl) :else
(System/exit 0))))
(main (vec *command-line-args*))
helpはMakefileのを移植したもの
code:Makefile
.PHONY: help
help:
@awk -F':.*##' '/^-_a-zA-Z0-9+:.*##/{printf"%-16s\t%s\n",$$1,$$2}' $(MAKEFILE_LIST) | sort .PHONY: example
format: ## Format all stuffs.
clojure -m cljfmt.main fix .
npx prettier --write package.json
npx prettier --parser yaml --write .yamllint .github/workflows/*.yml
ag -g '\.md$' | xargs -t -P "$(($(nproc) * 2))" -I {} sh -eux -c 'npx prettier --write "{}" && npx textlint --fix "{}"'