Module: Runbook::Helpers::TmuxHelper

Included in:
Run::ClassMethods
Defined in:
lib/runbook/helpers/tmux_helper.rb

Instance Method Summary collapse

Instance Method Details

#_all_panes_exist?(stored_layout) ⇒ Boolean



47
48
49
# File 'lib/runbook/helpers/tmux_helper.rb', line 47

def _all_panes_exist?(stored_layout)
  (stored_layout.values - _session_panes).empty?
end

#_initialize_panes(panes_to_init, layout_panes) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/runbook/helpers/tmux_helper.rb', line 139

def _initialize_panes(panes_to_init, layout_panes)
  panes_to_init.each do |pane|
    target = layout_panes[pane[:name]]
    _set_directory(pane[:directory], target) if pane[:directory]
    send_keys(pane[:command], target) if pane[:command]
  end
end

#_kill_pane(pane_id) ⇒ Object



35
36
37
# File 'lib/runbook/helpers/tmux_helper.rb', line 35

def _kill_pane(pane_id)
  `tmux kill-pane -t #{pane_id}`
end

#_layout_file(runbook_title) ⇒ Object



39
40
41
# File 'lib/runbook/helpers/tmux_helper.rb', line 39

def _layout_file(runbook_title)
  `tmux display-message -p -t $TMUX_PANE "#{Dir.tmpdir}/runbook_layout_\#{pid}_\#{session_name}_\#{pane_pid}_\#{pane_id}_#{runbook_title}.yml"`.strip
end

#_new_window(name) ⇒ Object



155
156
157
# File 'lib/runbook/helpers/tmux_helper.rb', line 155

def _new_window(name)
  `tmux new-window -n "#{name}" -P -F '#D' -d`.strip
end

#_pager_escape_sequenceObject



31
32
33
# File 'lib/runbook/helpers/tmux_helper.rb', line 31

def _pager_escape_sequence
  "q C-u"
end

#_remove_stale_layoutsObject



51
52
53
54
55
56
57
# File 'lib/runbook/helpers/tmux_helper.rb', line 51

def _remove_stale_layouts
  session_panes = _session_panes
  session_layout_files = _session_layout_files
  session_layout_files.each do |file|
    File.delete(file) unless session_panes.any? { |pane| /_#{pane}_/ =~ file }
  end
end

#_rename_window(name) ⇒ Object



151
152
153
# File 'lib/runbook/helpers/tmux_helper.rb', line 151

def _rename_window(name)
  `tmux rename-window "#{name}"`
end

#_runbook_paneObject



147
148
149
# File 'lib/runbook/helpers/tmux_helper.rb', line 147

def _runbook_pane
  @runbook_pane ||= `tmux display-message -p '#D'`.strip
end

#_session_layout_filesObject



63
64
65
66
# File 'lib/runbook/helpers/tmux_helper.rb', line 63

def _session_layout_files
  session_layout_glob = `tmux display-message -p "#{Dir.tmpdir}/runbook_layout_\#{pid}_\#{session_name}_*.yml"`.strip
  Dir[session_layout_glob]
end

#_session_panesObject



59
60
61
# File 'lib/runbook/helpers/tmux_helper.rb', line 59

def _session_panes
  `tmux list-panes -s -F '#D'`.split("\n")
end

#_set_directory(directory, target) ⇒ Object



170
171
172
# File 'lib/runbook/helpers/tmux_helper.rb', line 170

def _set_directory(directory, target)
  send_keys("cd #{directory}; clear", target)
end

#_setup_layout(structure) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/runbook/helpers/tmux_helper.rb', line 68

def _setup_layout(structure)
  current_pane = _runbook_pane
  panes_to_init = []
  {}.tap do |layout_panes|
    if structure.is_a?(Hash)
      first_window = true
      structure.each do |name, window|
        if first_window
          _rename_window(name)
          first_window = false
        else
          current_pane = _new_window(name)
        end
        _setup_panes(layout_panes, panes_to_init, current_pane, window)
      end
    else
      _setup_panes(layout_panes, panes_to_init, current_pane, structure)
    end
    _swap_runbook_pane(panes_to_init, layout_panes)
    _initialize_panes(panes_to_init, layout_panes)
  end
end

#_setup_panes(layout_panes, panes_to_init, current_pane, structure, depth = 0) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/runbook/helpers/tmux_helper.rb', line 91

def _setup_panes(layout_panes, panes_to_init, current_pane, structure, depth=0)
  return if structure.empty?
  case structure
  when Array
    case structure.size
    when 1
      _setup_panes(layout_panes, panes_to_init, current_pane, structure.shift, depth+1)
    else
      size = 100 - 100 / structure.size
      new_pane = _split(current_pane, depth, size)
      _setup_panes(layout_panes, panes_to_init, current_pane, structure.shift, depth+1)
      _setup_panes(layout_panes, panes_to_init, new_pane, structure, depth)
    end
  when Hash
    if structure.values.all? { |v| v.is_a?(Numeric) }
      total_size = structure.values.reduce(:+)
      case structure.size
      when 1
        _setup_panes(layout_panes, panes_to_init, current_pane, structure.keys[0], depth+1)
      else
        size = (total_size - structure.values[0]) * 100 / total_size
        new_pane = _split(current_pane, depth, size)
        first_struct = structure.keys[0]
        structure.delete(first_struct)
        _setup_panes(layout_panes, panes_to_init, current_pane, first_struct, depth+1)
        _setup_panes(layout_panes, panes_to_init, new_pane, structure, depth)
      end
    else
      layout_panes[structure[:name]] = current_pane
      panes_to_init << structure
    end
  when Symbol
    layout_panes[structure] = current_pane
  end
end

#_slug(title) ⇒ Object



43
44
45
# File 'lib/runbook/helpers/tmux_helper.rb', line 43

def _slug(title)
  title.titleize.gsub(/\s+/, "").underscore.dasherize
end

#_split(current_pane, depth, size) ⇒ Object



159
160
161
162
163
164
# File 'lib/runbook/helpers/tmux_helper.rb', line 159

def _split(current_pane, depth, size)
  direction = depth.even? ? "h" : "v"
  command = "tmux split-window"
  args = "-#{direction} -t #{current_pane} -p #{size} -P -F '#D' -d"
  `#{command} #{args}`.strip
end

#_swap_panes(target_pane, source_pane) ⇒ Object



166
167
168
# File 'lib/runbook/helpers/tmux_helper.rb', line 166

def _swap_panes(target_pane, source_pane)
  `tmux swap-pane -d -t #{target_pane} -s #{source_pane}`
end

#_swap_runbook_pane(panes_to_init, layout_panes) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/runbook/helpers/tmux_helper.rb', line 127

def _swap_runbook_pane(panes_to_init, layout_panes)
  if (runbook_pane = panes_to_init.find { |pane| pane[:runbook_pane] })
    current_runbook_pane_name = layout_panes.keys.find do |k|
      layout_panes[k] == _runbook_pane
    end
    target_pane_id = layout_panes[runbook_pane[:name]]
    layout_panes[runbook_pane[:name]] = _runbook_pane
    layout_panes[current_runbook_pane_name] = target_pane_id
    _swap_panes(target_pane_id, _runbook_pane)
  end
end

#kill_all_panes(layout_panes) ⇒ Object



24
25
26
27
28
29
# File 'lib/runbook/helpers/tmux_helper.rb', line 24

def kill_all_panes(layout_panes)
  runbook_pane = _runbook_pane
  layout_panes.values.each do |pane_id|
    _kill_pane(pane_id) unless pane_id == runbook_pane
  end
end

#send_keys(command, target) ⇒ Object



20
21
22
# File 'lib/runbook/helpers/tmux_helper.rb', line 20

def send_keys(command, target)
  `tmux send-keys -t #{target} #{_pager_escape_sequence} '#{command}' C-m`
end

#setup_layout(structure, runbook_title:) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/runbook/helpers/tmux_helper.rb', line 3

def setup_layout(structure, runbook_title:)
  _remove_stale_layouts
  layout_file = _layout_file(_slug(runbook_title))
  if File.exists?(layout_file)
    stored_layout = ::YAML::load_file(layout_file)
    if _all_panes_exist?(stored_layout)
      return stored_layout
    end
  end

  _setup_layout(structure).tap do |layout_panes|
    File.open(layout_file, 'w') do |f|
      f.write(layout_panes.to_yaml)
    end
  end
end