terminitor 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +10 -0
- data/lib/terminitor.rb +3 -1
- data/lib/terminitor/capture/iterm_capture.rb +51 -0
- data/lib/terminitor/cli.rb +1 -1
- data/lib/terminitor/cores/iterm_core.rb +145 -0
- data/lib/terminitor/runner.rb +13 -2
- data/lib/terminitor/version.rb +1 -1
- data/test/cli_test.rb +2 -2
- data/test/cores/iterm_core_test.rb +67 -0
- data/test/runner_test.rb +10 -2
- metadata +7 -4
data/README.md
CHANGED
@@ -296,6 +296,7 @@ Cores allow Terminitor to operate on a variety of platforms. They abstract the g
|
|
296
296
|
|
297
297
|
* MacCore - Mac OS X Terminal
|
298
298
|
* KonsoleCore - KDE Konsole
|
299
|
+
* ITermCore - Mac OS X iTerm
|
299
300
|
|
300
301
|
Feel free to contribute more cores so that Terminitor can support your terminal of choice :)
|
301
302
|
|
@@ -308,6 +309,13 @@ Limitations
|
|
308
309
|
Right now the Mac OS X Terminal tabs are created by invoking keystrokes which means there are limitations with the terminal being in
|
309
310
|
focus during execution of these commands. Obviously the long term goal is to solve this issue as well but in all honesty, this solution works well enough most of the time.
|
310
311
|
|
312
|
+
|
313
|
+
#### ITermCore ####
|
314
|
+
|
315
|
+
Currently the iTerm Core only provides basic functionality such as opening tabs, windows, and executing commands within them. The capture
|
316
|
+
and settings functionality will be integrated soon.
|
317
|
+
|
318
|
+
|
311
319
|
#### Fetching ####
|
312
320
|
|
313
321
|
The fetch task only pulls off Github repositories at the moment. Later on, this functionality will be extended to non github repository.
|
@@ -334,6 +342,8 @@ Thanks to the following people for their contributions so far:
|
|
334
342
|
* Alexey Kuleshov ([kulesa](https://github.com/kulesa)) for contributing the terminal settings and terminal settings capture functionality
|
335
343
|
* Arthur Gunn ([gunn](https://github.com/gunn)) for contributing a path to support tab syntax and load path.
|
336
344
|
* Elliot Winkler ([mcmire](https://github.com/mcmire)) for adding 1.8.6 compatiblity and ensuring tabs open in order.
|
345
|
+
* Justin Hilemen ([bobthecow](https://github.com/bobthecow)) for fixing the list command to remove the term extensions.
|
346
|
+
* recurser ([recurser](https://github.com/recurser)) for adding basic iTerm support.
|
337
347
|
|
338
348
|
Acknowledgements
|
339
349
|
-----------------
|
data/lib/terminitor.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
lib_dir = File.expand_path("..", __FILE__)
|
2
2
|
$:.unshift( lib_dir ) unless $:.include?( lib_dir )
|
3
|
-
|
3
|
+
|
4
4
|
require 'terminitor/yaml'
|
5
5
|
require 'terminitor/dsl'
|
6
6
|
require 'terminitor/runner'
|
@@ -15,6 +15,8 @@ module Terminitor
|
|
15
15
|
require 'appscript'
|
16
16
|
autoload :MacCore, 'terminitor/cores/mac_core'
|
17
17
|
autoload :MacCapture, 'terminitor/capture/mac_capture'
|
18
|
+
autoload :ItermCore, 'terminitor/cores/iterm_core'
|
19
|
+
autoload :ItermCapture, 'terminitor/capture/iterm_capture'
|
18
20
|
when %r{linux}
|
19
21
|
require 'dbus'
|
20
22
|
autoload :KonsoleCore, 'terminitor/cores/konsole_core'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Terminitor
|
2
|
+
# Captures terminal windows and tabs for Mac OS X
|
3
|
+
class ItermCapture < AbstractCapture
|
4
|
+
include Appscript
|
5
|
+
|
6
|
+
# Defines what options of window or tab to capture and how
|
7
|
+
# just in case we'll need to get other properties
|
8
|
+
OPTIONS_MASK = {
|
9
|
+
:window => {
|
10
|
+
:bounds => "bounds"
|
11
|
+
},
|
12
|
+
:tab => {
|
13
|
+
:settings => "current_settings.name"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
# Initialize @terminal with Terminal.app, Load the Windows, store the Termfile
|
18
|
+
# Terminitor::MacCore.new('/path')
|
19
|
+
def initialize
|
20
|
+
@terminal = app('iTerm.app')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns settings of currently opened windows and tabs.
|
24
|
+
def capture_windows
|
25
|
+
windows = []
|
26
|
+
# for some reason terminal.windows[] contain duplicated elements
|
27
|
+
@terminal.windows.get.uniq.each do |window|
|
28
|
+
if window.visible.get
|
29
|
+
tabs = window.tabs.get.inject([]) do |tabs, tab|
|
30
|
+
tabs << {:options => object_options(tab)}
|
31
|
+
end
|
32
|
+
windows << {:options => object_options(window), :tabs => tabs}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
windows
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns hash of options of window or tab
|
39
|
+
def object_options(object)
|
40
|
+
options = {}
|
41
|
+
class_ = object.class_.get
|
42
|
+
if class_ && OPTIONS_MASK[class_]
|
43
|
+
OPTIONS_MASK[class_].each_pair do |option, getter|
|
44
|
+
value = object.instance_eval(getter).get
|
45
|
+
options[option] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
options
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/terminitor/cli.rb
CHANGED
@@ -30,7 +30,7 @@ module Terminitor
|
|
30
30
|
def list
|
31
31
|
say "Global scripts: \n"
|
32
32
|
Dir.glob("#{ENV['HOME']}/.terminitor/*").each do |file|
|
33
|
-
say " * #{File.basename(file
|
33
|
+
say " * #{File.basename(file, '.term')} #{grab_comment_for_file(file)}"
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Terminitor
|
2
|
+
# Mac OS X Core for Terminitor
|
3
|
+
# This Core manages all the interaction with Appscript and the Terminal
|
4
|
+
class ItermCore < AbstractCore
|
5
|
+
include Appscript
|
6
|
+
|
7
|
+
ALLOWED_OPTIONS = {
|
8
|
+
:window => [:bounds, :visible, :miniaturized],
|
9
|
+
:tab => [:settings, :selected]
|
10
|
+
}
|
11
|
+
|
12
|
+
# Initialize @terminal with Terminal.app, Load the Windows, store the Termfile
|
13
|
+
# Terminitor::MacCore.new('/path')
|
14
|
+
def initialize(path)
|
15
|
+
super
|
16
|
+
@terminal = app('iTerm')
|
17
|
+
@windows = @terminal.terminals
|
18
|
+
@delayed_options = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# executes the given command via appscript
|
22
|
+
# execute_command 'cd /path/to', :in => #<tab>
|
23
|
+
def execute_command(cmd, options = {})
|
24
|
+
if options[:in]
|
25
|
+
options[:in].write(:text => "#{cmd}")
|
26
|
+
else
|
27
|
+
active_window.write(:text => "#{cmd}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Opens a new tab and returns itself.
|
32
|
+
# TODO : handle options (?)
|
33
|
+
def open_tab(options = nil)
|
34
|
+
session = current_terminal.sessions.end.make( :new => :session )
|
35
|
+
session.exec(:command => ENV['SHELL'])
|
36
|
+
session
|
37
|
+
end
|
38
|
+
|
39
|
+
# Opens A New Window, applies settings to the first tab and returns the tab object.
|
40
|
+
# TODO : handle options (?)
|
41
|
+
def open_window(options = nil)
|
42
|
+
window = terminal.make( :new => :terminal )
|
43
|
+
session = window.sessions.end.make( :new => :session )
|
44
|
+
session.exec(:command => ENV['SHELL'])
|
45
|
+
session
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the Terminal Process
|
49
|
+
# We need this method to workaround appscript so that we can instantiate new tabs and windows.
|
50
|
+
# otherwise it would have looked something like window.make(:new => :tab) but that doesn't work.
|
51
|
+
def terminal_process
|
52
|
+
app("System Events").application_processes["iTerm.app"]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the last instantiated tab from active window
|
56
|
+
def return_last_tab
|
57
|
+
current_terminal.sessions.last.get rescue false
|
58
|
+
end
|
59
|
+
|
60
|
+
# returns the active windows
|
61
|
+
def active_window
|
62
|
+
current_terminal.current_session.get
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the current terminal
|
66
|
+
def current_terminal
|
67
|
+
@terminal.current_terminal
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sets options of the given object
|
71
|
+
def set_options(object, options = {})
|
72
|
+
options.each_pair do |option, value|
|
73
|
+
case option
|
74
|
+
when :settings # works for windows and tabs, for example :settings => "Grass"
|
75
|
+
begin
|
76
|
+
object.current_settings.set(@terminal.settings_sets[value])
|
77
|
+
rescue Appscript::CommandError => e
|
78
|
+
puts "Error: invalid settings set '#{value}'"
|
79
|
+
end
|
80
|
+
when :bounds # works only for windows, for example :bounds => [10,20,300,200]
|
81
|
+
# the only working sequence to restore window size and position!
|
82
|
+
object.bounds.set(value)
|
83
|
+
object.frame.set(value)
|
84
|
+
object.position.set(value)
|
85
|
+
when :selected # works for tabs, for example tab :active => true
|
86
|
+
delayed_option(option, value, object)
|
87
|
+
when :miniaturized # works for windows only
|
88
|
+
delayed_option(option, value, object)
|
89
|
+
when :name
|
90
|
+
# ignore it.
|
91
|
+
else # trying to apply any other option
|
92
|
+
begin
|
93
|
+
object.instance_eval(option.to_s).set(value)
|
94
|
+
rescue
|
95
|
+
puts "Error setting #{option} = #{value} on #{object.inspect}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Apply delayed options and remove them from the queue
|
102
|
+
def set_delayed_options
|
103
|
+
@delayed_options.length.times do
|
104
|
+
option = @delayed_options.shift
|
105
|
+
option[:object].instance_eval(option[:option]).set(option[:value])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# These methods are here for reference so I can ponder later
|
112
|
+
# how I could possibly use them.
|
113
|
+
# And Currently aren't tested. =(
|
114
|
+
|
115
|
+
# returns a window by the id
|
116
|
+
def window_by_id(id)
|
117
|
+
@windows.ID(id)
|
118
|
+
end
|
119
|
+
|
120
|
+
# grabs the window id.
|
121
|
+
def window_id(window)
|
122
|
+
window.id_.get
|
123
|
+
end
|
124
|
+
|
125
|
+
# set_window_title #<Window>, "hi"
|
126
|
+
# Note: This sets all the windows to the same title.
|
127
|
+
def set_window_title(window, title)
|
128
|
+
window.custom_title.set(title)
|
129
|
+
end
|
130
|
+
|
131
|
+
# selects options allowed for window or tab
|
132
|
+
def allowed_options(object_type, options)
|
133
|
+
Hash[ options.select {|option, value| ALLOWED_OPTIONS[object_type].include?(option) }]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Add option to the list of delayed options
|
137
|
+
def delayed_option(option, value, object)
|
138
|
+
@delayed_options << {
|
139
|
+
:option => option.to_s,
|
140
|
+
:value => value,
|
141
|
+
:object => object
|
142
|
+
}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/terminitor/runner.rb
CHANGED
@@ -6,7 +6,12 @@ module Terminitor
|
|
6
6
|
# find_core RUBY_PLATFORM
|
7
7
|
def find_core(platform)
|
8
8
|
core = case platform.downcase
|
9
|
-
when %r{darwin} then
|
9
|
+
when %r{darwin} then
|
10
|
+
if ENV['TERM_PROGRAM'] == 'iTerm.app'
|
11
|
+
Terminitor::ItermCore
|
12
|
+
else
|
13
|
+
Terminitor::MacCore
|
14
|
+
end
|
10
15
|
when %r{linux} then Terminitor::KonsoleCore # TODO check for gnome and others
|
11
16
|
else nil
|
12
17
|
end
|
@@ -15,7 +20,12 @@ module Terminitor
|
|
15
20
|
# Defines how to capture terminal settings on the specified platform
|
16
21
|
def capture_core(platform)
|
17
22
|
core = case platform.downcase
|
18
|
-
when %r{darwin} then
|
23
|
+
when %r{darwin} then
|
24
|
+
if ENV['TERM_PROGRAM'] == 'iTerm.app'
|
25
|
+
Terminitor::ItermCapture
|
26
|
+
else
|
27
|
+
Terminitor::MacCapture
|
28
|
+
end
|
19
29
|
when %r{linux} then Terminitor::KonsoleCapture # TODO check for gnome and others
|
20
30
|
else nil
|
21
31
|
end
|
@@ -109,4 +119,5 @@ module Terminitor
|
|
109
119
|
end
|
110
120
|
|
111
121
|
end
|
122
|
+
|
112
123
|
end
|
data/lib/terminitor/version.rb
CHANGED
data/test/cli_test.rb
CHANGED
@@ -23,8 +23,8 @@ context "Terminitor" do
|
|
23
23
|
File.open(File.join(@path,'bar.yml'),"w") { |f| f.puts @template }
|
24
24
|
capture(:stdout) { Terminitor::Cli.start(['list']) }
|
25
25
|
end
|
26
|
-
asserts_topic.matches %r{foo - COMMENT OF SCRIPT HERE}
|
27
|
-
asserts_topic.matches %r{bar - COMMENT OF SCRIPT HERE}
|
26
|
+
asserts_topic.matches %r{foo\.yml - COMMENT OF SCRIPT HERE}
|
27
|
+
asserts_topic.matches %r{bar\.yml - COMMENT OF SCRIPT HERE}
|
28
28
|
end
|
29
29
|
|
30
30
|
asserts "#init creates .terminitor" do
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path('../../teststrap',__FILE__)
|
2
|
+
|
3
|
+
if platform?("darwin") # Only run test if it's darwin
|
4
|
+
context "ItermCore" do
|
5
|
+
setup do
|
6
|
+
any_instance_of(Terminitor::ItermCore) do |core|
|
7
|
+
stub(core).app('iTerm') { mock!.terminals { true } }
|
8
|
+
stub(core).load_termfile('/path/to') { true }
|
9
|
+
end
|
10
|
+
@iterm_core = Terminitor::ItermCore.new('/path/to')
|
11
|
+
end
|
12
|
+
|
13
|
+
asserts "#terminal_process calls System Events" do
|
14
|
+
core = topic.dup
|
15
|
+
mock(core).app('System Events') { mock!.application_processes.returns("iTerm.app" => true) }
|
16
|
+
core.terminal_process
|
17
|
+
end
|
18
|
+
|
19
|
+
context "#open_tab" do
|
20
|
+
|
21
|
+
should "return the current tab" do
|
22
|
+
core = topic.dup
|
23
|
+
mock(core).current_terminal.stub!.sessions.stub!.end.
|
24
|
+
stub!.make(:new => :session).stub!.
|
25
|
+
exec(:command => ENV['SHELL'])
|
26
|
+
core.open_tab
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#open_window" do
|
32
|
+
|
33
|
+
should "return the last tab" do
|
34
|
+
core = topic.dup
|
35
|
+
mock(core).terminal.stub!.make(:new=>:terminal).
|
36
|
+
stub!.sessions.stub!.end.stub!.make(:new=>:session).
|
37
|
+
stub!.exec(:command => ENV['SHELL'])
|
38
|
+
core.open_window
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
asserts "#return_last_tab returns the last tab" do
|
43
|
+
core = topic.dup
|
44
|
+
mock(core).current_terminal.stub!.sessions.stub!.
|
45
|
+
last.stub!.get.returns(true)
|
46
|
+
core.return_last_tab
|
47
|
+
end
|
48
|
+
|
49
|
+
asserts "#execute_command executes" do
|
50
|
+
core = topic.dup
|
51
|
+
mock(core).active_window.stub!.write(:text => "hasta").returns(true)
|
52
|
+
core.execute_command('hasta')
|
53
|
+
end
|
54
|
+
|
55
|
+
asserts "#active_window gives window" do
|
56
|
+
core = topic.dup
|
57
|
+
mock(core).current_terminal.stub!.current_session.stub!.get.returns(true)
|
58
|
+
core.active_window
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
else
|
63
|
+
context "itermCore" do
|
64
|
+
puts "Nothing to do, you are not on OSX"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/test/runner_test.rb
CHANGED
@@ -28,7 +28,11 @@ context "Runner" do
|
|
28
28
|
|
29
29
|
|
30
30
|
context "#find_core" do
|
31
|
-
|
31
|
+
if ENV['TERM_PROGRAM'] == 'iTerm.app'
|
32
|
+
should("have Darwin") { @test_runner.find_core('darwin') }.equals Terminitor::ItermCore
|
33
|
+
else
|
34
|
+
should("have Darwin") { @test_runner.find_core('darwin') }.equals Terminitor::MacCore
|
35
|
+
end
|
32
36
|
|
33
37
|
if platform?('linux') # TODO Gotta be a better way.
|
34
38
|
should("have KDE") { @test_runner.find_core('linux') }.equals Terminitor::KonsoleCore
|
@@ -36,7 +40,11 @@ context "Runner" do
|
|
36
40
|
end
|
37
41
|
|
38
42
|
context "#capture_core" do
|
39
|
-
|
43
|
+
if ENV['TERM_PROGRAM'] == 'iTerm.app'
|
44
|
+
should("have Darwin") { @test_runner.capture_core('darwin') }.equals Terminitor::ItermCapture
|
45
|
+
else
|
46
|
+
should("have Darwin") { @test_runner.capture_core('darwin') }.equals Terminitor::MacCapture
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
context "#open_in_editor" do
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Arthur Chiu
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01
|
18
|
+
date: 2011-02-01 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -142,9 +142,11 @@ files:
|
|
142
142
|
- lib/terminitor.rb
|
143
143
|
- lib/terminitor/abstract_capture.rb
|
144
144
|
- lib/terminitor/abstract_core.rb
|
145
|
+
- lib/terminitor/capture/iterm_capture.rb
|
145
146
|
- lib/terminitor/capture/konsole_capture.rb
|
146
147
|
- lib/terminitor/capture/mac_capture.rb
|
147
148
|
- lib/terminitor/cli.rb
|
149
|
+
- lib/terminitor/cores/iterm_core.rb
|
148
150
|
- lib/terminitor/cores/konsole_core.rb
|
149
151
|
- lib/terminitor/cores/mac_core.rb
|
150
152
|
- lib/terminitor/dsl.rb
|
@@ -158,6 +160,7 @@ files:
|
|
158
160
|
- test/abstract_core_test.rb
|
159
161
|
- test/capture/mac_capture_test.rb
|
160
162
|
- test/cli_test.rb
|
163
|
+
- test/cores/iterm_core_test.rb
|
161
164
|
- test/cores/konsole_core_test.rb
|
162
165
|
- test/cores/mac_core_test.rb
|
163
166
|
- test/dsl_test.rb
|