diff --git a/site-modules/core/files/bin/pf b/site-modules/core/files/bin/pf new file mode 100755 index 0000000..82bf357 --- /dev/null +++ b/site-modules/core/files/bin/pf @@ -0,0 +1,80 @@ +#!/usr/bin/env bb +;; vi: ft=clojure +;; +;; A Procfile runner for tmux. Each procfile will have its own tmux session and +;; each process will have its own window. This way you can use tmux to attach +;; view logs and also restart individual processes. +;; +(require '[babashka.process :refer [shell]] + '[babashka.cli :as cli] + '[babashka.fs :as fs] + '[clojure.string :as string]) + +(defn current-project-name + "Returns the current project name based on the current working directory. + This assumes you have our porjects organised in a GOPATH style. This will + return the last two components of the current working directory, that should + be {org}/{project}" + [] + (string/join "/" (map #(.toString %) (take 2 (reverse(fs/components (fs/cwd))))))) + +(defn parse-procfile + "Parses a procfile file and returns a list of [name command] pairs." + [] + (map #(string/split % #":\s+") (string/split (slurp "Procfile.dev") #"\n" ))) + +(defn has-session? + "Tests to see if a session already exists with a given name." + [session-name] + (string/includes? (:out (shell {:out :string} "tmux list-sessions")) session-name)) + +(defn has-window? + "Tests to see if a window already exists within a tmux session." + [session-name window-name] + (string/includes? (:out (shell {:out :string} (format "tmux list-windows -t '%s'" session-name))) window-name)) + +(defn create-window + "Creates a new tmux window in a session if it dose not already exists. Then + it will run any commands that are passed inside the new window." + [project name & commands] + (when-not (has-window? project name) + (shell (format "tmux new-window -t '%s' -n '%s'" project name)) + (doseq [command commands] + (shell (format "tmux send-keys -t %s:'%s' '%s' C-m" project name command))))) + +(defn command-start [_] + (when (not (fs/exists? "Procfile.dev")) + (println "No Procfile.dev found in the current directory") + (System/exit 0)) + + (when (not (has-session? (current-project-name))) + (shell (format "tmux new-session -d -c %s -s '%s'" (fs/cwd) (current-project-name)))) + + (doseq [[name command] (parse-procfile)] + (create-window (current-project-name) name command))) + +(defn command-stop [_] + (when (has-session? (current-project-name)) + (shell (format "tmux kill-session -t '%s'" (current-project-name))))) + +(defn command-restart [args] + (command-stop args) + (command-start args)) + +(defn help [_m] + (println "A Procfile runner for tmux") + (println "") + (println "\033[1mCommands:\033[0m") + (println " start Start all of the processes in your Procfile.dev") + (println " stop Stop all the currently running processes") + (println " restart Restart all of the processes") + (println "")) + +(def command-table + [{:cmds ["start"] :fn command-start} + {:cmds ["stop"] :fn command-stop} + {:cmds ["restart"] :fn command-restart} + {:cmds [] :fn help}]) + +(cli/dispatch command-table *command-line-args*) +