-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
with-output-to-destination #155
Comments
I've just realized this is equivalent to UIOP/STREAM:WITH-OUTPUT |
My version supports passing arguments to OPEN when opening files, and that's important for my use cases, as I may want to overwrite, etc. So this may still be useful. |
The one concern I have it here is interpreting strings as files -- |
Ok. I'll improve it
El dom., 23 jul. 2023 11:28, Paul M. Rodriguez ***@***.***>
escribió:
… The one concern I have it here is interpreting strings as files --
cl:with-output-to-string, serapeum:with-string, and uiop:with-output all
allow writing to a string with a fill pointer as if it were a stream. The
function should at least check for a fill pointer and treat it as a stream
in that case.
—
Reply to this email directly, view it on GitHub
<#155 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADKPDWQN4VDKRTMIZ3QLBLXRUYHHANCNFSM6AAAAAA2UPODMU>
.
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
How about this: (defun call-with-output-to-destination (destination function &rest args)
"Evaluate FUNCTION with a stream created from DESTINATION as argument.
If DESTINATION is a pathname, then open the file for writing. ARGS are used in the OPEN call.
If it is a string with a fill-pointer, WITH-OUTPUT-TO-STRING is used to create a stream for it.
If it is a stream, then it is used as it is.
If it is NIL, then WITH-OUTPUT-TO-STRING is used to create the stream.
If it is T, then *STANDARD-OUTPUT* is used for the stream."
(etypecase destination
(pathname
(let ((stream (apply #'open destination :direction :output args)))
(unwind-protect
(funcall function stream)
(close stream))))
(string
(assert (array-has-fill-pointer-p destination)
nil "Destination string doesn't have a fill-pointer")
(let ((result nil))
(with-output-to-string (stream destination)
(setf result (funcall function stream)))
result))
(stream
(funcall function destination))
(null
(with-output-to-string (stream)
(funcall function stream)))
((eql t)
(funcall function *standard-output*))))
(defmacro with-output-to-destination ((var destination &rest args) &body body)
"Evaluate BODY with VAR bound to a stream created from DESTINATION.
If DESTINATION is a pathname, then open the file for writing. ARGS are used in the OPEN call.
If it is a string with a fill-pointer, use WITH-OUTPUT-TO-STRING to create a stream for it.
If it is a stream, then it is used as it is.
If it is NIL, then WITH-OUTPUT-TO-STRING is used to create the stream.
If it is T, then *STANDARD-OUTPUT* is used for the stream."
`(call-with-output-to-destination ,destination (lambda (,var) ,@body) ,@args)) Strings are not interpreted as pathnames anymore, to avoid any confusion. And are required to have a fill-pointer. |
That sounds good to me, if you'd like to make an MR. |
Hi.
I use this macro in some of my systems, to write to an output stream created from a "destination" spec:
*standard-output*
.Similar to CL:FORMAT destination argument, but also writes to files.
I've opened this issue in case you are interested and would like to include in Serapeum.
The text was updated successfully, but these errors were encountered: