Core LibraryunreleasedAPI Reference

Choose documentation 1

latest

Current version

latest
English

Unreleased io.github.libtmux:libtmux-clojure has not been released. Its API may change during development. This site's structure and URLs may change too.

function libtmux-clojure latest

libtmux.data/panes

Returns captured pane occurrences in a snapshot, session, or window.

Source and package
Qualified name
libtmux.data/panes
Module
libtmux.data
Declared in
libtmux.data
Package
io.github.libtmux:libtmux-clojure
Source
libtmux-clojure/src/main/clojure/libtmux/data.clj
Other languages
Perlclass ErlangPowerShellcmdlet Juliastruct Elixirstruct Haskell Common Lispclass PythonRubyLuaTypeScriptRustGoJavaC#C++SwiftKotlinScalaOCamlF#module

Public owner: libtmux.data

Description#

Use libtmux.core/panes! for a new acquisition; active-pane selects locally.

Examples#

Traverse root, session, window and pane observations. Use JDK 25 or newer, the Clojure CLI, Git and tmux on Linux or macOS, with /bin/cat and /bin/sh available. These packages are unpublished. In an empty directory, install this exact source into the consumer's isolated Maven repository:

Terminal window
$ git clone https://github.com/libtmux/libtmux-java libtmux-source && \
git -C libtmux-source checkout --detach 5f88402151ff08fc0390dd438b90963692ec3fe4 && \
(cd libtmux-source && ./gradlew \
:libtmux:publishToMavenLocal \
:libtmux-clojure:publishToMavenLocal \
--console=plain \
"-Dmaven.repo.local=$PWD/../m2")

Save this file as deps.edn. Dependencies resolve from the isolated m2 directory; the core.async dependency is only enabled by its alias. View source

{:paths ["src/main/clojure"]
:mvn/local-repo "m2"
:deps {org.clojure/clojure {:mvn/version "1.12.6"}
io.github.libtmux/libtmux-clojure {:mvn/version "0.1.2-SNAPSHOT"}}
:aliases
{:core-async
{:extra-deps
{io.github.libtmux/libtmux-clojure-core-async {:mvn/version "0.1.2-SNAPSHOT"}}}}}

Save this file as run.sh. The launcher creates and stops a private server, including after program failure, and reports leaked servers as errors. View source

#!/bin/sh
set -eu
if [ "$#" -eq 0 ]; then
printf 'Usage: sh run.sh program [arguments...]\n' >&2
exit 2
fi
binary=$(command -v "${TMUX_BIN:-tmux}")
root=${API_RUN_ROOT:-/tmp/libtmux-java-dev}
# A client that names no socket follows TMUX or LIBTMUX_SOCKET*, and otherwise lands on the default
# socket under TMUX_TMPDIR. The program gets none of them, and a TMUX_TMPDIR of its own below.
unset TMUX TMUX_PANE
for name in $(env | sed -n 's/^\(LIBTMUX_SOCKET[A-Za-z0-9_]*\)=.*/\1/p'); do
unset "$name"
done
mkdir -p "$root"
directory=$(mktemp -d "$root/api.XXXXXX")
tmpdir=$(mktemp -d "$root/tmpdir.XXXXXX")
socket="$directory/tmux.sock"
config="$directory/tmux.conf"
serves() {
"$binary" -S "$1" display-message -p '#{pid}' >/dev/null 2>&1
}
# Stops the server on the socket, then waits for it to stop answering.
stop() {
"$binary" -S "$1" kill-server || return 1
attempts=0
while serves "$1" && [ "$attempts" -lt 60 ]; do
sleep 0.05
attempts=$((attempts + 1))
done
! serves "$1"
}
cleanup() {
status=$?
trap - 0 HUP INT TERM PIPE
# A closed output must not end the cleanup, whose messages are the only thing left to write.
trap '' PIPE
set +e
stuck=
left=
if [ -S "$socket" ] && serves "$socket" && ! stop "$socket"; then
stuck="$stuck tmux.sock"
fi
# Every socket anywhere under either directory, without following links. Only one a server answers
# on is a leak; the runner's own is expected to be there.
old_ifs=$IFS
IFS='
'
set -f
for candidate in $(find "$tmpdir" "$directory" -type s 2>/dev/null); do
[ "$candidate" = "$socket" ] && continue
serves "$candidate" || continue
case "$candidate" in
"$tmpdir"/*) name=${candidate#"$tmpdir"/} ;;
*) name=${candidate#"$directory"/} ;;
esac
left="$left $name"
stop "$candidate" || stuck="$stuck $name"
done
set +f
IFS=$old_ifs
if [ -n "$stuck" ]; then
printf 'tmux still answers on%s after kill-server; kept %s and %s under the runner root\n' \
"$stuck" "${directory##*/}" "${tmpdir##*/}" >&2
exit 1
fi
rm -rf "$directory" "$tmpdir" || exit 1
if [ -n "$left" ]; then
printf 'The program left a tmux server running:%s\n' "$left" >&2
exit 1
fi
exit "$status"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM PIPE
# A default socket path longer than this does not fit in sun_path.
default_socket="$tmpdir/tmux-$(id -u)/default"
if [ "$(printf '%s' "$default_socket" | wc -c)" -gt 100 ]; then
printf 'API_RUN_ROOT is too long for a tmux socket\n' >&2
exit 1
fi
TMUX_TMPDIR=$tmpdir
export TMUX_TMPDIR
printf 'set-option -g default-shell /bin/sh\n' > "$config"
"$binary" -S "$socket" -f "$config" new-session -d -s work-one -n editor /bin/cat
"$binary" -S "$socket" split-window -h -t '=work-one:editor' /bin/cat
"$binary" -S "$socket" new-window -d -t '=work-one' -n logs /bin/cat
"$binary" -S "$socket" new-session -d -s work-two -n editor /bin/cat
"$@" "$binary" "$socket" "$config"
"$binary" -S "$socket" has-session -t '=work-one'
"$binary" -S "$socket" has-session -t '=work-two'

Save the complete program as src/main/clojure/libtmux/examples/api/list_panes.clj, creating its parent directories. Closing its client leaves the launcher's server running. View source

(ns libtmux.examples.api.list-panes
"Traverse session, window and pane observations without another acquisition."
(:require [libtmux.core :as tm]
[libtmux.data :as data]))
(defn -main [& args]
(when-not (= 3 (count args))
(throw (IllegalArgumentException. "expected: tmux-binary socket-path config-file")))
(let [[binary socket config] args]
(with-open [server (tm/open! {:binary binary :socket-path socket
:config-file config})]
(let [snapshot (tm/snapshot! server)
session (data/exactly-one
(filter #(= "work-one" (:session/name %))
(:tmux/sessions snapshot)))
window (data/exactly-one
(filter #(= "editor" (:window/name %)) (data/windows session)))]
(println (str "panes=" (count (data/panes snapshot))))
(println (str "window-panes=" (count (data/panes window))))))))

Run it with the private fixture. Set TMUX_BIN to select another tmux binary:

Terminal window
$ sh run.sh clojure \
-J-Dclojure.main.report=stderr \
-M \
-m libtmux.examples.api.list-panes

Expected output:

panes=4
window-panes=2

Use a preserved Java Pane ref to read a command exit status and output. Use JDK 25 or newer, the Clojure CLI, Git and tmux on Linux or macOS, with /bin/cat and /bin/sh available. These packages are unpublished. In an empty directory, install this exact source into the consumer's isolated Maven repository:

Terminal window
$ git clone https://github.com/libtmux/libtmux-java libtmux-source && \
git -C libtmux-source checkout --detach 5f88402151ff08fc0390dd438b90963692ec3fe4 && \
(cd libtmux-source && ./gradlew \
:libtmux:publishToMavenLocal \
:libtmux-clojure:publishToMavenLocal \
--console=plain \
"-Dmaven.repo.local=$PWD/../m2")

Save this file as deps.edn. Dependencies resolve from the isolated m2 directory; the core.async dependency is only enabled by its alias. View source

{:paths ["src/main/clojure"]
:mvn/local-repo "m2"
:deps {org.clojure/clojure {:mvn/version "1.12.6"}
io.github.libtmux/libtmux-clojure {:mvn/version "0.1.2-SNAPSHOT"}}
:aliases
{:core-async
{:extra-deps
{io.github.libtmux/libtmux-clojure-core-async {:mvn/version "0.1.2-SNAPSHOT"}}}}}

Save this file as run.sh. The launcher creates and stops a private server, including after program failure, and reports leaked servers as errors. View source

#!/bin/sh
set -eu
if [ "$#" -eq 0 ]; then
printf 'Usage: sh run.sh program [arguments...]\n' >&2
exit 2
fi
binary=$(command -v "${TMUX_BIN:-tmux}")
root=${API_RUN_ROOT:-/tmp/libtmux-java-dev}
# A client that names no socket follows TMUX or LIBTMUX_SOCKET*, and otherwise lands on the default
# socket under TMUX_TMPDIR. The program gets none of them, and a TMUX_TMPDIR of its own below.
unset TMUX TMUX_PANE
for name in $(env | sed -n 's/^\(LIBTMUX_SOCKET[A-Za-z0-9_]*\)=.*/\1/p'); do
unset "$name"
done
mkdir -p "$root"
directory=$(mktemp -d "$root/api.XXXXXX")
tmpdir=$(mktemp -d "$root/tmpdir.XXXXXX")
socket="$directory/tmux.sock"
config="$directory/tmux.conf"
serves() {
"$binary" -S "$1" display-message -p '#{pid}' >/dev/null 2>&1
}
# Stops the server on the socket, then waits for it to stop answering.
stop() {
"$binary" -S "$1" kill-server || return 1
attempts=0
while serves "$1" && [ "$attempts" -lt 60 ]; do
sleep 0.05
attempts=$((attempts + 1))
done
! serves "$1"
}
cleanup() {
status=$?
trap - 0 HUP INT TERM PIPE
# A closed output must not end the cleanup, whose messages are the only thing left to write.
trap '' PIPE
set +e
stuck=
left=
if [ -S "$socket" ] && serves "$socket" && ! stop "$socket"; then
stuck="$stuck tmux.sock"
fi
# Every socket anywhere under either directory, without following links. Only one a server answers
# on is a leak; the runner's own is expected to be there.
old_ifs=$IFS
IFS='
'
set -f
for candidate in $(find "$tmpdir" "$directory" -type s 2>/dev/null); do
[ "$candidate" = "$socket" ] && continue
serves "$candidate" || continue
case "$candidate" in
"$tmpdir"/*) name=${candidate#"$tmpdir"/} ;;
*) name=${candidate#"$directory"/} ;;
esac
left="$left $name"
stop "$candidate" || stuck="$stuck $name"
done
set +f
IFS=$old_ifs
if [ -n "$stuck" ]; then
printf 'tmux still answers on%s after kill-server; kept %s and %s under the runner root\n' \
"$stuck" "${directory##*/}" "${tmpdir##*/}" >&2
exit 1
fi
rm -rf "$directory" "$tmpdir" || exit 1
if [ -n "$left" ]; then
printf 'The program left a tmux server running:%s\n' "$left" >&2
exit 1
fi
exit "$status"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM PIPE
# A default socket path longer than this does not fit in sun_path.
default_socket="$tmpdir/tmux-$(id -u)/default"
if [ "$(printf '%s' "$default_socket" | wc -c)" -gt 100 ]; then
printf 'API_RUN_ROOT is too long for a tmux socket\n' >&2
exit 1
fi
TMUX_TMPDIR=$tmpdir
export TMUX_TMPDIR
printf 'set-option -g default-shell /bin/sh\n' > "$config"
"$binary" -S "$socket" -f "$config" new-session -d -s work-one -n editor /bin/cat
"$binary" -S "$socket" split-window -h -t '=work-one:editor' /bin/cat
"$binary" -S "$socket" new-window -d -t '=work-one' -n logs /bin/cat
"$binary" -S "$socket" new-session -d -s work-two -n editor /bin/cat
"$@" "$binary" "$socket" "$config"
"$binary" -S "$socket" has-session -t '=work-one'
"$binary" -S "$socket" has-session -t '=work-two'

Save the complete program as src/main/clojure/libtmux/examples/api/run_a_command.clj, creating its parent directories. Closing its client leaves the launcher's server running. View source

(ns libtmux.examples.api.run-a-command
"Use the preserved Java Pane ref to observe a command's real exit status."
(:require [clojure.string :as str]
[libtmux.core :as tm]
[libtmux.data :as data])
(:import [io.github.libtmux Pane PaneRun PaneRun$Outcome]
[java.time Duration]))
(defn -main [& args]
(when-not (= 3 (count args))
(throw (IllegalArgumentException. "expected: tmux-binary socket-path config-file")))
(let [[binary socket config] args]
(with-open [server (tm/open! {:binary binary :socket-path socket :config-file config})]
(let [session (tm/new-session! server {:name "command-example" :command ["/bin/sh"]})
^Pane pane (:tmux/ref (data/exactly-one (data/panes session)))
^PaneRun result (.run pane "printf 'built\\n'; exit 3" (Duration/ofMillis 900))]
(assert (= PaneRun$Outcome/FINISHED (.outcome result)))
(assert (= 3 (.orElseThrow (.exitStatus result))))
(assert (= ["built"] (vec (.output result))))
(println (str "exit=" (.orElseThrow (.exitStatus result))
" output=" (str/join " / " (.output result))))))))

Run it with the private fixture. Set TMUX_BIN to select another tmux binary:

Terminal window
$ sh run.sh clojure \
-J-Dclojure.main.report=stderr \
-M \
-m libtmux.examples.api.run-a-command

Expected output:

exit=3 output=built
Parameters

Guides#

Pages that discuss panes.

In other ports#

A tmux pane

Equivalents of A tmux pane in other languages
Language Equivalent
Python libtmux.Pane
Ruby LibTmux::Pane
Lua libtmux.Pane
PowerShell LibTmux\Get-TmuxPane This cmdlet reads shared .NET LibTmux.Pane objects. Its -Server, -Session, and -Window parameter sets select the scope.
Julia LibTmux.PaneSnapshot PaneSnapshot holds captured pane data. Actions use its PaneRef; PaneOccurrence adds a window placement in a session.
Erlang #tmux_model:pane{}
Elixir LibTmux.Pane Pane is an immutable physical pane observation. It does not send keys or capture text.
Haskell No public Haskell equivalent is implemented; the current modules expose scalar values and version parsing.
Common Lisp libtmux:pane pane is an immutable captured physical pane.
TypeScript pane.Pane
Rust pane.Pane
Go tmux.Pane
Java io.github.libtmux.Pane
Kotlin io.github.libtmux.kotlin.Pane
Scala io.github.libtmux.scaladsl.Pane
C# LibTmux.Pane
F# LibTmux.FSharp.Pane This F# module reads captured fields and starts explicit operations on the shared .NET LibTmux.Pane type.
C++ libtmux::Pane
Swift Pane
OCaml Libtmux.Pane.t
Perl LibTmux::Pane A physical pane retains its captured graph, without retaining transport.

List a window's panes

Equivalents of List a window's panes in other languages
Language Equivalent
Python libtmux.Window.panes
Ruby LibTmux::Window#list_panes
PowerShell LibTmux\Get-TmuxPane Use the -Window parameter set to acquire panes in one window.
Julia LibTmux.panes panes with a captured WindowSnapshot reads panes in that window; missing coverage is an error.
Erlang tmux_snapshot:related/3 Pass panes, a captured physical window and its snapshot for a local relationship read.
Haskell No public Haskell equivalent is implemented; the current modules expose scalar values and version parsing.
Common Lisp libtmux:panes panes traverses a captured window without contacting tmux.
TypeScript window.Window.panes
Rust window.Window.panes
Go tmux.Window.Panes
Java io.github.libtmux.Window.panes
Kotlin io.github.libtmux.kotlin.Window.panes
Scala io.github.libtmux.scaladsl.Window.panes
C# LibTmux.Window.Panes
F# LibTmux.FSharp.Window.panes Builds a deferred pane query from one LibTmux.Window and its server. Query.list acquires panes scoped to that window ID.
C++ libtmux::Window::panes
Swift Snapshot.panes(of:)
OCaml Libtmux.Window.panes Reads captured panes in one global window without I/O.
Perl LibTmux::Window::panes Reads this physical window’s captured panes without I/O.

No equivalent is recorded in Lua or Elixir.

Esc

Type to search.

Reference previewOpen reference