Class: Muxr::Pane
- Inherits:
-
Object
- Object
- Muxr::Pane
- Defined in:
- lib/muxr/pane.rb
Overview
A Pane bundles a Terminal emulator buffer with the PTYProcess running the shell that feeds it. The Window keeps a list of panes; the Renderer asks each pane for its current grid contents and cursor position.
Each pane has a stable 6-hex id generated at creation. The id survives promote_to_master and other array reshuffles (since it lives on the Pane, not on the index) and is persisted in the session JSON so it also survives a full cold restart. The drawer pane uses the symbol ‘:drawer` as its id; the MCP control surface treats it specially and never lists it under `panes.list`.
Constant Summary collapse
- READ_BUDGET =
Drain everything currently in the PTY’s kernel read buffer, feeding each chunk to the Terminal. Coalescing reads here means we render once per fully-formed output burst (fzf re-render, vim cursor+status redraw, etc.) instead of once per ~8 KiB chunk — the latter shows intermediate frames and is the main source of in-pane flicker. Bounded by a byte cap so a runaway producer can’t starve other panes on a single tick.
1 << 20
Instance Attribute Summary collapse
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#process ⇒ Object
readonly
Returns the value of attribute process.
-
#rect ⇒ Object
Returns the value of attribute rect.
-
#terminal ⇒ Object
readonly
Returns the value of attribute terminal.
Instance Method Summary collapse
- #alive? ⇒ Boolean
- #close ⇒ Object
- #cwd ⇒ Object
- #drain_writes ⇒ Object
-
#initialize(id: nil, rows: 24, cols: 80, cwd: nil, command: nil, env_overrides: nil, process: nil) ⇒ Pane
constructor
A new instance of Pane.
- #io ⇒ Object
- #mark_private! ⇒ Object
- #mark_public! ⇒ Object
- #pending_write? ⇒ Boolean
-
#private? ⇒ Boolean
Private panes are invisible to the MCP control surface — their cwd is stripped from panes.list and pane.read/send_input/run/subscribe/kill all refuse.
-
#read_from_pty ⇒ Object
1 MiB.
- #resize(rows, cols) ⇒ Object
- #toggle_private! ⇒ Object
- #write(data) ⇒ Object
- #writer_io ⇒ Object
Constructor Details
#initialize(id: nil, rows: 24, cols: 80, cwd: nil, command: nil, env_overrides: nil, process: nil) ⇒ Pane
Returns a new instance of Pane.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/muxr/pane.rb', line 18 def initialize(id: nil, rows: 24, cols: 80, cwd: nil, command: nil, env_overrides: nil, process: nil) @id = id || SecureRandom.hex(3) @rows = rows @cols = cols @terminal = Terminal.new(rows: rows, cols: cols) @process = process || PTYProcess.new( rows: rows, cols: cols, cwd: cwd, command: command, env_overrides: env_overrides || {} ) @rect = nil @initial_cwd = cwd || @process.cwd @private_flag = false end |
Instance Attribute Details
#id ⇒ Object (readonly)
Returns the value of attribute id.
15 16 17 |
# File 'lib/muxr/pane.rb', line 15 def id @id end |
#process ⇒ Object (readonly)
Returns the value of attribute process.
15 16 17 |
# File 'lib/muxr/pane.rb', line 15 def process @process end |
#rect ⇒ Object
Returns the value of attribute rect.
16 17 18 |
# File 'lib/muxr/pane.rb', line 16 def rect @rect end |
#terminal ⇒ Object (readonly)
Returns the value of attribute terminal.
15 16 17 |
# File 'lib/muxr/pane.rb', line 15 def terminal @terminal end |
Instance Method Details
#alive? ⇒ Boolean
110 111 112 |
# File 'lib/muxr/pane.rb', line 110 def alive? @process.alive? end |
#close ⇒ Object
118 119 120 |
# File 'lib/muxr/pane.rb', line 118 def close @process.close end |
#cwd ⇒ Object
114 115 116 |
# File 'lib/muxr/pane.rb', line 114 def cwd @process.cwd || @initial_cwd end |
#drain_writes ⇒ Object
68 69 70 |
# File 'lib/muxr/pane.rb', line 68 def drain_writes @process.drain end |
#io ⇒ Object
56 57 58 |
# File 'lib/muxr/pane.rb', line 56 def io @process.io end |
#mark_private! ⇒ Object
44 45 46 |
# File 'lib/muxr/pane.rb', line 44 def mark_private! @private_flag = true end |
#mark_public! ⇒ Object
48 49 50 |
# File 'lib/muxr/pane.rb', line 48 def mark_public! @private_flag = false end |
#pending_write? ⇒ Boolean
64 65 66 |
# File 'lib/muxr/pane.rb', line 64 def pending_write? @process.pending_write? end |
#private? ⇒ Boolean
Private panes are invisible to the MCP control surface — their cwd is stripped from panes.list and pane.read/send_input/run/subscribe/kill all refuse. Toggled by the human via Ctrl-a P or ‘:private`. Never settable from the control surface itself (so a misbehaving MCP client can’t unmark a pane it shouldn’t see).
40 41 42 |
# File 'lib/muxr/pane.rb', line 40 def private? @private_flag end |
#read_from_pty ⇒ Object
1 MiB
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/muxr/pane.rb', line 83 def read_from_pty total = 0 while total < READ_BUDGET chunk = @process.read_nonblock break unless chunk @terminal.feed(chunk) total += chunk.bytesize end # The emulator may owe the inner program a reply (DSR / CPR — see # Terminal#take_pending_replies!). Ship it back through the PTY's # input side as if it had been typed. Failure here is non-fatal: the # process can have exited between read and write. if (reply = @terminal.take_pending_replies!) begin @process.write(reply) rescue Errno::EIO, Errno::EPIPE end end total.positive? ? total : nil end |
#resize(rows, cols) ⇒ Object
104 105 106 107 108 |
# File 'lib/muxr/pane.rb', line 104 def resize(rows, cols) return if rows == @terminal.rows && cols == @terminal.cols @terminal.resize(rows, cols) @process.resize(rows, cols) end |
#toggle_private! ⇒ Object
52 53 54 |
# File 'lib/muxr/pane.rb', line 52 def toggle_private! @private_flag = !@private_flag end |
#write(data) ⇒ Object
72 73 74 |
# File 'lib/muxr/pane.rb', line 72 def write(data) @process.write(data) end |
#writer_io ⇒ Object
60 61 62 |
# File 'lib/muxr/pane.rb', line 60 def writer_io @process.writer_io end |