diff --git a/src/data/CCMixtbl.mli b/src/data/CCMixtbl.mli index a315b41a..5878624e 100644 --- a/src/data/CCMixtbl.mli +++ b/src/data/CCMixtbl.mli @@ -25,7 +25,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (** {1 Hash Table with Heterogeneous Keys} -From https://github.com/mjambon/mixtbl , thanks to him. +From https://github.com/mjambon/mixtbl (thanks to him). Example: {[ diff --git a/src/unix/CCUnix.ml b/src/unix/CCUnix.ml index ec739f0f..6d51723c 100644 --- a/src/unix/CCUnix.ml +++ b/src/unix/CCUnix.ml @@ -113,3 +113,36 @@ let call ?(bufsize=2048) ?(stdin=`Str "") ?(env=[||]) cmd = end ) +type line = string + +type async_call_result = + < stdout:line gen; + stderr:line gen; + stdin:line -> unit; (* send a line *) + close_in:unit; (* close stdin *) + close_err:unit; + close_out:unit; + wait:Unix.process_status; (* block until the process ends *) + > + +let async_call ?(env=[||]) cmd = + (* render the command *) + let buf = Buffer.create 256 in + kbprintf' buf cmd + (fun buf -> + let cmd = Buffer.contents buf in + let oc, ic, errc = Unix.open_process_full cmd env in + object + method stdout () = + try Some (input_line oc) + with End_of_file -> None + method stderr () = + try Some (input_line errc) + with End_of_file -> None + method stdin l = output_string ic l; output_char ic '\n' + method close_in = close_out ic + method close_out = close_in oc + method close_err = close_in errc + method wait = Unix.close_process_full (oc, ic, errc) + end + ) diff --git a/src/unix/CCUnix.mli b/src/unix/CCUnix.mli index e1e75ba7..fcadd8ec 100644 --- a/src/unix/CCUnix.mli +++ b/src/unix/CCUnix.mli @@ -73,5 +73,27 @@ val call : ?bufsize:int -> (call "echo %s" "a'b'c")#stdout = "abc\n" *) +type line = string + +type async_call_result = + < stdout:line gen; + stderr:line gen; + stdin:line -> unit; (* send a line *) + close_in:unit; (* close stdin *) + close_err:unit; + close_out:unit; + wait:Unix.process_status; (* block until the process ends *) + > +(** A subprocess for interactive usage (read/write channels line by line) + @since NEXT_RELEASE *) + +val async_call : ?env:string array -> + ('a, Buffer.t, unit, async_call_result) format4 -> + 'a +(** Spawns a subprocess, like {!call}, but the subprocess's channels are + line generators and line sinks (for stdin). + if [p] is [async_call "cmd"], then [p#wait] waits for the subprocess + to die. Channels can be closed independently. + @since NEXT_RELEASE *)