Skip to content

Instantly share code, notes, and snippets.

@ordnungswidrig
Last active July 8, 2025 09:39
Show Gist options
  • Select an option

  • Save ordnungswidrig/6605483ac429a399a644024a6736ecf0 to your computer and use it in GitHub Desktop.

Select an option

Save ordnungswidrig/6605483ac429a399a644024a6736ecf0 to your computer and use it in GitHub Desktop.

Revisions

  1. ordnungswidrig revised this gist May 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion babash.bb
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    #!/usr/bin/enb rlwrap bb -i
    #!/usr/bin/env rlwrap bb -i

    ;; needs babashka beta

  2. ordnungswidrig revised this gist May 27, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion babash.bb
    Original file line number Diff line number Diff line change
    @@ -68,7 +68,7 @@

    (defn cmd-cd [cmd_ args_]
    (if (> (count args_) 1)
    (println (format "%s: %s: %s" cmd_ "too many arguments"))
    (println (format "%s: %s" cmd_ "too many arguments"))

    (let [target (or (first args_) (str (fs/home)))
    dir (if (fs/absolute? target) target
  3. ordnungswidrig created this gist May 27, 2022.
    125 changes: 125 additions & 0 deletions babash.bb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,125 @@
    #!/usr/bin/enb rlwrap bb -i

    ;; needs babashka beta

    (defn ^sun.misc.Signal ->signal
    "Convert a keyword to an appropriate Signal instance."
    [signal]
    (sun.misc.Signal. (-> signal name .toUpperCase)))

    (defn ^Long signal->number
    "Find out a signal's number"
    [signal]
    (-> signal ->signal .getNumber))

    (defn ^clojure.lang.Keyword signal->kw
    "Translate a signal to a keyword"
    [^sun.misc.Signal s]
    (-> s .getName .toLowerCase keyword))

    (defn ^sun.misc.SignalHandler ->handler
    "Convert class to signal handler."
    [handler]
    (proxy [sun.misc.SignalHandler] []
    (handle [sig] (handler (signal->kw sig)))))

    (defn on-signal
    "Execute handler when signal is caught"
    [signal handler]
    (sun.misc.Signal/handle (->signal signal) (->handler handler)))


    (def waiting-for-input (atom true))

    (def ^:dynamic *handlers*
    {:_ (fn [sig] (println "SIGNAL: " sig))
    :int (fn [sig]
    (when @waiting-for-input
    (println "Use quit to exit.")))})

    (defn handle-signal [sig]
    (when-let [h (or (get *handlers* sig)
    (get *handlers* :_))]
    (h sig)))

    (defmacro with-handlers
    [handlers & body]

    `(binding [*handlers* (merge *handlers* ~handlers)]
    ~@body))


    (doseq [s [:hup :int :quit :pipe :alrm :term :usr1 :usr2 :chld :ttin :ttou :winch]]
    (on-signal s handle-signal))

    (require '[babashka.process :refer [process check]])
    (require '[clojure.string :as str])
    (require '[babashka.fs :as fs])

    ;; babash(ka) sh(ell)
    (println "Welcome to babash...")

    (def cwd (atom (-> (io/file".") fs/absolutize (fs/canonicalize {:nofollow-links true})str)))

    (defn prompt! []
    (let [home (str (fs/home))
    d (str/replace @cwd home "~")]
    (print "" d "> ")) (flush))

    (defn cmd-cd [cmd_ args_]
    (if (> (count args_) 1)
    (println (format "%s: %s: %s" cmd_ "too many arguments"))

    (let [target (or (first args_) (str (fs/home)))
    dir (if (fs/absolute? target) target
    (io/file @cwd target))]
    (if (fs/exists? dir)
    (if (fs/directory? dir)
    (do
    (reset! cwd (-> dir
    (fs/canonicalize {:nofollow-links true})
    str)))
    (println (format "%s: %s: %s" cmd_ "not a directory" (first args_))))
    (println (format "%s: %s: %s" cmd_ "no such file or directory" (first args_)))))))


    (prompt!)
    (doseq [i *input*]
    (let [i (.trim i)
    [cmd_ & args_] (str/split i #"\s+")]
    (try
    (cond
    (= "" i)
    :nop

    (= "quit" i)
    (do
    (println "Tschüß...")
    (System/exit 0))

    (= "pwd" cmd_)
    (println @cwd)

    (= "cd" cmd_)
    (cmd-cd cmd_ args_)

    :else
    ;; tokenize with edn
    (do
    (let [reader (java.io.PushbackReader. (java.io.StringReader. i))
    cmd i
    #_(take-while #(not= ::eof %)
    (repeatedly #(edn/read {:eof ::eof} reader)))]
    ;; (println "Running" (pr-str cmd))
    (try (reset! waiting-for-input true)
    (.flush *out*) (.flush *err*)
    (-> (let [o @(process cmd {:dir @cwd :inherit true})]
    (.flush *out*) (.flush *err*)))
    (catch java.io.IOException e
    (binding [*out* *err*]
    (println (.getMessage e))))
    (finally
    (reset! waiting-for-input false))))))
    (prompt!)
    (catch Exception e
    (println "GOT" e)))))