Class: Muxr::PTYProcess
- Inherits:
-
Object
- Object
- Muxr::PTYProcess
- Defined in:
- lib/muxr/pty_process.rb
Overview
Owns a single pseudo-terminal pair plus the child shell process attached to the slave side. The parent side is exposed via #io / #read_nonblock / #write.
Instance Attribute Summary collapse
-
#cols ⇒ Object
readonly
Returns the value of attribute cols.
-
#io ⇒ Object
readonly
Returns the value of attribute io.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
-
#rows ⇒ Object
readonly
Returns the value of attribute rows.
Instance Method Summary collapse
- #alive? ⇒ Boolean
- #close ⇒ Object
-
#cwd ⇒ Object
Best-effort cwd of the child process.
-
#initialize(command: nil, rows: 24, cols: 80, cwd: nil, env_overrides: {}) ⇒ PTYProcess
constructor
A new instance of PTYProcess.
- #read_nonblock(max = 8192) ⇒ Object
- #reap ⇒ Object
- #resize(rows, cols) ⇒ Object
- #write(data) ⇒ Object
Constructor Details
#initialize(command: nil, rows: 24, cols: 80, cwd: nil, env_overrides: {}) ⇒ PTYProcess
Returns a new instance of PTYProcess.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/muxr/pty_process.rb', line 9 def initialize(command: nil, rows: 24, cols: 80, cwd: nil, env_overrides: {}) @rows = rows @cols = cols @exited = false shell = command || ENV["SHELL"] || "/bin/sh" env = ENV.to_h.merge("TERM" => "xterm-256color").merge(env_overrides) env["LINES"] = rows.to_s env["COLUMNS"] = cols.to_s chdir = (cwd && File.directory?(cwd)) ? cwd : Dir.pwd @reader, @writer, @pid = PTY.spawn(env, shell, chdir: chdir) @io = @reader resize(rows, cols) end |
Instance Attribute Details
#cols ⇒ Object (readonly)
Returns the value of attribute cols.
7 8 9 |
# File 'lib/muxr/pty_process.rb', line 7 def cols @cols end |
#io ⇒ Object (readonly)
Returns the value of attribute io.
7 8 9 |
# File 'lib/muxr/pty_process.rb', line 7 def io @io end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
7 8 9 |
# File 'lib/muxr/pty_process.rb', line 7 def pid @pid end |
#rows ⇒ Object (readonly)
Returns the value of attribute rows.
7 8 9 |
# File 'lib/muxr/pty_process.rb', line 7 def rows @rows end |
Instance Method Details
#alive? ⇒ Boolean
52 53 54 55 56 57 58 59 |
# File 'lib/muxr/pty_process.rb', line 52 def alive? return false if @exited Process.kill(0, @pid) true rescue Errno::ESRCH, Errno::EPERM @exited = true false end |
#close ⇒ Object
67 68 69 70 71 72 73 74 |
# File 'lib/muxr/pty_process.rb', line 67 def close reap Process.kill("TERM", @pid) if alive? @reader.close unless @reader.closed? @writer.close if @writer != @reader && !@writer.closed? rescue Errno::ESRCH, Errno::EBADF, IOError # already gone end |
#cwd ⇒ Object
Best-effort cwd of the child process. Used to inherit cwd when opening the drawer or for session save/restore. Falls back to nil if the system doesn’t expose the information.
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/muxr/pty_process.rb', line 79 def cwd if File.directory?("/proc/#{@pid}") File.readlink("/proc/#{@pid}/cwd") else # macOS / BSD fallback via lsof. out = `lsof -a -p #{@pid} -d cwd -Fn 2>/dev/null` line = out.lines.find { |l| l.start_with?("n/") } line && line[1..].strip end rescue StandardError nil end |
#read_nonblock(max = 8192) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/muxr/pty_process.rb', line 33 def read_nonblock(max = 8192) @reader.read_nonblock(max) rescue IO::WaitReadable nil rescue EOFError, Errno::EIO @exited = true nil end |
#reap ⇒ Object
61 62 63 64 65 |
# File 'lib/muxr/pty_process.rb', line 61 def reap Process.waitpid(@pid, Process::WNOHANG) rescue Errno::ECHILD nil end |
#resize(rows, cols) ⇒ Object
42 43 44 45 46 47 48 49 50 |
# File 'lib/muxr/pty_process.rb', line 42 def resize(rows, cols) @rows = rows @cols = cols begin @reader.winsize = [rows, cols, 0, 0] rescue StandardError # Some platforms reject zero pixel sizes; ignore. end end |
#write(data) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/muxr/pty_process.rb', line 26 def write(data) @writer.write(data) @writer.flush rescue Errno::EIO, IOError, Errno::EPIPE @exited = true end |