From aa8b89fe84ac7693cfb488b739ef086a37ca9e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madeleine=20Sydney=20=C5=9Alaga?= Date: Tue, 24 Feb 2026 09:43:47 -0700 Subject: [PATCH] --- doerg/src/net/deertopia/doerg/common.clj | 65 ++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/doerg/src/net/deertopia/doerg/common.clj b/doerg/src/net/deertopia/doerg/common.clj index 9a73d5c..ed5ed93 100644 --- a/doerg/src/net/deertopia/doerg/common.clj +++ b/doerg/src/net/deertopia/doerg/common.clj @@ -5,7 +5,7 @@ [clojure.java.io :as io]) (:import (java.io FilterInputStream StringWriter InputStream OutputStream PrintStream ByteArrayOutputStream - ByteArrayInputStream) + ByteArrayInputStream FilterOutputStream) (java.nio.charset StandardCharsets))) (defn deref-with-timeout [process ms] @@ -23,7 +23,10 @@ :timed-out-after-milliseconds ms})) @p))) -(defn tee-input-stream [sink input-stream] +(defn tee-input-stream + "Return a wrapped `InputStream` that writes all bytes read from + input-stream to sink, à la the UNIX command tee(1)." + [input-stream sink] (proxy [FilterInputStream] [input-stream] (read ([] @@ -45,16 +48,72 @@ (try (proxy-super close) (finally (.close sink)))))) +(defn tee-output-stream + "Return a wrapped `OutputStream` that writes all bytes written to + output-stream to sink, à la the UNIX command tee(1)." + [output-stream sink] + (proxy [FilterOutputStream] [output-stream] + (write + ([bs-or-b] + (proxy-super write bs-or-b) + (.write sink bs-or-b)) + ([^bytes bs off len] + (proxy-super write bs off len) + (.write sink bs off len))) + (close [] + (try (proxy-super close) + (finally (.close sink)))))) + +#_ +(defn hook-input-stream [input-stream hook] + (proxy [FilterInputStream] [input-stream] + (read + ([] + (let [c (proxy-super read)] + (when (not= c -1) + (hook (byte-array [c]))) + c)) + ([^bytes bs] + (let [n (proxy-super read bs)] + (when (not= n -1) + (let [bs* (byte-array n 0)] + (System/arraycopy bs 0 bs* 0 n) + (hook bs*))) + n)) + ([^bytes bs off len] + (let [n (proxy-super read bs off len)] + (when (not= n -1) + (.write sink bs off n)) + n))) + (close [] + (try (proxy-super close) + (finally (.close sink)))))) + (comment (with-open [sink (ByteArrayOutputStream.) out (ByteArrayOutputStream.) in (ByteArrayInputStream. (.getBytes "hello worms"))] - (io/copy (tee-input-stream sink in) out) + (io/copy (tee-input-stream in sink) out) + (def the-out out) + (def the-sink sink) + {:out out + :sink sink}) + (with-open [sink (l/log-stream :info "blah") + out (ByteArrayOutputStream.) + in (ByteArrayInputStream. (.getBytes "hello worms"))] + (io/copy (tee-input-stream in sink) out) (def the-out out) (def the-sink sink) {:out out :sink sink})) +(comment + (let [out (ByteArrayOutputStream.)] + (p/shell {:out (tee-output-stream + out + (l/log-stream :info "blah"))} + "echo" "hello" "worms"))) + (defn invoke [opts & cmd] (l/info (str/join " " (cons "$" cmd))) (let [r (apply p/shell