Core LibraryunreleasedHome

Choose documentation 1

latest

Current version

latest
English

Unreleased libtmux_erlang has not been released. Its API may change during development. This site's structure and URLs may change too.

Edit this page on GitHub

tmux client library for Erlang

Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, capture pane contents.

Install

{deps, [
{libtmux_erlang, {git_subdir,
"https://github.com/libtmux/libtmux-erlang.git",
{ref, "master"}, "apps/libtmux_erlang"}}
]}.

At a glance

Server → Session → Window → Pane. Each level of the tmux hierarchy has its own entry in the Erlang API, with the tmux object it wraps.

TypeWraps
tmux_server:t/0 A tmux server
#tmux_model:session{} A session, ID $n
#tmux_model:window{} A physical tmux window; session membership uses window links, ID @n
#tmux_model:pane{} A pane in a window, ID %n

What it does

-module(readme_demo).
-moduledoc "Create a workspace, query its graph and preserve captured values.".
-export([run/1]).
-import_record(tmux_model, [pane]).
-spec run(binary()) -> map().
run(Executable) ->
{ok, Server, Ownership} =
tmux_server:start_owned(#{executable => Executable}),
try
{ok, Session} = tmux_session:create(Server, #{name => <<"workspace">>,
window_name => <<"editor">>, width => 120, height => 30,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Worker} = tmux_window:create(Session,
#{name => <<"workers">>,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Right} = tmux_pane:split(Worker, #{direction => horizontal,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, _} = tmux_window:select_layout(Worker, even_horizontal),
{ok, _} = tmux_pane:resize(Right, #{width => 40}),
{ok, Snapshot} = tmux_server:snapshot(Server),
Windows = tmux_select:windows(Snapshot),
Workers = #{name => <<"workers">>, panes => #{count => 2,
every => #{current_command => <<"cat">>}}},
{ok, Captured} = tmux_select:one(Workers, Windows),
{ok, Children} = tmux_snapshot:related(panes, Captured, Snapshot),
Ids = [Id || #pane{id = Id} <:- Children],
2 = length(Ids),
Criteria = #{width => #{gte => 20},
window => #{is => #{name => <<"workers">>}}},
Query = tmux_query:where(Criteria, tmux_query:panes(Server)),
{ok, Fetched} = tmux_query:fetch(Query),
2 = tmux_select:size(Fetched),
{ok, _} = tmux_window:rename(Worker, <<"finished">>),
<<"workers">> = tmux_model:get(name, Captured),
{ok, Fresh} = tmux_query:fetch(tmux_query:where(
#{name => <<"finished">>}, tmux_query:windows(Server))),
{ok, Renamed} = tmux_select:one(Fresh),
<<"finished">> = tmux_model:get(name, Renamed),
1 = length(tmux_snapshot:sessions(Snapshot)),
2 = length(tmux_snapshot:windows(Snapshot)),
3 = length(tmux_snapshot:panes(Snapshot)),
#{sessions => 1, windows => 2, panes => 3, matched_panes => 2,
captured_name => <<"workers">>, immutable => true}
after
ok = tmux_server:stop_owned(Ownership)
end.
-module(readme_demo).
-moduledoc "Create a workspace, query its graph and preserve captured values.".
-export([run/1]).
-import_record(tmux_model, [pane]).
-spec run(binary()) -> map().
run(Executable) ->
{ok, Server, Ownership} =
tmux_server:start_owned(#{executable => Executable}),
try
{ok, Session} = tmux_session:create(Server, #{name => <<"workspace">>,
window_name => <<"editor">>, width => 120, height => 30,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Worker} = tmux_window:create(Session,
#{name => <<"workers">>,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Right} = tmux_pane:split(Worker, #{direction => horizontal,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, _} = tmux_window:select_layout(Worker, even_horizontal),
{ok, _} = tmux_pane:resize(Right, #{width => 40}),
{ok, Snapshot} = tmux_server:snapshot(Server),
Windows = tmux_select:windows(Snapshot),
Workers = #{name => <<"workers">>, panes => #{count => 2,
every => #{current_command => <<"cat">>}}},
{ok, Captured} = tmux_select:one(Workers, Windows),
{ok, Children} = tmux_snapshot:related(panes, Captured, Snapshot),
Ids = [Id || #pane{id = Id} <:- Children],
2 = length(Ids),
Criteria = #{width => #{gte => 20},
window => #{is => #{name => <<"workers">>}}},
Query = tmux_query:where(Criteria, tmux_query:panes(Server)),
{ok, Fetched} = tmux_query:fetch(Query),
2 = tmux_select:size(Fetched),
{ok, _} = tmux_window:rename(Worker, <<"finished">>),
<<"workers">> = tmux_model:get(name, Captured),
{ok, Fresh} = tmux_query:fetch(tmux_query:where(
#{name => <<"finished">>}, tmux_query:windows(Server))),
{ok, Renamed} = tmux_select:one(Fresh),
<<"finished">> = tmux_model:get(name, Renamed),
1 = length(tmux_snapshot:sessions(Snapshot)),
2 = length(tmux_snapshot:windows(Snapshot)),
3 = length(tmux_snapshot:panes(Snapshot)),
#{sessions => 1, windows => 2, panes => 3, matched_panes => 2,
captured_name => <<"workers">>, immutable => true}
after
ok = tmux_server:stop_owned(Ownership)
end.
-module(readme_demo).
-moduledoc "Create a workspace, query its graph and preserve captured values.".
-export([run/1]).
-import_record(tmux_model, [pane]).
-spec run(binary()) -> map().
run(Executable) ->
{ok, Server, Ownership} =
tmux_server:start_owned(#{executable => Executable}),
try
{ok, Session} = tmux_session:create(Server, #{name => <<"workspace">>,
window_name => <<"editor">>, width => 120, height => 30,
launch => #{argv => [<<"/bin/cat">>]}}),
try
{ok, Worker} = tmux_window:create(Session,
#{name => <<"workers">>,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Right} = tmux_pane:split(Worker, #{direction => horizontal,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, _} = tmux_window:select_layout(Worker, even_horizontal),
{ok, _} = tmux_pane:resize(Right, #{width => 40}),
{ok, Snapshot} = tmux_server:snapshot(Server),
Windows = tmux_select:windows(Snapshot),
Workers = #{name => <<"workers">>, panes => #{count => 2,
every => #{current_command => <<"cat">>}}},
{ok, Captured} = tmux_select:one(Workers, Windows),
{ok, Children} = tmux_snapshot:related(panes, Captured, Snapshot),
Ids = [Id || #pane{id = Id} <:- Children],
2 = length(Ids),
Criteria = #{width => #{gte => 20},
window => #{is => #{name => <<"workers">>}}},
Query = tmux_query:where(Criteria, tmux_query:panes(Server)),
{ok, Fetched} = tmux_query:fetch(Query),
2 = tmux_select:size(Fetched),
{ok, _} = tmux_window:rename(Worker, <<"finished">>),
<<"workers">> = tmux_model:get(name, Captured),
{ok, Fresh} = tmux_query:fetch(tmux_query:where(
#{name => <<"finished">>}, tmux_query:windows(Server))),
{ok, Renamed} = tmux_select:one(Fresh),
<<"finished">> = tmux_model:get(name, Renamed),
1 = length(tmux_snapshot:sessions(Snapshot)),
2 = length(tmux_snapshot:windows(Snapshot)),
3 = length(tmux_snapshot:panes(Snapshot)),
#{sessions => 1, windows => 2, panes => 3, matched_panes => 2,
captured_name => <<"workers">>, immutable => true}
after
{ok, _} = tmux_session:kill(Session)
end
after
ok = tmux_server:stop_owned(Ownership)
end.
-module(readme_demo).
-moduledoc "Create a workspace, query its graph and preserve captured values.".
-export([run/1]).
-import_record(tmux_model, [pane]).
-spec run(binary()) -> map().
run(Executable) ->
{ok, Server, Ownership} =
tmux_server:start_owned(#{executable => Executable}),
try
{ok, Session} = tmux_session:create(Server, #{name => <<"workspace">>,
window_name => <<"editor">>, width => 120, height => 30,
launch => #{argv => [<<"/bin/cat">>]}}),
try
{ok, Worker} = tmux_window:create(Session,
#{name => <<"workers">>,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, Right} = tmux_pane:split(Worker, #{direction => horizontal,
launch => #{argv => [<<"/bin/cat">>]}}),
{ok, _} = tmux_window:select_layout(Worker, even_horizontal),
{ok, _} = tmux_pane:resize(Right, #{width => 40}),
{ok, Snapshot} = tmux_server:snapshot(Server),
Windows = tmux_select:windows(Snapshot),
Workers = #{name => <<"workers">>, panes => #{count => 2,
every => #{current_command => <<"cat">>}}},
{ok, Captured} = tmux_select:one(Workers, Windows),
{ok, Children} = tmux_snapshot:related(panes, Captured, Snapshot),
Ids = [Id || #pane{id = Id} <:- Children],
2 = length(Ids),
Criteria = #{width => #{gte => 20},
window => #{is => #{name => <<"workers">>}}},
Query = tmux_query:where(Criteria, tmux_query:panes(Server)),
{ok, Fetched} = tmux_query:fetch(Query),
2 = tmux_select:size(Fetched),
{ok, _} = tmux_window:rename(Worker, <<"finished">>),
<<"workers">> = tmux_model:get(name, Captured),
{ok, Fresh} = tmux_query:fetch(tmux_query:where(
#{name => <<"finished">>}, tmux_query:windows(Server))),
{ok, Renamed} = tmux_select:one(Fresh),
<<"finished">> = tmux_model:get(name, Renamed),
1 = length(tmux_snapshot:sessions(Snapshot)),
2 = length(tmux_snapshot:windows(Snapshot)),
3 = length(tmux_snapshot:panes(Snapshot)),
#{sessions => 1, windows => 2, panes => 3, matched_panes => 2,
captured_name => <<"workers">>, immutable => true}
after
{ok, _} = tmux_session:kill(Session)
end
after
ok = tmux_server:stop_owned(Ownership)
end.
Example details
Run this example

Linux, tmux 3.3a–3.8, Erlang/OTP 29.1.2, Rebar3 3.28.0, Git, make and a C11 compiler. Save the displayed files in an empty project directory.

Save the program above as src/readme_demo.erl in a new directory, along with the files below.

Every version retires its owned server in try/after. Cleanup also removes the created session explicitly. The program stops its private tmux server and removes any temporary files it created when it finishes. Unmatched tagged results raise with a stack trace. The program propagates failures through try/after cleanup.

rebar.config
{minimum_otp_vsn, "29.1.2"}.
{erl_opts, [debug_info, warnings_as_errors]}.
{deps, [
{libtmux_erlang, {git_subdir,
"https://github.com/libtmux/libtmux-erlang.git",
{ref, "9a1ca749f7bf6f082c910c99f961bb586781ab0b"}, "apps/libtmux_erlang"}}
]}.
src/tmux_example.app.src
{application, tmux_example, [
{vsn, "0.1.0"},
{applications, [kernel, stdlib, libtmux_erlang]},
{modules, []}
]}.

Setup and run

rebar3 compile
env \
-u TMUX \
-u TMUX_PANE \
erl \
-noshell \
-pa _build/default/lib/tmux_example/ebin \
-pa _build/default/lib/libtmux_erlang/apps/libtmux_erlang/ebin \
-eval '
{ok, _} = application:ensure_all_started(libtmux_erlang),
Tmux = unicode:characters_to_binary(os:find_executable("tmux")),
Stats = readme_demo:run(Tmux),
io:format("~B session, ~B windows, ~B panes; ~B matches~n", [
maps:get(sessions, Stats), maps:get(windows, Stats),
maps:get(panes, Stats), maps:get(matched_panes, Stats)]),
halt().'

Expected output

1 session, 2 windows, 3 panes; 2 matches

Typed API

What you get over the tmux CLI

Testing

Run tests against an isolated tmux server: tmux_server:start_owned/1.

Esc

Type to search.

Reference previewOpen reference