Class: AgentsControl::Terminals::Tmux
- Defined in:
- lib/agents_control/terminals/tmux.rb
Overview
tmux.
The only backend that works on both macOS and Linux, and also the fastest one: a full pane list comes back in 0.008s versus 0.9s for iTerm2 — a hundred-plus-fold difference. It's also the only one with scrollback and the only one that survives an ssh disconnect.
Inside iTerm2 it runs as tmux -CC: tmux windows become native
tabs, and both backends operate on the same machine at once.
Constant Summary collapse
- FORMAT_FIELDS =
%w doesn't interpolate — the literal tmux substitutions stay intact inside.
%w[ #{pane_id} #{pane_tty} #{pane_current_command} #{pane_current_path} #{session_name} #{window_name} ].freeze
- FIELDS =
%i[id tty command cwd session window].freeze
- SHELLS =
Shells under which a pane counts as "at a prompt" rather than busy.
%w[zsh bash sh fish dash ksh tcsh].freeze
Instance Method Summary collapse
-
#available? ⇒ Boolean
Just having the binary is enough: the server might not be running yet, but we can still create a window in it.
-
#capture(id, lines: 200) ⇒ Object
This is exactly what tmux is for: history, not just the visible screen.
- #close(id) ⇒ Object
- #create_tab(cwd: nil, command: nil) ⇒ Object
- #focus(id) ⇒ Object
- #name ⇒ Object
- #send_text(id, text, newline: true) ⇒ Object
- #sessions ⇒ Object
Methods inherited from Base
Constructor Details
This class inherits a constructor from AgentsControl::Terminals::Base
Instance Method Details
#available? ⇒ Boolean
Just having the binary is enough: the server might not be running yet, but we can still create a window in it.
34 |
# File 'lib/agents_control/terminals/tmux.rb', line 34 def available? = !binary.nil? |
#capture(id, lines: 200) ⇒ Object
This is exactly what tmux is for: history, not just the visible screen.
78 79 80 81 |
# File 'lib/agents_control/terminals/tmux.rb', line 78 def capture(id, lines: 200) result = run("capture-pane", "-p", "-t", id, "-S", "-#{lines}") result.success? ? result.stdout.rstrip : "" end |
#close(id) ⇒ Object
87 |
# File 'lib/agents_control/terminals/tmux.rb', line 87 def close(id) = run("kill-pane", "-t", id).success? |
#create_tab(cwd: nil, command: nil) ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'lib/agents_control/terminals/tmux.rb', line 62 def create_tab(cwd: nil, command: nil) args = ["new-window", "-P", "-F", "#{'#'}{pane_id}"] args += ["-c", cwd] if cwd && !cwd.empty? args << command if command && !command.empty? result = run(*args) result.success? ? result.stdout.strip : nil end |
#focus(id) ⇒ Object
83 84 85 |
# File 'lib/agents_control/terminals/tmux.rb', line 83 def focus(id) run("select-window", "-t", id).success? && run("select-pane", "-t", id).success? end |
#name ⇒ Object
30 |
# File 'lib/agents_control/terminals/tmux.rb', line 30 def name = :tmux |
#send_text(id, text, newline: true) ⇒ Object
71 72 73 74 75 |
# File 'lib/agents_control/terminals/tmux.rb', line 71 def send_text(id, text, newline: true) args = ["send-keys", "-t", id, "--", text] args << "Enter" if newline run(*args).success? end |
#sessions ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/agents_control/terminals/tmux.rb', line 36 def sessions return [] unless available? result = run("list-panes", "-a", "-F", format_string) # No server isn't an error, it just means there are no panes yet. return [] unless result.success? parse_records(result.stdout, FIELDS).map do |record| Session.new( id: record[:id], backend: name, tty: record[:tty], title: [record[:session], record[:window]].compact.join(":"), cwd: record[:cwd], # tmux has no equivalent of `is processing`, so this is nil — # "unknown", not "no". ProcessProbe determines busy-ness. processing: nil, at_shell_prompt: SHELLS.include?(record[:command].to_s), # tmux already knows what's running in the pane — this same # list-panes call hands back the process name for free, with # no trip through ProcessProbe needed. foreground_command: record[:command] ) end end |