termup 2.0.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +8 -2
- data/lib/templates/iterm_advanced.yml +2 -2
- data/lib/termup.rb +11 -1
- data/lib/termup/base.rb +24 -80
- data/lib/termup/cli.rb +11 -8
- data/lib/termup/iterm.rb +96 -0
- data/lib/termup/process.rb +40 -0
- data/lib/termup/terminal.rb +32 -0
- data/lib/termup/version.rb +1 -1
- data/termup.gemspec +7 -7
- metadata +22 -27
- data/lib/termup/handler.rb +0 -111
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8702c31b85da161fafb1b949d630708e70502a61
|
4
|
+
data.tar.gz: 750ecb147eafa0f15e370dd9fb0116f0dcd3451d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95d9c08e02a3db81ecf7b6b220835b2a8271b889d501ff836b3f22181542547f554ad298f42fd6c2703779b0fb776728575b64e12d1a1b984b9437df19fdb87e
|
7
|
+
data.tar.gz: 06d58b6a0a0576dadde3cc187385bdf269a4ee48f191cc300279d32ef690c5e41711307a3deb5756a853d2b58a84f6e34017acb359d0a2821a233a8b615773cb
|
data/README.md
CHANGED
@@ -5,11 +5,12 @@ Automate opening up terminal tabs (or split panes) with a set of routine command
|
|
5
5
|
|
6
6
|
It's the easiest way to get started for your projects every day.
|
7
7
|
|
8
|
-
Compatible with Terminal.app and
|
8
|
+
Compatible with Terminal.app and iTerm2 v3 on OSX Yosemite or later.
|
9
9
|
|
10
10
|

|
11
11
|
|
12
|
-
**
|
12
|
+
**For iTerm2 v2 or earlier:** Termup 3.0 and up is not compatible with iTerm2 v2. Install Termup 2 by `gem install termup -v=2.0.3`
|
13
|
+
**For iTerm 1:** Termup 2.0 and up is not compatible with iTerm 1. Install 1.3.1 by `gem install termup -v=1.3.1`
|
13
14
|
|
14
15
|
Installation
|
15
16
|
------------
|
@@ -20,6 +21,11 @@ $ gem install termup
|
|
20
21
|
|
21
22
|
Note that you need to prepend `sudo` if you're using the OSX pre-installed Ruby.
|
22
23
|
|
24
|
+
Changelog
|
25
|
+
---------
|
26
|
+
|
27
|
+
Termup v3.0 is a complete rewrite using the new JavaScript for Automation which was introduced with OSX Yosemite.
|
28
|
+
|
23
29
|
Usage
|
24
30
|
-----
|
25
31
|
|
data/lib/termup.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'pathname'
|
3
|
+
require 'execjs/runtimes/jxa'
|
4
|
+
|
5
|
+
ExecJS.runtime = ExecJS::Runtimes::JXA
|
6
|
+
|
1
7
|
module Termup
|
8
|
+
Dir = Pathname.new(ENV['HOME']).join('.config/termup')
|
9
|
+
|
2
10
|
autoload :Base, 'termup/base'
|
3
11
|
autoload :Cli, 'termup/cli'
|
4
|
-
autoload :
|
12
|
+
autoload :Iterm, 'termup/iterm'
|
13
|
+
autoload :Process, 'termup/process'
|
14
|
+
autoload :Terminal, 'termup/terminal'
|
5
15
|
end
|
data/lib/termup/base.rb
CHANGED
@@ -1,90 +1,34 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
1
|
module Termup
|
4
2
|
class Base
|
5
|
-
def initialize(project)
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
@
|
10
|
-
|
11
|
-
# Config file compatibility checking
|
12
|
-
if @tabs.is_a?(Array) and @tabs.first.is_a?(Hash)
|
13
|
-
abort 'YAML syntax for config has been changed. See https://github.com/kenn/termup for details.'
|
14
|
-
end
|
15
|
-
|
16
|
-
@options = config['options'] || {}
|
17
|
-
@iterm_options = @options['iterm']
|
18
|
-
|
19
|
-
# Split panes for iTerm 2
|
20
|
-
split_panes if @handler.iterm? and @iterm_options
|
21
|
-
|
22
|
-
# Setting up tabs / panes
|
23
|
-
@tabs.each_with_index do |(tabname, values), index|
|
24
|
-
# Set tab title
|
25
|
-
@handler.set_property(:name, tabname)
|
26
|
-
|
27
|
-
# Run commands
|
28
|
-
(advanced_iterm? ? values['commands'] : values).each do |command|
|
29
|
-
@handler.run command
|
30
|
-
end
|
31
|
-
|
32
|
-
# Layout
|
33
|
-
if advanced_iterm?
|
34
|
-
values['properties'].each do |key, value|
|
35
|
-
@handler.set_property(key, value)
|
36
|
-
end if values['properties']
|
37
|
-
|
38
|
-
values['layout'].each do |command|
|
39
|
-
layout command
|
40
|
-
end if values['layout']
|
41
|
-
else
|
42
|
-
# Move to next
|
43
|
-
if @iterm_options
|
44
|
-
layout :goto_next_pane
|
45
|
-
else
|
46
|
-
if index < @tabs.size - 1
|
47
|
-
layout :new_tab
|
48
|
-
sleep 0.01 # Allow some time to complete opening a new tab
|
49
|
-
else
|
50
|
-
layout :goto_next_tab # Back home
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
3
|
+
def initialize(project, process)
|
4
|
+
@config = YAML.load_file(Termup::Dir.join("#{project}.yml"))
|
5
|
+
@options = @config['options'] || {}
|
6
|
+
@tabs = @config['tabs'] || {}
|
7
|
+
@process = process
|
8
|
+
@lines = []
|
55
9
|
end
|
56
10
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
width.times do
|
66
|
-
(height - 1).times do
|
67
|
-
layout :split_horizontally
|
68
|
-
end
|
69
|
-
layout :goto_next_pane # Move to next, or back home
|
70
|
-
end
|
11
|
+
def start
|
12
|
+
script = <<-JS
|
13
|
+
var app = Application(#{@process.pid});
|
14
|
+
var se = Application('System Events');
|
15
|
+
app.activate();
|
16
|
+
#{@lines.join(';')}
|
17
|
+
JS
|
18
|
+
ExecJS.exec script
|
71
19
|
end
|
72
20
|
|
73
|
-
|
74
|
-
unless defined?(@advanced_iterm)
|
75
|
-
@advanced_iterm = case @tabs.values.first
|
76
|
-
when Hash then true
|
77
|
-
when Array then false
|
78
|
-
else
|
79
|
-
abort 'invalid YAML format'
|
80
|
-
end
|
81
|
-
abort 'advanced config only supported for iTerm' if @advanced_iterm and !@handler.iterm?
|
82
|
-
end
|
83
|
-
@advanced_iterm
|
84
|
-
end
|
21
|
+
protected
|
85
22
|
|
86
|
-
def
|
87
|
-
|
23
|
+
def hit(key, *using)
|
24
|
+
# activate
|
25
|
+
using = using.map{|i| i.to_s.gsub(/_/,' ') }
|
26
|
+
case key
|
27
|
+
when Integer
|
28
|
+
@lines << "se.keyCode(#{key}, { using: #{using} })"
|
29
|
+
when String
|
30
|
+
@lines << "se.keystroke('#{key}', { using: #{using} })"
|
31
|
+
end
|
88
32
|
end
|
89
33
|
end
|
90
34
|
end
|
data/lib/termup/cli.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'thor'
|
2
2
|
|
3
3
|
module Termup
|
4
|
-
TERMUP_DIR = File.join(ENV['HOME'],'.config','termup')
|
5
|
-
|
6
4
|
class Cli < Thor
|
7
5
|
include Thor::Actions
|
8
6
|
|
@@ -26,8 +24,8 @@ module Termup
|
|
26
24
|
|
27
25
|
desc 'edit PROJECT', 'Edit termup project (Shortcut: e)'
|
28
26
|
def edit(project)
|
29
|
-
unless
|
30
|
-
empty_directory
|
27
|
+
unless path(project).exist?
|
28
|
+
empty_directory Termup::Dir
|
31
29
|
if options['iterm_advanced']
|
32
30
|
template 'templates/iterm_advanced.yml', path(project)
|
33
31
|
elsif options['iterm_basic']
|
@@ -42,20 +40,25 @@ module Termup
|
|
42
40
|
|
43
41
|
desc 'list', 'List termup projects (Shortcut: l)'
|
44
42
|
def list
|
45
|
-
projects = Dir
|
43
|
+
projects = Pathname.glob(Termup::Dir.join('*.yml')).map{|f| f.basename('.yml') }
|
46
44
|
say "Your projects: #{projects.join(', ')}"
|
47
45
|
end
|
48
46
|
|
49
47
|
desc 'start PROJECT', 'Start termup project (Shortcut: s)'
|
50
48
|
def start(project)
|
51
|
-
say "project \"#{project}\" doesn't exist!" and return unless
|
52
|
-
Termup::
|
49
|
+
say "project \"#{project}\" doesn't exist!" and return unless path(project).exist?
|
50
|
+
process = Termup::Process.new
|
51
|
+
if process.iterm?
|
52
|
+
Termup::Iterm.new(project, process).start
|
53
|
+
else
|
54
|
+
Termup::Terminal.new(project, process).start
|
55
|
+
end
|
53
56
|
end
|
54
57
|
|
55
58
|
protected
|
56
59
|
|
57
60
|
def path(project)
|
58
|
-
"#{
|
61
|
+
Termup::Dir.join("#{project}.yml")
|
59
62
|
end
|
60
63
|
end
|
61
64
|
end
|
data/lib/termup/iterm.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Termup
|
2
|
+
class Iterm < Base
|
3
|
+
def start
|
4
|
+
split_panes if @options['iterm']
|
5
|
+
|
6
|
+
# Setting up tabs
|
7
|
+
@tabs.each.with_index do |(tabname, values), index|
|
8
|
+
set_property(:name, tabname) # Set tab title
|
9
|
+
|
10
|
+
if advanced_iterm?
|
11
|
+
values['commands'].each do |command|
|
12
|
+
run(command)
|
13
|
+
end
|
14
|
+
|
15
|
+
values['properties'].each do |key, value|
|
16
|
+
set_property(key, value)
|
17
|
+
end if values['properties']
|
18
|
+
|
19
|
+
values['layout'].each do |command|
|
20
|
+
layout command
|
21
|
+
end if values['layout']
|
22
|
+
else
|
23
|
+
values.each do |command|
|
24
|
+
run(command)
|
25
|
+
end
|
26
|
+
|
27
|
+
layout :goto_next_pane
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def split_panes
|
37
|
+
width, height = @options['iterm']['width'], @options['iterm']['height']
|
38
|
+
return unless width && height
|
39
|
+
|
40
|
+
(width - 1).times do
|
41
|
+
layout :split_vertically
|
42
|
+
end
|
43
|
+
layout :goto_next_pane # Back home
|
44
|
+
width.times do
|
45
|
+
(height - 1).times do
|
46
|
+
layout :split_horizontally
|
47
|
+
end
|
48
|
+
layout :goto_next_pane # Move to next, or back home
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def run(command)
|
53
|
+
@lines << "app.currentWindow().currentSession().write({'text':'#{command}'})"
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_property(key, value)
|
57
|
+
value = value.inspect if value.is_a?(String)
|
58
|
+
@lines << "app.currentWindow().currentSession().#{camelize(key)}.set(#{value})"
|
59
|
+
end
|
60
|
+
|
61
|
+
def advanced_iterm?
|
62
|
+
unless defined?(@advanced_iterm)
|
63
|
+
@advanced_iterm = case @tabs.values.first
|
64
|
+
when Hash then true
|
65
|
+
when Array then false
|
66
|
+
else
|
67
|
+
abort 'invalid YAML format'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@advanced_iterm
|
71
|
+
end
|
72
|
+
|
73
|
+
def camelize(string)
|
74
|
+
string.to_s.split('_').map.with_index{|s,index| index.zero? ? s : s.slice(0).upcase + s.slice(1..-1) }.join
|
75
|
+
end
|
76
|
+
|
77
|
+
def layout(command)
|
78
|
+
case command.to_sym
|
79
|
+
when :new_tab then hit 't', :command_down
|
80
|
+
when :close_tab then hit 'w', :command_down
|
81
|
+
when :goto_previous_tab then hit '[', :command_down, :shift_down
|
82
|
+
when :goto_next_tab then hit ']', :command_down, :shift_down
|
83
|
+
when :goto_previous_pane then hit '[', :command_down
|
84
|
+
when :goto_next_pane then hit ']', :command_down
|
85
|
+
when :split_vertically then hit 'd', :command_down
|
86
|
+
when :split_horizontally then hit 'd', :command_down, :shift_down
|
87
|
+
when :go_left then hit 123, :command_down, :option_down
|
88
|
+
when :go_right then hit 124, :command_down, :option_down
|
89
|
+
when :go_down then hit 125, :command_down, :option_down
|
90
|
+
when :go_up then hit 126, :command_down, :option_down
|
91
|
+
else
|
92
|
+
abort "Unknown iTerm2.app command: #{command}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Termup
|
2
|
+
class Process
|
3
|
+
attr_reader :pid
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
lookup_pid
|
7
|
+
end
|
8
|
+
|
9
|
+
def terminal?
|
10
|
+
app_name == 'Terminal'
|
11
|
+
end
|
12
|
+
|
13
|
+
def iterm?
|
14
|
+
app_name == 'iTerm'
|
15
|
+
end
|
16
|
+
|
17
|
+
def app_name
|
18
|
+
@app_name ||= ExecJS.eval "Application(#{@pid}).name()"
|
19
|
+
end
|
20
|
+
|
21
|
+
def lookup_pid
|
22
|
+
pid = ::Process.ppid
|
23
|
+
pids = []
|
24
|
+
|
25
|
+
# Go up the process tree to find term-like process
|
26
|
+
while pid > 1 do
|
27
|
+
pids << pid if term_like_pids.include?(pid)
|
28
|
+
pid = `ps -p #{pid} -o ppid=`.strip.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
abort 'terminal pid not found!' if pids.empty?
|
32
|
+
|
33
|
+
@pid = pids.last
|
34
|
+
end
|
35
|
+
|
36
|
+
def term_like_pids
|
37
|
+
@term_like_pids ||= `ps x | grep Term`.split("\n").reject{|i| i =~ /grep/ }.map{|i| i.match(/\d+/).to_s.to_i }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Termup
|
2
|
+
class Terminal < Base
|
3
|
+
def start
|
4
|
+
# Setting up tabs / panes
|
5
|
+
@tabs.each.with_index do |(tabname, values), index|
|
6
|
+
values.each do |command|
|
7
|
+
@lines << "app.doScript('#{command}', { in: app.windows[0].tabs.last() })"
|
8
|
+
end
|
9
|
+
|
10
|
+
if index < @tabs.size - 1
|
11
|
+
layout :new_tab
|
12
|
+
sleep 0.01 # Allow some time to complete opening a new tab
|
13
|
+
else
|
14
|
+
layout :goto_next_tab # Back home
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def layout(command)
|
22
|
+
case command.to_sym
|
23
|
+
when :new_tab then hit 't', :command_down
|
24
|
+
when :close_tab then hit 'w', :command_down
|
25
|
+
when :goto_previous_tab then hit '[', :command_down, :shift_down
|
26
|
+
when :goto_next_tab then hit ']', :command_down, :shift_down
|
27
|
+
else
|
28
|
+
abort "Unknown Terminal.app command: #{command}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/termup/version.rb
CHANGED
data/termup.gemspec
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
require File.expand_path('../lib/termup/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = [
|
6
|
-
gem.email = [
|
5
|
+
gem.authors = ['Kenn Ejima']
|
6
|
+
gem.email = ['kenn.ejima@gmail.com']
|
7
7
|
gem.description = %q{Setup terminal tabs with preset commands for your projects}
|
8
8
|
gem.summary = %q{Setup terminal tabs with preset commands for your projects}
|
9
|
-
gem.homepage =
|
9
|
+
gem.homepage = 'https://github.com/kenn/termup'
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\).reject{|f| f =~ /^images/ } # Exclude images
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
-
gem.name =
|
15
|
-
gem.require_paths = [
|
14
|
+
gem.name = 'termup'
|
15
|
+
gem.require_paths = ['lib']
|
16
16
|
gem.version = Termup::VERSION
|
17
17
|
|
18
|
-
gem.
|
19
|
-
gem.
|
18
|
+
gem.add_dependency 'execjs-runtimes-jxa', '~> 0.1'
|
19
|
+
gem.add_dependency 'thor', '~> 0.16'
|
20
20
|
end
|
metadata
CHANGED
@@ -1,48 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: termup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 3.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Kenn Ejima
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-06-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
prerelease: false
|
14
|
+
name: execjs-runtimes-jxa
|
17
15
|
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
22
|
-
none: false
|
19
|
+
version: '0.1'
|
23
20
|
type: :runtime
|
21
|
+
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
23
|
requirements:
|
26
|
-
- - ~>
|
24
|
+
- - "~>"
|
27
25
|
- !ruby/object:Gem::Version
|
28
|
-
version: 0.
|
29
|
-
none: false
|
26
|
+
version: '0.1'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: thor
|
32
|
-
prerelease: false
|
33
29
|
requirement: !ruby/object:Gem::Requirement
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.16
|
38
|
-
none: false
|
33
|
+
version: '0.16'
|
39
34
|
type: :runtime
|
35
|
+
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
37
|
requirements:
|
42
|
-
- - ~>
|
38
|
+
- - "~>"
|
43
39
|
- !ruby/object:Gem::Version
|
44
|
-
version: 0.16
|
45
|
-
none: false
|
40
|
+
version: '0.16'
|
46
41
|
description: Setup terminal tabs with preset commands for your projects
|
47
42
|
email:
|
48
43
|
- kenn.ejima@gmail.com
|
@@ -51,7 +46,7 @@ executables:
|
|
51
46
|
extensions: []
|
52
47
|
extra_rdoc_files: []
|
53
48
|
files:
|
54
|
-
- .gitignore
|
49
|
+
- ".gitignore"
|
55
50
|
- Gemfile
|
56
51
|
- LICENSE
|
57
52
|
- README.md
|
@@ -63,32 +58,32 @@ files:
|
|
63
58
|
- lib/termup.rb
|
64
59
|
- lib/termup/base.rb
|
65
60
|
- lib/termup/cli.rb
|
66
|
-
- lib/termup/
|
61
|
+
- lib/termup/iterm.rb
|
62
|
+
- lib/termup/process.rb
|
63
|
+
- lib/termup/terminal.rb
|
67
64
|
- lib/termup/version.rb
|
68
65
|
- termup.gemspec
|
69
66
|
homepage: https://github.com/kenn/termup
|
70
67
|
licenses: []
|
68
|
+
metadata: {}
|
71
69
|
post_install_message:
|
72
70
|
rdoc_options: []
|
73
71
|
require_paths:
|
74
72
|
- lib
|
75
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
76
74
|
requirements:
|
77
|
-
- -
|
75
|
+
- - ">="
|
78
76
|
- !ruby/object:Gem::Version
|
79
77
|
version: '0'
|
80
|
-
none: false
|
81
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
79
|
requirements:
|
83
|
-
- -
|
80
|
+
- - ">="
|
84
81
|
- !ruby/object:Gem::Version
|
85
82
|
version: '0'
|
86
|
-
none: false
|
87
83
|
requirements: []
|
88
84
|
rubyforge_project:
|
89
|
-
rubygems_version:
|
85
|
+
rubygems_version: 2.5.1
|
90
86
|
signing_key:
|
91
|
-
specification_version:
|
87
|
+
specification_version: 4
|
92
88
|
summary: Setup terminal tabs with preset commands for your projects
|
93
89
|
test_files: []
|
94
|
-
has_rdoc:
|
data/lib/termup/handler.rb
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
require 'appscript'
|
2
|
-
|
3
|
-
module Termup
|
4
|
-
class Handler
|
5
|
-
def app(*args)
|
6
|
-
Appscript.app(*args)
|
7
|
-
end
|
8
|
-
|
9
|
-
def run(command)
|
10
|
-
if terminal?
|
11
|
-
app_process.do_script(command, :in => app_process.windows[1].tabs.last.get)
|
12
|
-
else
|
13
|
-
app_process.current_terminal.current_session.write(:text => command)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def set_property(key, value)
|
18
|
-
if iterm?
|
19
|
-
app_process.current_terminal.current_session.send(key).set(value)
|
20
|
-
else
|
21
|
-
# No-op for terminal for now
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def activate
|
26
|
-
app_process.activate
|
27
|
-
end
|
28
|
-
|
29
|
-
def hit(key, *using)
|
30
|
-
activate
|
31
|
-
case key
|
32
|
-
when Integer
|
33
|
-
app('System Events').processes[app_name].key_code key, using && { :using => using }
|
34
|
-
when String
|
35
|
-
app('System Events').processes[app_name].keystroke key, using && { :using => using }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def terminal?
|
40
|
-
app_name == 'Terminal'
|
41
|
-
end
|
42
|
-
|
43
|
-
def iterm?
|
44
|
-
app_name == 'iTerm'
|
45
|
-
end
|
46
|
-
|
47
|
-
def app_name
|
48
|
-
@app_name ||= app_process.name.get
|
49
|
-
end
|
50
|
-
|
51
|
-
def app_process
|
52
|
-
@app_process ||= app.by_pid(term_pid)
|
53
|
-
end
|
54
|
-
|
55
|
-
def term_pid
|
56
|
-
return @term_pid if @term_pid
|
57
|
-
|
58
|
-
pid = Process.ppid
|
59
|
-
|
60
|
-
# Go up the process tree to find term-like process
|
61
|
-
100.times do
|
62
|
-
ppid = `ps -p #{pid} -o ppid=`.strip.to_i
|
63
|
-
|
64
|
-
abort 'terminal pid not found!' if ppid == 1
|
65
|
-
|
66
|
-
if term_like_pids.include?(ppid)
|
67
|
-
@term_pid = ppid
|
68
|
-
break
|
69
|
-
end
|
70
|
-
|
71
|
-
pid = ppid
|
72
|
-
end
|
73
|
-
|
74
|
-
@term_pid
|
75
|
-
end
|
76
|
-
|
77
|
-
def term_like_pids
|
78
|
-
@term_like_pids ||= `ps x | grep Term`.split("\n").reject{|i| i =~ /grep/ }.map{|i| i.match(/\d+/).to_s.to_i }
|
79
|
-
end
|
80
|
-
|
81
|
-
def layout(command)
|
82
|
-
if iterm?
|
83
|
-
case command.to_sym
|
84
|
-
when :new_tab then hit 't', :command_down
|
85
|
-
when :close_tab then hit 'w', :command_down
|
86
|
-
when :goto_previous_tab then hit '[', :command_down, :shift_down
|
87
|
-
when :goto_next_tab then hit ']', :command_down, :shift_down
|
88
|
-
when :goto_previous_pane then hit '[', :command_down
|
89
|
-
when :goto_next_pane then hit ']', :command_down
|
90
|
-
when :split_vertically then hit 'd', :command_down
|
91
|
-
when :split_horizontally then hit 'd', :command_down, :shift_down
|
92
|
-
when :go_left then hit 123, :command_down, :option_down
|
93
|
-
when :go_right then hit 124, :command_down, :option_down
|
94
|
-
when :go_down then hit 125, :command_down, :option_down
|
95
|
-
when :go_up then hit 126, :command_down, :option_down
|
96
|
-
else
|
97
|
-
abort "Unknown iTerm2.app command: #{command}"
|
98
|
-
end
|
99
|
-
else
|
100
|
-
case command.to_sym
|
101
|
-
when :new_tab then hit 't', :command_down
|
102
|
-
when :close_tab then hit 'w', :command_down
|
103
|
-
when :goto_previous_tab then hit '[', :command_down, :shift_down
|
104
|
-
when :goto_next_tab then hit ']', :command_down, :shift_down
|
105
|
-
else
|
106
|
-
abort "Unknown Terminal.app command: #{command}"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|