Class: Terminitor::ItermCore
- Inherits:
-
AbstractCore
- Object
- AbstractCore
- Terminitor::ItermCore
- Includes:
- Appscript
- Defined in:
- lib/terminitor/cores/iterm_core.rb
Overview
Mac OS X Core for Terminitor This Core manages all the interaction with Appscript and the Terminal
Constant Summary collapse
- ALLOWED_OPTIONS =
{ :window => [:bounds, :visible, :miniaturized], :tab => [:settings, :selected] }
Instance Attribute Summary
Attributes inherited from AbstractCore
#termfile, #terminal, #windows, #working_dir
Instance Method Summary collapse
-
#active_window ⇒ Object
Returns the active window i.e.
- #call_ui_action(menu, submenu, action) ⇒ Object
-
#current_terminal ⇒ Object
Returns the current terminal i.e.
-
#execute_command(cmd, options = {}) ⇒ Object
executes the given command via appscript execute_command ‘cd /path/to’, :in => #<tab>.
- #execute_pane_commands(pane_commands, tab_commands) ⇒ Object
- #first_pane_level_split(panes, tab_commands) ⇒ Object
- #handle_panes(tab_content) ⇒ Object
- #handle_subpanes(subpanes, tab_commands) ⇒ Object
-
#initialize(path) ⇒ ItermCore
constructor
Initialize @terminal with Terminal.app, Load the Windows, store the Termfile Terminitor::MacCore.new(‘/path’).
-
#iterm_menu ⇒ Object
Methods for splitting panes (GUI_scripting).
-
#open_tab(options = nil) ⇒ Object
Opens a new tab, iterm sets focus on new tab TODO : handle options (?).
-
#open_window(options = nil) ⇒ Object
Open new window, applies settings to the first tab.
-
#run_in_window(window_name, window_content, options = {}) ⇒ Object
this command will run commands in the designated window run_in_window ‘window1’, => [‘ls’,‘ok’].
- #second_pane_level_split(panes, tab_commands) ⇒ Object
-
#select_pane(direction) ⇒ Object
to select panes; iTerm’s Appscript select method does not work as expected, we have to select via menu instead.
-
#set_delayed_options ⇒ Object
Apply delayed options and remove them from the queue.
-
#set_options(object, options = {}) ⇒ Object
Sets options of the given object.
- #split_h ⇒ Object
- #split_v ⇒ Object
Methods inherited from AbstractCore
#load_termfile, #process!, #setup!
Constructor Details
#initialize(path) ⇒ ItermCore
Initialize @terminal with Terminal.app, Load the Windows, store the Termfile Terminitor::MacCore.new(‘/path’)
14 15 16 17 18 19 |
# File 'lib/terminitor/cores/iterm_core.rb', line 14 def initialize(path) super @terminal = app('iTerm') @windows = @terminal.terminals @delayed_options = [] end |
Instance Method Details
#active_window ⇒ Object
Returns the active window i.e. the active terminal session in iTerm
46 47 48 |
# File 'lib/terminitor/cores/iterm_core.rb', line 46 def active_window current_terminal.current_session end |
#call_ui_action(menu, submenu, action) ⇒ Object
189 190 191 192 193 |
# File 'lib/terminitor/cores/iterm_core.rb', line 189 def call_ui_action(, , action) = .[].[] = .[].[] if .[action].click end |
#current_terminal ⇒ Object
Returns the current terminal i.e. the active iTerm window
51 52 53 |
# File 'lib/terminitor/cores/iterm_core.rb', line 51 def current_terminal @terminal.current_terminal end |
#execute_command(cmd, options = {}) ⇒ Object
executes the given command via appscript execute_command ‘cd /path/to’, :in => #<tab>
23 24 25 26 27 28 29 |
# File 'lib/terminitor/cores/iterm_core.rb', line 23 def execute_command(cmd, = {}) if [:in] [:in].write(:text => "#{cmd}") else active_window.write(:text => "#{cmd}") end end |
#execute_pane_commands(pane_commands, tab_commands) ⇒ Object
176 177 178 179 |
# File 'lib/terminitor/cores/iterm_core.rb', line 176 def execute_pane_commands(pane_commands, tab_commands) pane_commands = tab_commands + pane_commands pane_commands.each { |cmd| execute_command cmd} end |
#first_pane_level_split(panes, tab_commands) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/terminitor/cores/iterm_core.rb', line 143 def first_pane_level_split(panes, tab_commands) first_pane = true split_v_counter = 0 panes.keys.sort.each do |pane_key| pane_content = panes[pane_key] unless first_pane split_v split_v_counter += 1 end first_pane = false if first_pane pane_commands = pane_content[:commands] execute_pane_commands(pane_commands, tab_commands) end split_v_counter.times { select_pane 'Left' } end |
#handle_panes(tab_content) ⇒ Object
136 137 138 139 140 141 |
# File 'lib/terminitor/cores/iterm_core.rb', line 136 def handle_panes(tab_content) panes = tab_content[:panes] tab_commands = tab_content[:commands] first_pane_level_split(panes, tab_commands) second_pane_level_split(panes, tab_commands) end |
#handle_subpanes(subpanes, tab_commands) ⇒ Object
168 169 170 171 172 173 174 |
# File 'lib/terminitor/cores/iterm_core.rb', line 168 def handle_subpanes(subpanes, tab_commands) subpanes.keys.sort.each do |subpane_key| subpane_commands = subpanes[subpane_key][:commands] split_h execute_pane_commands(subpane_commands, tab_commands) end end |
#iterm_menu ⇒ Object
Methods for splitting panes (GUI_scripting)
184 185 186 187 |
# File 'lib/terminitor/cores/iterm_core.rb', line 184 def terminal_process = Appscript.app("System Events").processes["iTerm"] terminal_process..first end |
#open_tab(options = nil) ⇒ Object
Opens a new tab, iterm sets focus on new tab TODO : handle options (?)
33 34 35 |
# File 'lib/terminitor/cores/iterm_core.rb', line 33 def open_tab( = nil) current_terminal.launch_ :session => 'New session' end |
#open_window(options = nil) ⇒ Object
Open new window, applies settings to the first tab. iterm sets focus on new tab TODO : handle options (?)
40 41 42 43 |
# File 'lib/terminitor/cores/iterm_core.rb', line 40 def open_window( = nil) window = terminal.make( :new => :terminal ) window.launch_ :session => 'New session' end |
#run_in_window(window_name, window_content, options = {}) ⇒ Object
this command will run commands in the designated window run_in_window ‘window1’, => [‘ls’,‘ok’]
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 126 127 128 129 130 131 132 133 134 |
# File 'lib/terminitor/cores/iterm_core.rb', line 99 def run_in_window(window_name, window_content, = {}) = window_content[:options] first_tab = true window_content[:tabs].keys.sort.each do |tab_key| tab_content = window_content[:tabs][tab_key] # Open window on first 'tab' statement # first tab is already opened in the new window, so first tab should be # opened as a new tab in default window only = tab_content[:options] tab_name = [:name] if if first_tab && ![:default] first_tab = false = (.to_a + .to_a).inject([]) {|arr, pair| arr += pair } = Hash[*] # safe merge tab = .empty? ? open_window(nil) : open_window() else # give us the current window if its default, else open a tab. tab = ( tab_key == 'default' ? active_window : open_tab() ) end # append our before block commands. tab_content[:commands].insert(0, window_content[:before]).flatten! if window_content[:before] # clean up prompt tab_content[:commands].insert(0, 'clear') if tab_name || !@working_dir.to_s.empty? # add title to tab tab_content[:commands].insert(0, "PS1=\"$PS1\\[\\e]2;#{tab_name}\\a\\]\"") if tab_name tab_content[:commands].insert(0, "cd \"#{@working_dir}\"") unless @working_dir.to_s.empty? # if tab_content hash has a key :panes we know this tab should be split # we can execute tab commands if there is no key :panes if tab_content.key?(:panes) handle_panes(tab_content) else tab_content[:commands].each { |cmd| execute_command(cmd, :in => tab) } end end end |
#second_pane_level_split(panes, tab_commands) ⇒ Object
159 160 161 162 163 164 165 166 |
# File 'lib/terminitor/cores/iterm_core.rb', line 159 def second_pane_level_split(panes, tab_commands) panes.keys.sort.each do |pane_key| pane_content = panes[pane_key] handle_subpanes(pane_content[:panes], tab_commands) if pane_content.has_key? :panes # select next vertical pane select_pane 'Right' end end |
#select_pane(direction) ⇒ Object
to select panes; iTerm’s Appscript select method does not work as expected, we have to select via menu instead
205 206 207 208 209 210 211 212 |
# File 'lib/terminitor/cores/iterm_core.rb', line 205 def select_pane(direction) valid_directions = %w[Above Below Left Right] if valid_directions.include?(direction) call_ui_action("Window", "Select Split Pane", "Select Pane #{direction}") else puts "Error: #{direction} is not a valid direction to select a pane; Only Above/Below/Left/Right are valid directions" end end |
#set_delayed_options ⇒ Object
Apply delayed options and remove them from the queue
87 88 89 90 91 92 |
# File 'lib/terminitor/cores/iterm_core.rb', line 87 def @delayed_options.length.times do option = @delayed_options.shift option[:object].instance_eval(option[:option]).set(option[:value]) end end |
#set_options(object, options = {}) ⇒ Object
Sets options of the given object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/terminitor/cores/iterm_core.rb', line 56 def (object, = {}) .each_pair do |option, value| case option when :settings # works for windows and tabs, for example :settings => "Grass" begin object.current_settings.set(@terminal.settings_sets[value]) rescue Appscript::CommandError => e puts "Error: invalid settings set '#{value}'" end when :bounds # works only for windows, for example :bounds => [10,20,300,200] # the only working sequence to restore window size and position! object.bounds.set(value) object.frame.set(value) object.position.set(value) when :selected # works for tabs, for example tab :active => true delayed_option(option, value, object) when :miniaturized # works for windows only delayed_option(option, value, object) when :name # ignore it. else # trying to apply any other option begin object.instance_eval(option.to_s).set(value) rescue puts "Error setting #{option} = #{value} on #{object.inspect}" end end end end |
#split_h ⇒ Object
199 200 201 |
# File 'lib/terminitor/cores/iterm_core.rb', line 199 def split_h call_ui_action("Shell", nil, "Split Horizontally With Same Profile") end |
#split_v ⇒ Object
195 196 197 |
# File 'lib/terminitor/cores/iterm_core.rb', line 195 def split_v call_ui_action("Shell", nil, "Split Vertically With Same Profile") end |