Skip to content

Instantly share code, notes, and snippets.

@corasaurus-hex
Created April 8, 2022 12:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corasaurus-hex/429d07ef9b3bd4ad2b42e945c6285a2e to your computer and use it in GitHub Desktop.
Save corasaurus-hex/429d07ef9b3bd4ad2b42e945c6285a2e to your computer and use it in GitHub Desktop.
(ns cora.exec
(:require [clojure.java.io :as io])
(:import (java.lang Process
ProcessBuilder$Redirect)
(java.io File
StringWriter)))
(defn exec
[command & {:keys [input-from output-to error-to]}]
(let [shell (or (System/getenv "SHELL") "sh")
builder (cond-> (ProcessBuilder. (into-array String [shell "-c" command]))
(instance? File input-from) (.redirectInput (ProcessBuilder$Redirect/from input-from))
(instance? File output-to) (.redirectOutput (ProcessBuilder$Redirect/to output-to))
(instance? File error-to) (.redirectError (ProcessBuilder$Redirect/to error-to))
(= :tty input-from) (.redirectInput (ProcessBuilder$Redirect/from (io/file "/dev/tty")))
(= :tty output-to) (.redirectOutput (ProcessBuilder$Redirect/to (io/file "/dev/tty")))
(= :tty error-to) (.redirectError (ProcessBuilder$Redirect/to (io/file "/dev/tty"))))
process (.start builder)]
(when (sequential? input-from)
(let [out (io/writer (.getOutputStream process))]
(doseq [line (seq input-from)]
(.write out (str line "\n")))
(.close out)))
{:exit (.waitFor process)
:err (when-not error-to
@(future
(with-open [err (StringWriter.)]
(io/copy (.getErrorStream process) err)
(.toString err))))
:out (when-not output-to
@(future
(with-open [out (StringWriter.)]
(io/copy (.getInputStream process) out)
(.toString out))))}))
;; Fuzzy finder for people that allows multiple selections
(prn (exec "fzf -m" :input-from ["Larry" "Curly" "Moe"], :error-to :tty))
;; {:exit 0, :err "", :out "Larry\nMoe\n"}
;; Fuzzy finders for files
(prn (exec "fzf" :input-from :tty, :error-to :tty))
;; {:exit 0, :err "", :out "clojurians-logs/download.rb\n"}
;; gets the terminal dimensions
(prn (exec "stty size" :input-from :tty))
;; {:exit 0, :err "", :out "40 220\n"}
;; shuts down the thread pool for futures. needed if you don't want things to hang for 1 minute before exiting
(shutdown-agents)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment