Class: Consular::ITerm

Inherits:
Core
  • Object
show all
Includes:
Appscript
Defined in:
lib/consular/iterm.rb

Overview

Consular Core to interact with iTerm2 for Mac OS X

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ ITerm

Initializes a reference to the iTerm.app via appscript

Parameters:

  • path (String)

    Path to Termfile



39
40
41
42
# File 'lib/consular/iterm.rb', line 39

def initialize(path)
  super
  @terminal = app('iTerm')
end

Class Method Details

.to_sObject

Returns the name of Core. Used in CLI core selection.



27
28
29
# File 'lib/consular/iterm.rb', line 27

def to_s
  "Consular::ITerm Mac OSX iTerm2"
end

.valid_system?Boolean

Checks to see if the current system is darwin and if $TERM_PROGRAM is iTerm.app

Returns:

  • (Boolean)


20
21
22
# File 'lib/consular/iterm.rb', line 20

def valid_system?
  (RUBY_PLATFORM.downcase =~ /darwin/) && ENV['TERM_PROGRAM'] == 'iTerm.app'
end

Instance Method Details

#active_tabObject

Returns the active tab e.g the active terminal session.



292
293
294
# File 'lib/consular/iterm.rb', line 292

def active_tab
  active_window.current_session
end

#active_windowObject

Returns the active window/tab e.g the active terminal window.



299
300
301
# File 'lib/consular/iterm.rb', line 299

def active_window
  @terminal.current_terminal
end

#call_ui_action(menu, submenu, action) ⇒ Object

Execute the menu action via UI.

Examples:

@core.call_ui_action 'Edit', 'Find', 'Find Next'
@core.call_ui_action 'Shell', nil, 'Split Vertically With Same Profile'

Parameters:

  • menu (String)

    Top level menu name

  • submenu (String)

    Sub level menu name

  • action (String)

    Action name/description.



325
326
327
328
329
# File 'lib/consular/iterm.rb', line 325

def call_ui_action(menu, submenu, action)
  menu = iterm_menu.menu_bar_items[menu].menus[menu]
  menu = menu.menu_items[submenu].menus[submenu] if submenu
  menu.menu_items[action].click
end

#execute_command(cmd, options = {}) ⇒ Object

Execute the given command in the context of the active window.

Examples:

@osx.execute_command 'ps aux', :in => @tab_object

Parameters:

  • cmd (String)

    The command to execute.

  • options (Hash) (defaults to: {})

    Additional options to pass into appscript for the context.



284
285
286
287
# File 'lib/consular/iterm.rb', line 284

def execute_command(cmd, options = {})
  context = options[:in] || active_tab
  context.write :text => cmd
end

#execute_pane_commands(pane_commands, tab_commands) ⇒ Object

Execute the commands within a pane

Parameters:

  • pane_commands (Array)

    Commands for the designated pane.

  • tab_commands (Array)

    Commands for the designated tabs.



214
215
216
217
# File 'lib/consular/iterm.rb', line 214

def execute_pane_commands(pane_commands, tab_commands)
  pane_commands = (tab_commands || []) + (pane_commands || [])
  pane_commands.each { |cmd| execute_command cmd }
end

#execute_panes(content) ⇒ Object

Execute the tab and associated panes with the designated content

Parameters:

  • content (Hash)

    The Context containing panes.



154
155
156
157
158
# File 'lib/consular/iterm.rb', line 154

def execute_panes(content)
  panes    = content[:panes]
  commands = content[:tabs][:commands]
  top_level_pane_split panes, commands
end

#execute_subpanes(subpanes, tab_commands) ⇒ Object

Execute commands in the context of sub panes

Parameters:

  • subpanes (Array)

    Sub panes for the top level pane

  • tabcommands (Array)

    Tab commands



197
198
199
200
201
202
203
204
# File 'lib/consular/iterm.rb', line 197

def execute_subpanes(subpanes, tab_commands)
  subpanes.keys.sort.each do |subpane_key|
    subpane_commands = subpanes[subpane_key][:commands]
    horizontal_split
    execute_pane_commands(subpane_commands, tab_commands)
    select_pane 'Right'
  end
end

#execute_window(content, options = {}) ⇒ Object

Executes the commands for each designated window. .run_windows will iterate through each of the tabs in sorted order to execute the tabs in the order they were set. The logic follows this:

If the content is for the 'default' window,
then use the current active window and generate the commands.

If the content is for a new window,
then generate a new window and activate the windows.

Otherwise, open a new tab and execute the commands.

Examples:

@core.execute_window contents, :default => true
@core.execute_window contents, :default => true

Parameters:

  • content (Hash)

    The hash contents of the window from the Termfile.

  • options (Hash) (defaults to: {})

    Addional options to pass. You can use:

    :default - Whether this is being run as the default window.
    


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/consular/iterm.rb', line 117

def execute_window(content, options = {})
  window_options = content[:options]
  tab_contents   = content[:tabs]
  first_run      = true

  tab_contents.keys.sort.each do |key|
    tab_content = tab_contents[key]
    tab_options = tab_content[:options] || {}
    tab_name    = tab_options[:name]

    tab =
      if first_run && !options[:default]
        open_window options.merge(window_options)
      else
        key == 'default' ? active_tab : open_tab(tab_options) && active_tab
      end
    set_title tab_name, tab

    first_run = false
    commands = prepend_befores tab_content[:commands], content[:before]

    if content.key? :panes
      commands.each { |cmd| execute_command cmd, :in => tab }
      execute_panes content
      content.delete :panes
    else
      commands.each { |cmd| execute_command cmd, :in => tab }
    end
  end
end

#horizontal_splitObject

Split the active tab with horizontal panes



229
230
231
# File 'lib/consular/iterm.rb', line 229

def horizontal_split
  call_ui_action "Shell", nil, "Split Horizontally with Current Profile"
end

#iterm_menuObject

Returns a reference to the iTerm menu bar.



306
307
308
309
# File 'lib/consular/iterm.rb', line 306

def iterm_menu
  _process = app("System Events").processes["iTerm"]
  _process.menu_bars.first
end

#open_tab(options = nil) ⇒ Object

Opens a new tab and focuses on it.

Parameters:

  • options (Hash) (defaults to: nil)

    Additional options to further customize the tab.



257
258
259
# File 'lib/consular/iterm.rb', line 257

def open_tab(options = nil)
  active_window.launch_ :session => 'New session'
end

#open_window(options = nil) ⇒ Object

Opens a new window and focuses on the new tab.

Parameters:

  • options (Hash) (defaults to: nil)

    Additional options to further customize the window.



268
269
270
271
# File 'lib/consular/iterm.rb', line 268

def open_window(options = nil)
  window = @terminal.make :new => :terminal
  window.launch_ :session => 'New session'
end

#prepend_befores(commands, befores = nil) ⇒ Array<String>

Prepends the :before commands to the current context’s commands if it exists.

Parameters:

  • commands (Array<String>)

    The current tab commands

  • befores (Array<String>) (defaults to: nil)

    The current window’s :befores

Returns:

  • (Array<String>)

    The current context commands with the :before commands prepended



73
74
75
76
77
78
79
# File 'lib/consular/iterm.rb', line 73

def prepend_befores(commands, befores = nil)
  unless befores.nil? || befores.empty?
    commands.insert(0, befores).flatten!
  else
    commands
  end
end

#process!Object

Method called by runner to execute Termfile.



54
55
56
57
58
59
# File 'lib/consular/iterm.rb', line 54

def process!
  windows = @termfile[:windows]
  default = windows.delete('default')
  execute_window(default, :default => true) unless default[:tabs].empty?
  windows.each_pair { |_, cont| execute_window(cont) }
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

Parameters:

  • direction (String)

    Direction to split the pane. The valid directions are: ‘Above’, ‘Below’, ‘Left’, ‘Right’



241
242
243
244
245
246
247
248
# File 'lib/consular/iterm.rb', line 241

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_title(title, tab) ⇒ Object

Prepend a title setting command prior to the other commands.

Parameters:

  • The (String)

    tab title.

  • The (Appscript::Reference)

    tab instance resulting from #open_tab.



89
90
91
# File 'lib/consular/iterm.rb', line 89

def set_title(title, tab)
  tab.name.set(title) if title
end

#setup!Object

Method called by runner to Execute Termfile setup.



47
48
49
# File 'lib/consular/iterm.rb', line 47

def setup!
  @termfile[:setup].each { |cmd| execute_command(cmd) }
end

#top_level_pane_split(panes, commands) ⇒ Object

Execute commands in the context of a top level pane

Parameters:

  • panes (Hash)

    Pane contexts.

  • commands (Array)

    Current context tab commands.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/consular/iterm.rb', line 168

def top_level_pane_split(panes, commands)
  first_pane      = true

  panes.keys.sort.each do |pane_key|
    pane_content  = panes[pane_key]
    pane_commands = pane_content[:commands]

    vertical_split if first_pane
    execute_pane_commands(pane_commands,commands)

    if pane_content.key?(:panes)
      select_pane('Left') if first_pane
      execute_subpanes pane_content[:panes], commands
      pane_content.delete :panes
    end

    first_pane = false if first_pane
  end

end

#vertical_splitObject

Split the active tab with vertical panes



222
223
224
# File 'lib/consular/iterm.rb', line 222

def vertical_split
  call_ui_action "Shell", nil, "Split Vertically with Current Profile"
end