summaryrefslogtreecommitdiff
path: root/src/streams.lisp
blob: 766cf0768974b00cea08a8412ff94be4d2edbb22 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
;; SPDX-License-Identifier: EUPL-1.2
;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
(defpackage :ukkoclot/src/streams
  (:documentation "Stream-oriented utilities.")
  (:import-from :serapeum :-> :with-thunk)
  (:use :c2cl)
  (:export :call-with-format-like-stream :with-format-like-stream))
(in-package :ukkoclot/src/streams)

(-> call-with-format-like-stream ((or stream boolean) (function (stream) t)) t)
(defun call-with-format-like-stream (stream-spec fn)
  "Similar to `with-format-like-stream', but instead of binding the translated stream in a macro body,
calls the function `fn' with it."
  (case stream-spec
    ((t) (funcall fn *standard-output*) nil)
    ((nil) (with-output-to-string (stream) (funcall fn stream)))
    (otherwise (funcall fn stream-spec) nil)))

(defmacro with-format-like-stream ((stream-out stream-spec) &body body)
  "Translates the `stream-spec' into a `stream' similar to how `format' does it and binds it as `stream-out' in `body'.

If `stream-spec' is `t': Output to `*standard-output*' and return `nil'.
If `stream-spec' is `nil': Output to a string and return it.
Else: `stream-spec' must be a stream, output to it and return `nil'"
  (with-thunk (body stream-out)
    `(call-with-format-like-stream ,stream-spec ,body)))