(module utils racket
(require racket/system (for-syntax racket/syntax))
(provide process*)
(provide (contract-out [close-these-ports: (->* () #:rest (listof (or/c input-port? output-port?)) void?)]))
(define (close-these-ports: . ps)
(for ([p ps] #:when p)
(cond
[(input-port? p) (close-input-port p)]
[(output-port? p) (close-output-port p)])))
(provide with-external-command-as)
(define-syntax (with-external-command-as stx)
(syntax-case stx ()
[(_ p-nick x y action ...)
(with-syntax
([nick-stdout (format-id stx "~a-stdout" #'p-nick)]
[nick-stdin (format-id stx "~a-stdin" #'p-nick)]
[nick-pid (format-id stx "~a-pid" #'p-nick)]
[nick-stderr (format-id stx "~a-stderr" #'p-nick)]
[nick-ctrl (format-id stx "~a-ctrl" #'p-nick)]
)
(syntax-case #'x ()
[(com arg ...)
#`(let*
([p-params (process* (find-executable-path com) arg ...)]
[nick-stdout (car p-params)]
[nick-stdin (cadr p-params)]
[nick-pid (caddr p-params)]
[nick-stderr (cadddr p-params)]
[nick-ctrl (cadr (cdddr p-params))])
(define results (let () y action ...))
(close-these-ports: nick-stdout nick-stdin nick-stderr)
results)]
[#:cmdline
#`(let*
([p-params (apply process* (find-executable-path (car y)) (cdr y))]
[nick-stdout (car p-params)]
[nick-stdin (cadr p-params)]
[nick-pid (caddr p-params)]
[nick-stderr (cadddr p-params)]
[nick-ctrl (cadr (cdddr p-params))])
(define results (let () #t action ...))
(close-these-ports: nick-stdout nick-stdin nick-stderr)
results)]))]))
(provide with-subprocess-as)
(define-syntax (with-subprocess-as stx)
(syntax-case stx ()
[(_ p-nick outp inp errp (com arg ...) action ...)
(with-syntax
([nick-process (format-id stx "~a-process" #'p-nick)]
[nick-stdout (format-id stx "~a-stdout" #'p-nick)]
[nick-stdin (format-id stx "~a-stdin" #'p-nick)]
[nick-stderr (format-id stx "~a-stderr" #'p-nick)])
#`(let-values
([(nick-process nick-stdout nick-stdin nick-stderr)
(subprocess outp inp errp (find-executable-path com) arg ...)])
(let ([results (let () action ...)])
(when nick-stdout (close-input-port nick-stdout))
(when nick-stdin (close-output-port nick-stdin))
(when nick-stderr (close-input-port nick-stderr))
results)))]))
(provide run-pipeline)
(define-syntax (run-pipeline stx)
(syntax-case stx ()
[(_ pipe-stdout pipe-stdin (s arg ...))
#`(let-values
([(process out-inp in-outp err-inp)
(subprocess pipe-stdout pipe-stdin (current-error-port) (find-executable-path s) arg ...)])
(when in-outp (close-output-port in-outp))
out-inp)]
[(_ pipe-stdout pipe-stdin (s arg ...) (s0 arg0 ...) ...)
#`(let-values
([(process out-inp in-outp err-inp)
(subprocess #f pipe-stdin (current-error-port) (find-executable-path s) arg ...)])
(let ([result (run-pipeline
pipe-stdout out-inp
(s0 arg0 ...) ...)])
(when out-inp (close-input-port out-inp))
(when in-outp (close-output-port in-outp))
result))]))
)