exupero's blog

Babashka scripts to notify on stdin

I have a simple Obb script to display a notification, which I occasionally use to notify me when a long-running script completes. Here's the complete code:

(defn parse-args [args]
  (->> args
       (partition 2)
       (map (fn [[k v]]
              [(keyword (subs k 2)) v]))
       (into {})))
(let [{:keys [text title subtitle sound] :as m}
      , (parse-args *command-line-args*)
      app (js/Application.currentApplication)]
  (set! (.-includeStandardAdditions app) true)
  (.displayNotification app text #js {:withTitle title
                                      :subtitle (or subtitle "")
                                      :soundName (or sound "")}))

Recently, however, I wanted a notification triggered not by the completion of a script but by particular lines in its output. To do that, I created a Babashka script that iterates over line-seq:

(require '[clojure.java.io :as io]
         '[clojure.java.shell :as shell])
(let [[regex message] *command-line-args*]
  (doseq [line (line-seq (io/reader *in*))]
    (when (re-find (re-pattern regex) line)
      (shell/sh "notify" "--title" message "--sound" "tink"))))

I use the script to watch the output of build process, so I invoke the above Babashka command with arguments like this:

notify-on 'Uploaded build' 'New build uploaded'

I also wanted to see the original script's full output, and while I could print the output in the doseq body, I chose to use the moreutils command pee, which pipes its standard input to all given scripts and prints the combined outputs of those scripts:

build-script | pee cat "notify-on 'Uploaded build' 'New build uploaded'"