itermwindow 0.4.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.
- data/CHANGELOG.md +6 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/bin/iterm-window +6 -0
- data/lib/iterm_window.rb +298 -0
- metadata +95 -0
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009 Chris Powers
|
2
|
+
Copyright (c) 2011 John Bintz
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# iTermWindow
|
2
|
+
|
3
|
+
*Make iTerm obey your command! Start up your complex development environment quickly and easily.*
|
4
|
+
|
5
|
+
The typical Rails project requires three or tour terminal windows/tabs open at once:
|
6
|
+
|
7
|
+
* The Rails app itself running using `rails s`
|
8
|
+
* Two continuous testing environments, powered by Guard or Autotest, running on your Ruby and JavaScript code
|
9
|
+
* A console ready for committing code or other maintenance tasks
|
10
|
+
* A log file or two
|
11
|
+
|
12
|
+
Opening all the necessary terminals, starting the right processes in each, and making them easily identifiable
|
13
|
+
is a long, slow process when done by hand. But guess what -- computers can be used to automate processes that
|
14
|
+
otherwise would be laborious when done manually!
|
15
|
+
|
16
|
+
Enter *iTermWindow*, a terminal window/tab multiplexer and command runner for Mac OS X and iTerm, the really
|
17
|
+
awesome Terminal.app replacement. iTerm's scriptability and customization allows one to create complex
|
18
|
+
project configurations for one's terminal setups.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
`gem install itermwindow` or add it to your Gemfile.
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
The `iterm-window` executable will open and run an `iTermfile` file in the current directory.
|
27
|
+
An `iTermfile` file looks like this:
|
28
|
+
|
29
|
+
``` ruby
|
30
|
+
open :dir => Dir.pwd do
|
31
|
+
default_tab :console
|
32
|
+
|
33
|
+
open_tab :rails, :color => :rails do
|
34
|
+
rails "s"
|
35
|
+
end
|
36
|
+
|
37
|
+
open_tab :rspec, :color => :rspec do
|
38
|
+
guard "-g rspec"
|
39
|
+
end
|
40
|
+
|
41
|
+
open_tab :log, :color => "DDB" do
|
42
|
+
tail "+F -fr log/sphinx.log"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
In a nutshell:
|
48
|
+
|
49
|
+
* `open` blocks open new iTerm windows.
|
50
|
+
* `current` blocks use the cirrent iTerm window.
|
51
|
+
* Inside `open` or `current` blocks you can open a new tab with `open_tab`.
|
52
|
+
* Specify a tab to be the selected tab with `default_tab`.
|
53
|
+
* Inside of a tab, you can write text into the terminal with `write_text`.
|
54
|
+
* Set the title of the tab with `set_title`.
|
55
|
+
* Or run a command magically (using `method_missing`).
|
56
|
+
|
57
|
+
`open_tab` and `default_tab` can take an options hash:
|
58
|
+
|
59
|
+
* `:dir` changes to the given directory before executing commands.
|
60
|
+
* `:color` changes the window chrome and tab color to the given hex code (3 or 6 hex digits) or built-in color. See ItermWindow.colors for the list of available colors.
|
61
|
+
|
62
|
+
`open` can also take an options hash:
|
63
|
+
|
64
|
+
* `:dir` changes all tabs to the given directory before executing commands.
|
65
|
+
|
66
|
+
More docs coming soon! Also, look at `lib/iterm_window.rb` for more usage examples.
|
67
|
+
|
68
|
+
* Developed March 17, 2008 by Chris Powers
|
69
|
+
* Extended June 2011 and beyond by John Bintz and (hopefully) many others
|
70
|
+
|
data/bin/iterm-window
ADDED
data/lib/iterm_window.rb
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
# Developed March 17, 2008 by Chris Powers
|
2
|
+
#
|
3
|
+
# The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
|
4
|
+
# Under the hood, this class is a wrapper of iTerm's Applescript scripting API. Methods are used to
|
5
|
+
# generate Applescript code which is run as an <tt>osascript</tt> command when the ItermWindow initialization
|
6
|
+
# block is closed.
|
7
|
+
#
|
8
|
+
# ItermWindow::Tab models a tab (session) in an iTerm terminal window and allows for it to be controlled by Ruby.
|
9
|
+
# These tabs can be created with either the ItermWindow#open_bookmark method or the ItermWindow#open_tab
|
10
|
+
# method. Each tab is given a name (symbol) by which it can be accessed later as a method of ItermWindow.
|
11
|
+
#
|
12
|
+
# EXAMPLE - Open a new iTerm window, cd to a project and open it in TextMate
|
13
|
+
#
|
14
|
+
# ItermWindow.open do
|
15
|
+
# open_tab :my_tab do
|
16
|
+
# write "cd ~/projects/my_project/trunk"
|
17
|
+
# write "mate ./"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# EXAMPLE - Use the current iTerm window, cd to a project and open in TextMate, launch the server and the console and title them
|
22
|
+
#
|
23
|
+
# ItermWindow.current do
|
24
|
+
# open_tab :project_dir do
|
25
|
+
# write "cd ~/projects/my_project/trunk"
|
26
|
+
# write "mate ./"
|
27
|
+
# set_title "MyProject Dir"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# open_tab :server do
|
31
|
+
# write "cd ~/projects/my_project/trunk"
|
32
|
+
# write "script/server -p 3005"
|
33
|
+
# set_title "MyProject Server"
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# open_tab :console do
|
37
|
+
# write "cd ~/projects/my_project/trunk"
|
38
|
+
# write "script/console"
|
39
|
+
# set_title "MyProject Console"
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# EXAMPLE - Same thing, but use bookmarks that were made for the server and console. Also, switch focus back to project dir.
|
44
|
+
#
|
45
|
+
# ItermWindow.current do
|
46
|
+
# open_tab :project_dir do
|
47
|
+
# write "cd ~/projects/my_project/trunk"
|
48
|
+
# write "mate ./"
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# open_bookmark :server, 'MyProject Server'
|
52
|
+
# open_bookmark :console, 'MyProject Console'
|
53
|
+
#
|
54
|
+
# project_dir.select
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# EXAMPLE - Arbitrarily open two tabs, switch between them and run methods/blocks with Tab#select method and Tab#write directly
|
58
|
+
#
|
59
|
+
# ItermWindow.open do
|
60
|
+
# open_tab :first_tab
|
61
|
+
# open_tab :second_tab
|
62
|
+
# first_tab.select do
|
63
|
+
# write 'cd ~/projects'
|
64
|
+
# write 'ls'
|
65
|
+
# end
|
66
|
+
# second_tab.write "echo 'hello there!'"
|
67
|
+
# first_tab.select # brings first tab back to focus
|
68
|
+
# end
|
69
|
+
|
70
|
+
require 'tempfile'
|
71
|
+
|
72
|
+
# The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
|
73
|
+
class ItermWindow
|
74
|
+
attr_reader :tab_color_files
|
75
|
+
|
76
|
+
class << self
|
77
|
+
def colors=(colors)
|
78
|
+
@colors = colors
|
79
|
+
end
|
80
|
+
|
81
|
+
def colors
|
82
|
+
@colors
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
ItermWindow.colors = {
|
87
|
+
:rails => 'F99',
|
88
|
+
:rspec => '99F',
|
89
|
+
:js => '9F9',
|
90
|
+
:doc => 'FF9',
|
91
|
+
:log => 'DFF',
|
92
|
+
}
|
93
|
+
|
94
|
+
# While you can directly use ItermWindow.new, using either ItermWindow.open or
|
95
|
+
# ItermWindow.current is the preferred method.
|
96
|
+
def initialize
|
97
|
+
@buffer = []
|
98
|
+
@tabs = {}
|
99
|
+
@tab_color_files = []
|
100
|
+
@default_tab = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.run_file(file)
|
104
|
+
instance_eval(file)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Creates a new terminal window, runs the block on it
|
108
|
+
def self.open(options = {}, &block)
|
109
|
+
self.new.run(:new, options, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Selects the first terminal window, runs the block on it
|
113
|
+
def self.current(&block)
|
114
|
+
self.new.run(:current, &block)
|
115
|
+
end
|
116
|
+
|
117
|
+
def run(window_type = :new, options = {}, &block)
|
118
|
+
@options = options
|
119
|
+
run_commands window_type, &block
|
120
|
+
send_output
|
121
|
+
end
|
122
|
+
|
123
|
+
# Creates a new tab from a bookmark, runs the block on it
|
124
|
+
def open_bookmark(name, bookmark, &block)
|
125
|
+
create_tab(name, bookmark, &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Creates a new tab from 'Default Session', runs the block on it
|
129
|
+
def open_tab(name, options = {}, &block)
|
130
|
+
create_tab(name, 'Default Session', options, &block)
|
131
|
+
@default_tab = name if options[:default]
|
132
|
+
end
|
133
|
+
|
134
|
+
def default_tab(name, options = {}, &block)
|
135
|
+
open_tab(name, options.merge(:default => true), &block)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Outputs a single line of Applescript code
|
139
|
+
def output(command)
|
140
|
+
@buffer << command.gsub("'", '"').gsub('\\', '\\\\\\')
|
141
|
+
end
|
142
|
+
|
143
|
+
def concatenated_buffer
|
144
|
+
@buffer.join("\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# Outputs @buffer to the command line as an osascript function
|
150
|
+
def send_output
|
151
|
+
shell_out
|
152
|
+
end
|
153
|
+
|
154
|
+
# Initializes the terminal window
|
155
|
+
def run_commands(window_type, &block)
|
156
|
+
window_types = {:new => '(make new terminal)', :current => 'first terminal'}
|
157
|
+
raise ArgumentError, "ItermWindow#run_commands should be passed :new or :current." unless window_types.keys.include? window_type
|
158
|
+
output "tell application 'iTerm'"
|
159
|
+
output "activate"
|
160
|
+
output "set myterm to #{window_types[window_type]}"
|
161
|
+
output "tell myterm"
|
162
|
+
self.instance_eval(&block) if block_given?
|
163
|
+
@tabs[@default_tab].select if @default_tab
|
164
|
+
output "end tell"
|
165
|
+
output "end tell"
|
166
|
+
end
|
167
|
+
|
168
|
+
# Creates a new Tab object, either default or from a bookmark,
|
169
|
+
# and creates a convenience method for retrieval
|
170
|
+
def create_tab(name, bookmark=nil, options = {}, &block)
|
171
|
+
@tabs[name] = Tab.new(self, name, bookmark, @options.merge(options), &block)
|
172
|
+
create_tab_convenience_method(name)
|
173
|
+
end
|
174
|
+
|
175
|
+
def create_tab_convenience_method(name)
|
176
|
+
(class << self; self; end).send(:define_method, name) do
|
177
|
+
@tabs[name]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def shell_out
|
182
|
+
Tempfile.open('iterm') do |f|
|
183
|
+
f.print concatenated_buffer
|
184
|
+
f.close
|
185
|
+
system %{osascript #{f.path}}
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
# The Tab class models a tab (session) in an iTerm terminal window and allows for it to be controlled by Ruby.
|
191
|
+
class Tab
|
192
|
+
|
193
|
+
attr_reader :name
|
194
|
+
attr_reader :bookmark
|
195
|
+
|
196
|
+
def initialize(window, name, bookmark = nil, options = {}, &block)
|
197
|
+
@name = name
|
198
|
+
@bookmark = bookmark
|
199
|
+
@window = window
|
200
|
+
@currently_executing_block = false
|
201
|
+
output "launch session '#{@bookmark}'"
|
202
|
+
# store tty id for later access
|
203
|
+
output "set #{name}_tty to the tty of the last session"
|
204
|
+
write "cd #{options[:dir]}" if options[:dir]
|
205
|
+
tab_color options[:color] if options[:color]
|
206
|
+
|
207
|
+
execute_block &block if block_given?
|
208
|
+
end
|
209
|
+
|
210
|
+
# Brings a tab into focus, runs a block on it if passed
|
211
|
+
def select(&block)
|
212
|
+
if block_given?
|
213
|
+
execute_block &block
|
214
|
+
else
|
215
|
+
output "select session id #{name}_tty"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Writes a command into the terminal tab
|
220
|
+
def write(command)
|
221
|
+
if @currently_executing_block
|
222
|
+
output "write text '#{command}'"
|
223
|
+
else
|
224
|
+
execute_block { write command }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Sets the title of the tab (ie the text on the iTerm tab itself)
|
229
|
+
def set_title(str)
|
230
|
+
if @currently_executing_block
|
231
|
+
output "set name to '#{str}'"
|
232
|
+
else
|
233
|
+
execute_block { set_title = str }
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Sets the title of the tab (ie the text on the iTerm tab itself)
|
238
|
+
def tab_color(color)
|
239
|
+
if @currently_executing_block
|
240
|
+
output "write text 'cat #{file = create_tab_color_file(color)} && rm #{file}'"
|
241
|
+
else
|
242
|
+
execute_block { tab_color(color) }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Runs a block on this tab with proper opening and closing statements
|
247
|
+
def execute_block(&block)
|
248
|
+
@currently_executing_block = true
|
249
|
+
output "tell session id #{name}_tty"
|
250
|
+
self.instance_eval(&block)
|
251
|
+
output "end tell"
|
252
|
+
@currently_executing_block = false
|
253
|
+
end
|
254
|
+
|
255
|
+
def method_missing(name, *args)
|
256
|
+
write("#{name} #{args.join(' ')}")
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.create_tab_color(color)
|
260
|
+
raise ArgumentError.new("bad hex color: #{color}") if color.downcase[%r{[^a-f0-9]}] || !([ 3, 6 ].include?(color.length))
|
261
|
+
%w{red green blue}.zip(color.scan(
|
262
|
+
(case color.length
|
263
|
+
when 3
|
264
|
+
/./
|
265
|
+
when 6
|
266
|
+
/../
|
267
|
+
end)
|
268
|
+
).collect { |part|
|
269
|
+
part += part if part.length == 1
|
270
|
+
part.hex
|
271
|
+
}).collect do |color, brightness|
|
272
|
+
"\033]6;1;bg;#{color};brightness;#{brightness}\a"
|
273
|
+
end.join
|
274
|
+
end
|
275
|
+
|
276
|
+
private
|
277
|
+
|
278
|
+
def output(command)
|
279
|
+
@window.output command
|
280
|
+
end
|
281
|
+
|
282
|
+
def create_tab_color_file(color)
|
283
|
+
file = Tempfile.open('iterm').path + '.tc'
|
284
|
+
File.open(file, 'wb') { |f| f.puts self.class.create_tab_color(ensure_color(color)) }
|
285
|
+
@window.tab_color_files << file
|
286
|
+
file
|
287
|
+
end
|
288
|
+
|
289
|
+
def ensure_color(color)
|
290
|
+
case color
|
291
|
+
when Symbol
|
292
|
+
ItermWindow.colors[color]
|
293
|
+
else
|
294
|
+
color
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itermwindow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.4.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Powers
|
9
|
+
- John Bintz
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2011-07-12 00:00:00 -04:00
|
15
|
+
default_executable:
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: rspec
|
19
|
+
prerelease: false
|
20
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
none: false
|
22
|
+
requirements:
|
23
|
+
- - ~>
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.6.0
|
26
|
+
type: :development
|
27
|
+
version_requirements: *id001
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: fakefs
|
30
|
+
prerelease: false
|
31
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: "0"
|
37
|
+
type: :development
|
38
|
+
version_requirements: *id002
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: mocha
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id003
|
50
|
+
description:
|
51
|
+
email:
|
52
|
+
- chrisjpowers@gmail.com
|
53
|
+
- john@coswellproductions.com
|
54
|
+
executables:
|
55
|
+
- iterm-window
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- README.md
|
62
|
+
- LICENSE
|
63
|
+
- CHANGELOG.md
|
64
|
+
- lib/iterm_window.rb
|
65
|
+
- bin/iterm-window
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/johnbintz/iterm_window
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
requirements: []
|
88
|
+
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.6.2
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
|
94
|
+
test_files: []
|
95
|
+
|