1 (in-package #:trivial-shell
)
4 (defmacro with-gensyms
(syms &body body
)
5 `(let ,(mapcar #'(lambda (s)
10 (defmacro with-stream-from-specifier
((stream stream-specifier direction
13 (with-gensyms (s close? result
)
21 (setf (values ,s
,close?
)
22 (make-stream-from-specifier
23 ,stream-specifier
,direction
,@args
))
26 (when (and ,close?
,s
)
27 (let ((it (close-stream-specifier ,s
)))
29 (setf (first ,result
) it
)))))
30 (values-list ,result
))))
32 (defmacro with-input
((var source
&rest args
) &body body
)
33 "Create an input stream from source and bind it to var within the body of the with-input form. The stream will be closed if necessary on exit."
34 `(with-stream-from-specifier (,var
,source
:input
,@args
)
37 (defmacro with-output
((var destination
&rest args
) &body body
)
38 "Create an output stream from source and bind it to var within the body of the with-output form. The stream will be closed if necessary on exit."
39 `(with-stream-from-specifier (,var
,destination
:output
,@args
)
42 (defgeneric make-stream-from-specifier
(specifier direction
&rest args
)
43 (:documentation
"Create and return a stream from specifier, direction and any other argsuments"))
45 (defgeneric close-stream-specifier
(steam)
46 (:documentation
"Close a stream and handle other bookkeeping as appropriate."))
48 (defmethod make-stream-from-specifier ((stream-specifier stream
)
49 (direction symbol
) &rest args
)
50 (declare (ignore args
))
51 (values stream-specifier nil
))
53 (defmethod make-stream-from-specifier ((stream-specifier (eql t
))
54 (direction symbol
) &rest args
)
55 (declare (ignore args
))
56 (values *standard-output
* nil
))
58 (defmethod make-stream-from-specifier ((stream-specifier (eql nil
))
59 (direction symbol
) &rest args
)
60 (declare (ignore args
))
61 (values (make-string-output-stream) t
))
63 (defmethod make-stream-from-specifier ((stream-specifier (eql :none
))
64 (direction symbol
) &rest args
)
65 (declare (ignore args
))
68 (defmethod make-stream-from-specifier ((stream-specifier pathname
)
69 (direction symbol
) &rest args
)
70 (values (apply #'open stream-specifier
:direction direction args
)
73 (defmethod make-stream-from-specifier ((stream-specifier string
)
74 (direction symbol
) &rest args
)
75 (let ((start (getf args
:start
0))
76 (end (getf args
:end
)))
77 (values (make-string-input-stream stream-specifier start end
) nil
)))
79 (defmethod make-stream-from-specifier ((stream-specifier string
)
80 (direction (eql :output
)) &rest args
)
81 (let ((if-does-not-exist (getf args
:if-does-not-exist
:create
)))
82 (remf args
:if-does-not-exist
)
83 (values (apply #'open stream-specifier
84 :direction direction
:if-does-not-exist if-does-not-exist args
)
87 (defmethod close-stream-specifier (s)
91 (defmethod close-stream-specifier ((s string-stream
))
93 (values (get-output-stream-string s
))