Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions libtmux-kotlin/src/main/kotlin/io/github/libtmux/kotlin/Pane.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,93 @@ import io.github.libtmux.Pane as JavaPane
* Holds the Java handle privately, so a member here always wins over a same-named catalog-generated
* extension in `PaneOperations.kt`. [Companion] hosts the generated query field namespace
* (`Pane.command`, `Pane.active`, ...).
*
* A property or a plain function here reads the capture this handle came from and issues no command.
* Every `suspend` function asks tmux now, dispatched through the [Server]'s policy, except the waits,
* which run on their own dispatcher.
*
* # What is on here
*
* The members fall into a few groups:
*
* **Reading the capture.** [id], [index], [active], [currentCommand], [floating], [size], [position],
* [edges], [title], [currentPath] and [pid] read what this capture stored about the pane, and
* [window] and [server] are what it sits in. The id is stable and the index is state, since panes
* renumber as neighbours come and go. [floating] is null when the running tmux cannot say, which
* before 3.7 is always, and [pid] is null when tmux reported no process. [currentPath] throws when
* this JVM cannot represent the directory's name.
*
* [id], [index], [active], [currentCommand], [floating], [size], [position], [edges], [title],
* [currentPath], [pid], [window], [server] and [asJava]
*
* **Sending input.** [send][Pane.send] types keys without pressing Enter and
* [sendLine][Pane.sendLine] presses it, which is how a command gets run. [sendKeys][Pane.sendKeys]
* resolves each entry through tmux's key table and types an unknown name as text;
* [sendLiteral][Pane.sendLiteral] types every entry as the characters it spells, so `C-c` is three
* characters. [paste][Pane.paste] delivers text as one block through a private buffer that is
* removed afterwards, and it throws for text containing NUL and before tmux 3.4.
* [noteTyped][Pane.noteTyped] tells a later wait about text that reached the pane without passing
* through this handle.
*
* [send][Pane.send], [sendLine][Pane.sendLine], [sendKeys][Pane.sendKeys],
* [sendLiteral][Pane.sendLiteral], [paste][Pane.paste], [pasteBuffer][Pane.pasteBuffer] and
* [noteTyped][Pane.noteTyped]
*
* **Reading output.** [capture][Pane.capture] returns the visible content, one element per line, read
* from tmux now rather than from the capture. Give it a `CaptureSpec` to read part of the history; it
* throws when the spec asks for something this server does not have. [pipeTo][Pane.pipeTo] sends
* everything the pane prints to a shell command until [stopPiping][Pane.stopPiping], and
* [clearHistory][Pane.clearHistory] discards the scrollback.
*
* [capture][Pane.capture], [pipeTo][Pane.pipeTo], [stopPiping][Pane.stopPiping] and
* [clearHistory][Pane.clearHistory]
*
* **Running and waiting.** [run] runs a shell command to its end and answers with its exit status and
* output, and throws when the pane is not running a POSIX shell. Reach for it first when the command
* is yours. When it is not, [awaitText] and [await] poll the screen or the pane's state on a timer
* and answer with why they ended; a pane killed mid-wait ends [awaitText] as `TextOutcome.PANE_GONE`
* rather than an exception. Cancelling the coroutine interrupts a wait and is not a timeout.
* [dead][Pane.dead] reads fresh whether the pane's process has exited, and throws when the pane is
* gone from a server that still answers.
*
* [run], [awaitText], [await] and [dead][Pane.dead]
*
* **Splitting and arranging.** [split][Pane.split] divides this pane in half, or as a `SplitSpec`
* describes, and returns the pane that appeared. [breakOut][Pane.breakOut] moves the pane into a
* window of its own, [joinTo][Pane.joinTo] into another window, and [swapWith][Pane.swapWith] swaps
* it with another pane. [resize][Pane.resize] grows it by cells in one direction,
* [resizeTo][Pane.resizeTo] sets exact dimensions, and [select][Pane.select] makes it the active
* pane. An unnamed [breakOut][Pane.breakOut] throws on exact tmux 3.7, which a named break or 3.7a
* avoids.
*
* [split][Pane.split], [breakOut][Pane.breakOut], [joinTo][Pane.joinTo], [swapWith][Pane.swapWith],
* [resize][Pane.resize], [resizeTo][Pane.resizeTo] and [select][Pane.select]
*
* **Modes.** [copyMode][Pane.copyMode] puts the pane into copy mode, [mode][Pane.mode] reads live
* which mode it is in, null when it is showing its program, and [exitMode][Pane.exitMode] leaves
* whichever mode it is in.
*
* [copyMode][Pane.copyMode], [mode][Pane.mode] and [exitMode][Pane.exitMode]
*
* **Changing the pane.** [retitle][Pane.retitle] returns a replacement capture, because this handle
* keeps its original state. [respawn][Pane.respawn] kills what runs here and starts the pane's
* default command or one you give, [respawnIn][Pane.respawnIn] does so in a directory, and
* [kill][Pane.kill] closes the pane.
*
* [retitle][Pane.retitle], [respawn][Pane.respawn], [respawnIn][Pane.respawnIn] and
* [kill][Pane.kill]
*
* **Options and hooks.** [options] and [hooks] reach what is set on this pane alone.
*
* [options] and [hooks]
*
* **Formats and refreshing.** [expand][Pane.expand] expands a tmux format, and
* [variables][Pane.variables] reads several named variables, in this pane's context.
* [refresh][Pane.refresh] takes a new capture to see the pane as it is now. It leaves this handle
* unchanged and returns the new one, and throws if the pane is gone from a server that still
* answers.
*
* [expand][Pane.expand], [variables][Pane.variables] and [refresh][Pane.refresh]
*/
public class Pane internal constructor(internal val java: JavaPane, public val server: Server) {

Expand Down
48 changes: 48 additions & 0 deletions libtmux-kotlin/src/main/kotlin/io/github/libtmux/kotlin/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,54 @@ import io.github.libtmux.Session as JavaSession
* Holds the Java handle privately, so a member here always wins over a same-named catalog-generated
* extension in `SessionOperations.kt`. [Companion] hosts the generated query field namespace
* (`Session.name`, `Session.attached`, ...).
*
* A property or a plain function here reads the capture this handle came from and issues no command.
* Every `suspend` extension asks tmux now, dispatched through the [Server]'s policy.
*
* # What is on here
*
* The members fall into a few groups:
*
* **Reading the capture.** [id], [name] and [attached] read what this capture stored about the
* session, and [server] is the [Server] it lives on. The id is stable, the name is state a user may
* change at any time, and a rename or an attach after the capture does not show in it.
*
* [id], [name], [attached], [server] and [asJava]
*
* **Windows and panes.** [windows] lists the session's windows in tmux's order, and [activeWindow]
* and [activePane] are the window tmux had active and the active pane of that window, each null when
* the capture holds none. All three are pure reads and issue no command. [selectWindow][Session.selectWindow]
* makes a window the active one, [nextWindow][Session.nextWindow] and
* [previousWindow][Session.previousWindow] step to a neighbour with wrap-around, and
* [lastWindow][Session.lastWindow] goes back to the one that was active before.
*
* [windows], [activeWindow], [activePane], [selectWindow][Session.selectWindow],
* [nextWindow][Session.nextWindow], [previousWindow][Session.previousWindow] and
* [lastWindow][Session.lastWindow]
*
* **Changing the session.** [newWindow][Session.newWindow] creates a window from a name or a
* `WindowSpec` and returns the window tmux made. [rename][Session.rename] returns a replacement
* capture, because this handle keeps its original state. [setHistoryLimit][Session.setHistoryLimit]
* sets the scrollback retained by panes created in this session afterwards.
* [detachClients][Session.detachClients] leaves the session running, and [kill][Session.kill] takes
* every window with it.
*
* [newWindow][Session.newWindow], [rename][Session.rename], [setHistoryLimit][Session.setHistoryLimit],
* [detachClients][Session.detachClients] and [kill][Session.kill]
*
* **Options, environment, and hooks.** These reach what is set on this session alone: its own
* options, its own environment, which a process started in it is given on top of the server's, and
* its own hooks. The [Server] holds the global ones, which a session inherits. Each returns a
* wrapper whose own operations are `suspend`.
*
* [options], [environment] and [hooks]
*
* **Formats and refreshing.** [expand][Session.expand] expands a tmux format in this session's
* context, and [refresh][Session.refresh] takes a new capture to see the session as it is now. It
* leaves this handle unchanged and returns the new one, and throws if the session is gone from a
* server that still answers.
*
* [expand][Session.expand] and [refresh][Session.refresh]
*/
public class Session internal constructor(internal val java: JavaSession, public val server: Server) {

Expand Down
66 changes: 66 additions & 0 deletions libtmux-kotlin/src/main/kotlin/io/github/libtmux/kotlin/Window.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,72 @@ import io.github.libtmux.Window as JavaWindow
*
* Holds the Java handle privately, so a member here always wins over a same-named catalog-generated
* extension in `WindowOperations.kt`. [Companion] hosts the generated query field namespace.
*
* A property or a plain function here reads the capture this handle came from and issues no command.
* Every `suspend` extension asks tmux now, dispatched through the [Server]'s policy.
*
* # What is on here
*
* The members fall into a few groups:
*
* **Reading the capture.** [id], [index], [context], [name], [active], [linked], [size] and [layout]
* read what this capture stored about the window, and [server] and [session] are the [Server] and
* [Session] it sits in. The id names the underlying window and the index names this link, so a window
* linked into two sessions has one id and two handles. A rename or a resize after the capture does
* not show in it.
*
* [id], [index], [context], [name], [active], [linked], [size], [layout], [server], [session] and
* [asJava]
*
* **Panes.** [panes] lists this link's panes in tmux's order and [activePane] is the one tmux had
* active, null when the capture holds none; both are pure reads. [split][Window.split] divides the
* active pane in half, or as a `SplitSpec` describes, and returns the pane that appeared. It throws
* when the spec asks for something this server does not have.
*
* [panes], [activePane] and [split][Window.split]
*
* **Layout and size.** [selectLayout][Window.selectLayout] rearranges the panes into one of tmux's
* built-in layouts, [nextLayout][Window.nextLayout] and [previousLayout][Window.previousLayout] step
* to a neighbour, and [rotate][Window.rotate] rotates the panes. Read the arrangement from [layout]
* and hand it back to [applyLayout][Window.applyLayout], which checks a string before tmux sees it.
* [resizeTo][Window.resizeTo] takes terminal cells. [synchronizePanes][Window.synchronizePanes]
* copies input typed into one pane into every pane of the window until
* [stopSynchronizingPanes][Window.stopSynchronizingPanes].
*
* [selectLayout][Window.selectLayout], [nextLayout][Window.nextLayout],
* [previousLayout][Window.previousLayout], [applyLayout][Window.applyLayout],
* [rotate][Window.rotate], [resizeTo][Window.resizeTo],
* [synchronizePanes][Window.synchronizePanes] and
* [stopSynchronizingPanes][Window.stopSynchronizingPanes]
*
* **Moving and linking.** [select][Window.select] makes the window the active one in its session.
* [linkTo][Window.linkTo] links it into another session so one window sits in both,
* [moveTo][Window.moveTo] moves it to another session or to an exact index there, and
* [unlink][Window.unlink] removes one link and throws when it is the window's only one, which tmux
* refuses to remove.
*
* [select][Window.select], [linkTo][Window.linkTo], [moveTo][Window.moveTo] and
* [unlink][Window.unlink]
*
* **Changing the window.** [rename][Window.rename] returns a replacement capture, because this handle
* keeps its original state. [respawn][Window.respawn] kills what is running in the window and starts
* it again, [displayPopup][Window.displayPopup] shows a popup over it and needs an attached client,
* and [kill][Window.kill] closes it.
*
* [rename][Window.rename], [respawn][Window.respawn], [displayPopup][Window.displayPopup] and
* [kill][Window.kill]
*
* **Options and hooks.** [options] and [hooks] reach what is set on this window alone, and every link
* to the window shares them.
*
* [options] and [hooks]
*
* **Formats and refreshing.** [expand][Window.expand] expands a tmux format in this window's
* context, and [refresh][Window.refresh] takes a new capture to see the window as it is now. It
* leaves this handle unchanged and returns the new one, and throws if the window is no longer linked
* here, from a server that still answers.
*
* [expand][Window.expand] and [refresh][Window.refresh]
*/
public class Window internal constructor(internal val java: JavaWindow, public val server: Server) {

Expand Down
98 changes: 98 additions & 0 deletions libtmux-scala/src/main/scala/io/github/libtmux/scaladsl/Pane.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,104 @@ import scala.jdk.DurationConverters._
* identifies the physical pane; every operation beyond that is an extension,
* generated from the operation catalog or handwritten where the catalog marks
* it `WAIT`, `STREAM` or `LIFECYCLE`.
*
* A pure read of the capture issues no command; every other operation asks tmux
* now, blocking the calling thread.
*
* # What is on here
*
* The operations fall into a few groups:
*
* **Reading the capture.** [[Pane.id]], [[Pane.index]], [[Pane.active]],
* [[Pane.currentCommand]], [[Pane.floating]], [[Pane.size]], [[Pane.position]],
* [[Pane.edges]], [[Pane.title]], [[Pane.currentPath]],
* [[Pane.currentPathText]] and [[Pane.pid]] read what this capture stored about
* the pane, and [[Pane.window]] and [[Pane.server]] are what it sits in. The id
* is stable and the index is state, since panes renumber as neighbours come and
* go. [[Pane.floating]] is empty when the running tmux cannot say, which before
* 3.7 is always, and [[Pane.pid]] is empty when tmux reported no process.
* [[Pane.currentPath]] throws when this JVM cannot represent the directory's
* name; [[Pane.currentPathText]] is what tmux reported and never throws.
*
* [[Pane.info]], [[Pane.id]], [[Pane.index]], [[Pane.active]],
* [[Pane.currentCommand]], [[Pane.floating]], [[Pane.size]], [[Pane.position]],
* [[Pane.edges]], [[Pane.title]], [[Pane.currentPath]],
* [[Pane.currentPathText]], [[Pane.pid]], [[Pane.window]], [[Pane.server]] and
* [[Pane.asJava]]
*
* **Sending input.** [[Pane.send]] types keys without pressing Enter and
* [[Pane.sendLine]] presses it, which is how a command gets run.
* [[Pane.sendKeys]] resolves each entry through tmux's key table and types an
* unknown name as text; [[Pane.sendLiteral]] types every entry as the
* characters it spells, so `C-c` is three characters. [[Pane.paste]] delivers
* text as one block through a private buffer that is removed afterwards, and it
* throws for text containing NUL and before tmux 3.4. [[Pane.noteTyped]] tells
* a later wait about text that reached the pane without passing through this
* handle.
*
* [[Pane.send]], [[Pane.sendLine]], [[Pane.sendKeys]], [[Pane.sendLiteral]],
* [[Pane.paste]], [[Pane.pasteBuffer]] and [[Pane.noteTyped]]
*
* **Reading output.** [[Pane.capture]] returns the visible content as a
* `Vector` with one element per line, read from tmux now rather than from the
* capture. Give it a callback on a builder or a `CaptureSpec` to read part of
* the history; it throws when the spec asks for something this server does not
* have. [[Pane.pipeTo]] sends everything the pane prints to a shell command
* until [[Pane.stopPiping]], and [[Pane.clearHistory]] discards the scrollback.
*
* [[Pane.capture]], [[Pane.pipeTo]], [[Pane.stopPiping]] and
* [[Pane.clearHistory]]
*
* **Running and waiting.** [[Pane.run]] runs a shell command to its end and
* answers with its exit status and output, and throws when the pane is not
* running a POSIX shell. Reach for it first when the command is yours. When it
* is not, [[Pane.awaitText]] and [[Pane.await]] poll the screen or the pane's
* state on a timer and answer with why they ended; a pane killed mid-wait ends
* [[Pane.awaitText]] as `TextOutcome.PANE_GONE` rather than an exception. Each
* wait blocks its thread, and interrupting the thread cancels it with
* `InterruptedException`. [[Pane.dead]] reads fresh whether the pane's process
* has exited, and throws when the pane is gone from a server that still
* answers.
*
* [[Pane.run]], [[Pane.awaitText]], [[Pane.await]] and [[Pane.dead]]
*
* **Splitting and arranging.** [[Pane.split]] divides this pane in half, from a
* callback on a builder or a `SplitSpec`, and returns the pane that appeared.
* [[Pane.breakOut]] moves the pane into a window of its own, [[Pane.joinTo]]
* into another window, and [[Pane.swapWith]] swaps it with another pane.
* [[Pane.resize]] grows it by cells in one direction, [[Pane.resizeTo]] sets
* exact dimensions, and [[Pane.select]] makes it the active pane. An unnamed
* [[Pane.breakOut]] throws on exact tmux 3.7, which a named break or 3.7a
* avoids.
*
* [[Pane.split]], [[Pane.breakOut]], [[Pane.joinTo]], [[Pane.swapWith]],
* [[Pane.resize]], [[Pane.resizeTo]] and [[Pane.select]]
*
* **Modes.** [[Pane.copyMode]] puts the pane into copy mode, [[Pane.mode]]
* reads live which mode it is in, empty when it is showing its program, and
* [[Pane.exitMode]] leaves whichever mode it is in.
*
* [[Pane.copyMode]], [[Pane.mode]] and [[Pane.exitMode]]
*
* **Changing the pane.** [[Pane.retitle]] returns a replacement capture,
* because this handle keeps its original state. [[Pane.respawn]] kills what
* runs here and starts the pane's default command or one you give,
* [[Pane.respawnIn]] does so in a directory, and [[Pane.kill]] closes the pane.
*
* [[Pane.retitle]], [[Pane.respawn]], [[Pane.respawnIn]] and [[Pane.kill]]
*
* **Options and hooks.** [[Pane.options]] and [[Pane.hooks]] reach what is set
* on this pane alone.
*
* [[Pane.options]] and [[Pane.hooks]]
*
* **Formats and refreshing.** [[Pane.expand]] expands a tmux format, and
* [[Pane.variables]] reads several named variables, in this pane's context.
* [[Pane.refresh]] takes a new capture to see the pane as it is now. It leaves
* this handle unchanged and returns the new one, and throws if the pane is gone
* from a server that still answers.
*
* [[Pane.expand]], [[Pane.variables]] and [[Pane.refresh]]
*/
opaque type Pane = JavaPane

Expand Down
Loading
Loading