Client.subscribe
Acquire verified coverage through one shared lane per session; choose the least observed session ID unless supplied. A client-owned reader delivers future bytes without application callbacks. Default queue bounds are 1 MiB/1024 events; max 16 subscribers and eight total client lanes, sharing the 32 MiB payload budget. Queue capacities remain reserved while empty; captures and reads need additional scratch space and can return Libtmux.Error.Capacity below the subscriber-count limit. See the shared capacity guide for combined reservations and process slots.
Source and package
- Qualified name
-
Libtmux_eio .Client. subscribe - Module
- Libtmux_eio
- Declared in
Client- Package
- libtmux-eio
- Source
- eio/libtmux_eio.mli
- val subscribe : ?session:Libtmux
.Session -> ?capacity_bytes:int -> ?capacity_events:int -> t -> Libtmux.target .Pane -> (Subscription.t .t , Libtmux.Error ) result.t -
Public owner:
Libtmux_eioDescription#
Overflow or coverage/layout changes emit Gap then End. Data starts after admission's marker, with no snapshot/history barrier, automatic reconnect or silent cursor reuse. New admission returns
Error Libtmux.Error.Closedonceclosestarts.Examples#
Observe future output with Eio. This complete program creates a private daemon, checks its result and closes its clients. Use OCaml 5.5.2 on Linux with tmux 3.3a through 3.8. Run it from the source checkout after following the installation guide. View source
open Libtmuxmodule Client = Libtmux_unix.Clientmodule Workspace = Libtmux_unix.Workspacemodule Config = Libtmux_workspace.Configmodule Plan = Libtmux_workspace.Planmodule Execution = Libtmux_workspace.Executionlet get = function| Ok value -> value| Error error -> failwith (Format.asprintf "%a" Error.pp error)let watch_output binary blocking (initial : Created.t) _spawn =Eio_main.run @@ fun env ->Eio.Switch.run @@ fun sw ->let module Client = Libtmux_eio.Client inlet module Subscription = Libtmux_eio.Subscription inlet client =get(Client.connect ~sw ~binary~process_mgr:(Eio.Stdenv.process_mgr env)~mono_clock:(Eio.Stdenv.mono_clock env)(Source.endpoint (Libtmux_unix.Client.source blocking)))inFun.protect~finally:(fun () ->Eio.Cancel.protect (fun () -> get (Client.close client)))(fun () ->let pane =Snapshot.find_pane(get (Client.capture client))(Pane.Target.id initial.pane)|> Option.getinlet subscription =get (Client.subscribe ~capacity_bytes:4096 client pane)inFun.protect~finally:(fun () ->Eio.Cancel.protect (fun () -> get (Subscription.close subscription)))(fun () ->let cursor, () =Eio.Fiber.pair(fun () ->matchSubscription.wait_for_bytes ~timeout:0.5 subscription~text:"changed"with| Ok cursor -> cursor| Error (Output.Failure error) ->failwith (Format.asprintf "%a" Error.pp error)| Error (Output.Ended reason) ->failwith (Format.asprintf "%a" Output.reason_pp reason))(fun () ->get (Client.send_text client (Pane.target pane) ~text:"changed");get (Client.send_keys client (Pane.target pane) [ Key.Enter ]))inassert (cursor.offset >= 7L);print_endline "observed: changed"))let with_demo binary use =let directory = Filename.temp_dir "libtmux-ocaml-showcase-" "" inFun.protect~finally:(fun () ->Sys.readdir directory|> Array.iter (fun name -> Sys.remove (Filename.concat directory name));Unix.rmdir directory)(fun () ->let socket = Filename.concat directory "server" in(* Give this private daemon a lifetime even if startup fails. *)let config_file = Filename.concat directory "tmux.conf" inOut_channel.with_open_text config_file (fun output ->output_string output "set-option -s exit-unattached on\n");let wrapper = Filename.concat directory "tmux" inOut_channel.with_open_text wrapper (fun output ->Printf.fprintf output "#!/bin/sh\nexec %s -f %s \"$@\"\n"(Filename.quote binary)(Filename.quote config_file));Unix.chmod wrapper 0o700;let channel = Unix.open_process_args_in binary [| binary; "-V" |] inlet version =Fun.protect~finally:(fun () ->if Unix.close_process_in channel <> Unix.WEXITED 0 thenfailwith "tmux version discovery failed")(fun () -> String.trim (input_line channel))inif not (String.starts_with ~prefix:"tmux " version) thenfailwith "invalid tmux version";let version = String.sub version 5 (String.length version - 5) inlet ready = Filename.concat directory "ready.txt" inOut_channel.with_open_text ready (fun output ->output_string output "showcase ready\n");let spawn =Spawn.make (Exec { program = "/bin/cat"; args = [ "-u"; ready; "-" ] })inlet config =matchConfig.make ~directory ~session:"showcase"[ Config.window ~name:"editor" [ Config.pane ~spawn () ] ]with| Ok value -> value| Error error -> failwith (Format.asprintf "%a" Config.pp_error error)inlet plan =matchPlan.make~endpoint:(Endpoint.socket_path socket)~version ~observed:None configwith| Ok value -> value| Error error -> failwith (Format.asprintf "%a" Plan.pp_error error)inlet operation = get (Workspace.submit_bootstrap ~binary:wrapper plan) inFun.protect~finally:(fun () -> get (Workspace.close operation))(fun () ->let receipt = get (Workspace.await operation) inif receipt.status <> Execution.Succeeded thenfailwith "workspace setup failed";let client = Option.get (Workspace.client operation) inlet initial = List.hd (Iarray.get receipt.steps 0).created inPrintf.printf "socket=%s\n%!" socket;let pane =Snapshot.find_pane(get (Client.capture client))(Pane.Target.id initial.pane)|> Option.getinignore(get(Client.wait_for_text ~timeout:0.5 client pane~text:"showcase ready"));use client initial spawn))let () =let binary = if Array.length Sys.argv = 2 then Sys.argv.(1) else "tmux" inwith_demo binary (watch_output binary)Run the recorded entry point:
Terminal window $ opam exec -- dune exec examples/showcase_watch.exe -- tmuxExpected outcome line, after the temporary socket path:
observed: changed- Parameters
-
-
capacity_bytes? (int) # -
capacity_events? (int) #
tmux command#
The tmux commands behind subscribe.
display-message refresh-client (when opening a new stream lane) tmux C API#
The C declarations in tmux that implement these commands.