What if we want to capture standard (and/or error) output in order to ignore it or post-process it ? It’s very simple, a little search and we’re good:
(let ((*standard-output* (make-string-output-stream))
(*error-output* (make-string-output-stream)))
(apply function args) ;; anything
(setf standard-output (get-output-stream-string *standard-output*)))
(print-results standard-output))
and now in print-results
we can print to standard output without
being intercepted (and in our case, we’ll highlight some user-defined
keywords).
Above, just don’t forget to get the output content with
(get-output-stream-string *standard-output*)
.
A thing to note is that if your app printed stuff on error output and standard output consecutively, now it will print all standard output as a single block.
(edit) Of course, with-output-to-string
is simpler to capture one stream:
(setf standard-output (with-output-to-string (*standard-output*)
(apply function args)))
edit 2, thanks to redditers:
Don’t bind standard-output
directly; bind the string stream to a
lexical, then bind *standard-output*
to that:
(with-output-to-string (s)
(let ((*standard-output* s)) (write-string "abc")))
-> "abc"
Now, let’s bind both *standard-output*
and *standard-error*
to s:
(with-output-to-string (s)
(let ((*standard-output* s)
(*standard-error* s))
(write-string "abc")
(write-string "def" *standard-error*)))
-> "abcdef"
Eliminate s and just bind *standard-output*
and then tie
*standard-error*
to the same stream:
(with-output-to-string (*standard-output*)
(let ((*standard-error* *standard-output*))
(write-string "abc")
(write-string "def" *standard-error*)))
--> "abcdef"
The conclusion stays: it’s handy and easy :)