tmux-fingers/lib/tmux.rb

220 lines
4.7 KiB
Ruby

# frozen_string_literal: true
# rubocop:disable Metrics/ClassLength
class Tmux
include Singleton
Pane = Struct.new(
:pane_id,
:window_id,
:pane_width,
:pane_height,
:scroll_position,
:pane_path,
:pane_in_mode,
:window_zoomed_flag,
:pane_current_path
)
Window = Struct.new(
:window_id,
:window_height,
:window_width,
:pane_id,
:pane_tty
)
def initialize
@format_printer = TmuxFormatPrinter.new
end
def refresh!
@panes = nil
@windows = nil
end
def panes
return @panes if @panes
format = build_tmux_output_format(Tmux::Pane.members)
output = `#{tmux} list-panes -a -F '#{format}'`.chomp
@panes = parse_tmux_formatted_output(output) do |fields|
Pane.new(*fields)
end
end
def windows
return @windows if @windows
format = build_tmux_output_format(Tmux::Window.members)
output = `#{tmux} list-windows -a -F '#{format}'`
@windows = parse_tmux_formatted_output(output) do |fields|
Window.new(*fields)
end
end
def new_session(name, cmd, width, height)
flags = []
flags.push('-f', config_file) if config_file
`env -u TMUX #{tmux} #{flags.join(' ')} new-session -d -s #{name} -x #{width} -y #{height} '#{cmd}'`
end
def start_server
flags = []
flags.push('-f', config_file) if config_file
`#{tmux} #{flags.join(' ')} start-server &`
end
def pane_by_id(id)
panes.find { |pane| pane['pane_id'] == id }
end
def window_by_id(id)
windows.find { |window| window['window_id'] == id }
end
def panes_by_window_id(window_id)
panes.select { |pane| pane['window_id'] == window_id }
end
def pane_exec(pane_id, cmd)
send_keys(pane_id, " #{cmd}")
send_keys(pane_id, 'Enter')
end
def send_keys(pane_id, keys)
`#{tmux} send-keys -t '#{pane_id}' '#{keys}'`
end
def capture_pane(pane_id)
pane = pane_by_id(pane_id)
if pane.pane_in_mode == '1'
start_line = -pane.scroll_position.to_i
end_line = pane.pane_height.to_i - pane.scroll_position.to_i - 1
`#{tmux} capture-pane -J -p -t '#{pane_id}' -S #{start_line} -E #{end_line}`
else
`#{tmux} capture-pane -J -p -t '#{pane_id}'`
end
end
def create_window(name, cmd, _pane_width, _pane_height)
format = build_tmux_output_format(Tmux::Window.members)
output = `#{tmux} new-window -P -d -n "#{name}" -F '#{format}' "#{cmd}"`.chomp
parse_tmux_formatted_output(output) do |fields|
Window.new(*fields)
end.first
end
def swap_panes(src_id, dst_id)
# TODO: -Z not supported on all tmux versions
system(tmux, 'swap-pane', '-d', '-s', src_id, '-t', dst_id)
end
def kill_pane(id)
`#{tmux} kill-pane -t #{id}`
end
def kill_window(id)
`#{tmux} kill-window -t #{id}`
end
# TODO: this command is version dependant D:
def resize_window(window_id, width, height)
system(tmux, 'resize-window', '-t', window_id, '-x', width.to_s, '-y', height.to_s)
end
# TODO: this command is version dependant D:
def resize_pane(pane_id, width, height)
system(tmux, 'resize-pane', '-t', pane_id, '-x', width.to_s, '-y', height.to_s)
end
def last_pane_id
`#{tmux} display -pt':.{last}' '#{pane_id}'`
end
def set_window_option(name, value)
system(tmux, 'set-window-option', name, value)
end
def set_key_table(table)
system(tmux, 'set-window-option', 'key-table', table)
system(tmux, 'switch-client', '-T', table)
end
def disable_prefix
set_global_option('prefix', 'None')
set_global_option('prefix2', 'None')
end
def set_global_option(name, value)
system(tmux, 'set-option', '-g', name, value)
end
def get_global_option(name)
`#{tmux} show -gqv #{name}`.chomp
end
def set_buffer(value)
return unless value
system(tmux, 'set-buffer', value)
end
def select_pane(id)
system(tmux, 'select-pane', '-t', id)
end
def zoom_pane(id)
system(tmux, 'resize-pane', '-Z', '-t', id)
end
def parse_format(format)
format_printer.print(format).chomp
end
attr_accessor :socket, :config_file
private
attr_reader :format_printer
def tmux
flags = []
flags.push('-L', socket_flag_value) if socket_flag_value
return "tmux #{flags.join(' ')}" unless flags.empty?
'tmux'
end
def build_tmux_output_format(fields)
fields.map { |field| format("\#{%<field>s}", field: field) }.join(';')
end
def parse_tmux_formatted_output(output)
output.split("\n").map do |line|
fields = line.split(';')
yield fields
end
end
def socket_flag_value
return ENV['FINGERS_TMUX_SOCKET'] if ENV['FINGERS_TMUX_SOCKET']
socket
end
end
#Tmux = TmuxControl
# rubocop:enable Metrics/ClassLength