go 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/LICENSE.md +7 -0
- data/README.md +94 -0
- data/Rakefile +5 -0
- data/go.gemspec +25 -0
- data/lib/go.rb +25 -0
- data/lib/go/channel.rb +51 -0
- data/lib/go/config.rb +36 -0
- data/lib/go/kernel.rb +26 -0
- data/lib/go/version.rb +3 -0
- data/test/test_go.rb +92 -0
- metadata +74 -51
- data/README.markdown +0 -42
- data/iterm_rails.gemspec +0 -35
- data/iterm_rails.rb +0 -1
- data/lib/iterm_rails.rb +0 -130
data/.gitignore
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2011 Travis Reeder, Appoxy LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Go - A concurrency library for Ruby inspired by Go (golang).
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
Install gem:
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install go
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
### Basic
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'go'
|
17
|
+
|
18
|
+
# set max threads (optional)
|
19
|
+
Go.config.max_threads = 10
|
20
|
+
|
21
|
+
# fire off blocks using go
|
22
|
+
100.times do |i|
|
23
|
+
go do
|
24
|
+
puts "hello #{i}"
|
25
|
+
sleep 1
|
26
|
+
puts "#{i} awoke"
|
27
|
+
puts "hi there"
|
28
|
+
end
|
29
|
+
puts "done #{i}"
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
### Use channels to communicate
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'go'
|
37
|
+
|
38
|
+
# Use channels to communicate
|
39
|
+
ch = Go::Channel.new
|
40
|
+
20.times do |i|
|
41
|
+
go do
|
42
|
+
puts "hello channel #{i} #{ch}"
|
43
|
+
sleep 2
|
44
|
+
# push to channel
|
45
|
+
ch << "pushed #{i} to channel"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Read from channel
|
50
|
+
ch.each do |x|
|
51
|
+
puts "Got #{x} from channel"
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
### Catching exceptions and checking for different return types on the channel
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
require 'go'
|
59
|
+
|
60
|
+
# Use channels to communicate
|
61
|
+
ch = Go::Channel.new
|
62
|
+
20.times do |i|
|
63
|
+
go do
|
64
|
+
begin
|
65
|
+
puts "hello channel #{i}"
|
66
|
+
ch << "pushed #{i} to channel"
|
67
|
+
rescue => ex
|
68
|
+
ch << ex
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Read from channel
|
74
|
+
ch.each do |m|
|
75
|
+
puts "Got #{m} from channel"
|
76
|
+
case m
|
77
|
+
when String
|
78
|
+
puts m
|
79
|
+
when Exception
|
80
|
+
puts "ERROR!!! #{m}"
|
81
|
+
else
|
82
|
+
puts "Something else: #{m}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
### Closing the channel
|
88
|
+
|
89
|
+
You can close the channel with the close() method which will stop all the listeners on the channel.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
ch.close()
|
93
|
+
```
|
94
|
+
|
data/Rakefile
ADDED
data/go.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require File.expand_path('../lib/go/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Travis Reeder"]
|
6
|
+
gem.email = ["treeder@gmail.com"]
|
7
|
+
gem.description = "A concurrency library for Ruby inspired by Go (golang)."
|
8
|
+
gem.summary = "A concurrency library for Ruby inspired by Go (golang)."
|
9
|
+
gem.homepage = "https://github.com/treeder/go"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "go"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Go::VERSION
|
17
|
+
|
18
|
+
gem.required_rubygems_version = ">= 1.3.6"
|
19
|
+
gem.required_ruby_version = Gem::Requirement.new(">= 1.9")
|
20
|
+
|
21
|
+
gem.add_runtime_dependency "concur"
|
22
|
+
|
23
|
+
gem.add_development_dependency "test-unit"
|
24
|
+
|
25
|
+
end
|
data/lib/go.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'concur'
|
3
|
+
|
4
|
+
require_relative 'go/version'
|
5
|
+
require_relative 'go/config'
|
6
|
+
require_relative 'go/channel'
|
7
|
+
require_relative 'go/kernel'
|
8
|
+
|
9
|
+
module Go
|
10
|
+
@@logger = Logger.new(STDOUT)
|
11
|
+
@@logger.level = Logger::INFO
|
12
|
+
@@config = Config.new
|
13
|
+
|
14
|
+
def self.logger
|
15
|
+
@@logger
|
16
|
+
end
|
17
|
+
def self.logger=(logger)
|
18
|
+
@@logger = logger
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.config
|
22
|
+
@@config ||= Config.new
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/go/channel.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Go
|
2
|
+
class Channel
|
3
|
+
attr_reader :closed
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@queue = Queue.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def <<(ob)
|
10
|
+
@queue << ob
|
11
|
+
end
|
12
|
+
|
13
|
+
def shift
|
14
|
+
begin
|
15
|
+
@queue.shift
|
16
|
+
rescue Exception => ex
|
17
|
+
puts ex.class.name
|
18
|
+
p ex
|
19
|
+
puts ex.message
|
20
|
+
if ex.class.name == "fatal" && ex.message.include?("deadlock")
|
21
|
+
close()
|
22
|
+
return Go::Exit
|
23
|
+
end
|
24
|
+
raise ex
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&blk)
|
29
|
+
while true do
|
30
|
+
puts "Closed? #{@closed}"
|
31
|
+
break if @closed
|
32
|
+
x = shift
|
33
|
+
break if x == Go::Exit
|
34
|
+
yield x
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# close the channel
|
39
|
+
def close
|
40
|
+
puts 'closing channel'
|
41
|
+
@closed = true
|
42
|
+
self << Go::Exit
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Just for exiting a channel
|
47
|
+
class Exit
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/lib/go/config.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Go
|
2
|
+
class Config
|
3
|
+
attr_reader :defaults
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
init_defaults
|
7
|
+
@listeners = []
|
8
|
+
@max_threads = options[:max_threads] || defaults[:max_threads]
|
9
|
+
end
|
10
|
+
|
11
|
+
def init_defaults
|
12
|
+
@defaults = {
|
13
|
+
max_threads: 20
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def max_threads=(x)
|
18
|
+
@max_threads = x
|
19
|
+
notify_listeners(:max_threads=>x)
|
20
|
+
end
|
21
|
+
|
22
|
+
def max_threads
|
23
|
+
@max_threads
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_listener(l)
|
27
|
+
@listeners << l
|
28
|
+
end
|
29
|
+
|
30
|
+
def notify_listeners(changes)
|
31
|
+
@listeners.each do |l|
|
32
|
+
l.update(changes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/go/kernel.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module Go
|
3
|
+
class GoKernel
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
@executor = Concur::Executor.new_thread_pool_executor(@config.max_threads)
|
7
|
+
@config.add_listener(@executor)
|
8
|
+
end
|
9
|
+
|
10
|
+
def executor
|
11
|
+
@executor
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.gok
|
16
|
+
@gok ||= GoKernel.new(Go.config)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
module ::Kernel
|
22
|
+
def go(ch=nil, &blk)
|
23
|
+
future = ::Go.gok.executor.execute(nil, ch, &blk)
|
24
|
+
future
|
25
|
+
end
|
26
|
+
end
|
data/lib/go/version.rb
ADDED
data/test/test_go.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
gem 'test-unit'
|
2
|
+
require 'test/unit'
|
3
|
+
require_relative '../lib/go'
|
4
|
+
|
5
|
+
class TestGo < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_go
|
8
|
+
|
9
|
+
Go.config.max_threads = 10
|
10
|
+
|
11
|
+
3.times do |i|
|
12
|
+
go do
|
13
|
+
puts "#{i} sleeping..."
|
14
|
+
sleep 1
|
15
|
+
puts "#{i} awoke"
|
16
|
+
end
|
17
|
+
puts "#{i} done "
|
18
|
+
end
|
19
|
+
|
20
|
+
ch = Go::Channel.new
|
21
|
+
times = 10
|
22
|
+
times.times do |i|
|
23
|
+
go do
|
24
|
+
#puts "hello channel #{i}"
|
25
|
+
sleep 1
|
26
|
+
# push to channel
|
27
|
+
ch << "hello, I am # #{i}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
puts "waiting on channel..."
|
32
|
+
i = 0
|
33
|
+
ch.each do |x|
|
34
|
+
puts "Got: #{x}"
|
35
|
+
i += 1
|
36
|
+
end
|
37
|
+
assert_equal times, i
|
38
|
+
|
39
|
+
# Pass different objects back
|
40
|
+
ch = Go::Channel.new
|
41
|
+
times = 10
|
42
|
+
errmod = 5
|
43
|
+
times.times do |i|
|
44
|
+
go do
|
45
|
+
begin
|
46
|
+
raise "Error yo!" if i % errmod == 0
|
47
|
+
puts "hello channel #{i}"
|
48
|
+
sleep 1
|
49
|
+
# push to channel
|
50
|
+
ch << "pushed #{i} to channel"
|
51
|
+
rescue => ex
|
52
|
+
ch << ex
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
go do
|
58
|
+
# wait for a bit, then close channel
|
59
|
+
sleep 10
|
60
|
+
ch.close
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "waiting on channel..."
|
64
|
+
i = 0
|
65
|
+
errs = 0
|
66
|
+
ch.each do |x|
|
67
|
+
puts "Got #{x} from channel"
|
68
|
+
i += 1
|
69
|
+
case x
|
70
|
+
when String
|
71
|
+
puts "Is String"
|
72
|
+
when Exception
|
73
|
+
puts "Is Exception!"
|
74
|
+
errs += 1
|
75
|
+
when nil
|
76
|
+
puts "got nil, breaking"
|
77
|
+
break
|
78
|
+
else
|
79
|
+
puts "Is something else"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
assert_equal times, i
|
83
|
+
assert_equal times / errmod, errs
|
84
|
+
puts 'donezo'
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
metadata
CHANGED
@@ -1,66 +1,89 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: go
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
version: 0.0.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
12
|
-
-
|
13
|
-
- Alvaro Pereyra
|
7
|
+
authors:
|
8
|
+
- Travis Reeder
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
|
-
cert_chain:
|
17
|
-
date:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: concur
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: test-unit
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: A concurrency library for Ruby inspired by Go (golang).
|
47
|
+
email:
|
48
|
+
- treeder@gmail.com
|
23
49
|
executables: []
|
24
|
-
|
25
50
|
extensions: []
|
26
|
-
|
27
51
|
extra_rdoc_files: []
|
28
|
-
|
29
|
-
|
30
|
-
-
|
31
|
-
-
|
32
|
-
-
|
33
|
-
-
|
34
|
-
|
35
|
-
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- LICENSE.md
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- go.gemspec
|
58
|
+
- lib/go.rb
|
59
|
+
- lib/go/channel.rb
|
60
|
+
- lib/go/config.rb
|
61
|
+
- lib/go/kernel.rb
|
62
|
+
- lib/go/version.rb
|
63
|
+
- test/test_go.rb
|
64
|
+
homepage: https://github.com/treeder/go
|
36
65
|
licenses: []
|
37
|
-
|
38
66
|
post_install_message:
|
39
67
|
rdoc_options: []
|
40
|
-
|
41
|
-
require_paths:
|
68
|
+
require_paths:
|
42
69
|
- lib
|
43
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
segments:
|
56
|
-
- 0
|
57
|
-
version: "0"
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.9'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.3.6
|
58
82
|
requirements: []
|
59
|
-
|
60
83
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.
|
84
|
+
rubygems_version: 1.8.25
|
62
85
|
signing_key:
|
63
86
|
specification_version: 3
|
64
|
-
summary: A
|
65
|
-
test_files:
|
66
|
-
|
87
|
+
summary: A concurrency library for Ruby inspired by Go (golang).
|
88
|
+
test_files:
|
89
|
+
- test/test_go.rb
|
data/README.markdown
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
GO - Iterm-Rails
|
2
|
-
===================
|
3
|
-
|
4
|
-
A script to launch commands in differents iTerm tabs for a Rails project: console, server, mate...
|
5
|
-
inspired by http://github.com/chrisjpowers/iterm_window examples
|
6
|
-
|
7
|
-
Examples:
|
8
|
-
--------------
|
9
|
-
|
10
|
-
iterm-rails /path/to/project
|
11
|
-
|
12
|
-
iterm-rails project # you can set a default project directory (see configuration options below)
|
13
|
-
|
14
|
-
|
15
|
-
Configuration:
|
16
|
-
--------------
|
17
|
-
You can override default configuration options:
|
18
|
-
|
19
|
-
- globally in ~/.iterm-rails.config
|
20
|
-
|
21
|
-
- per project in project/.iterm-rails.config
|
22
|
-
|
23
|
-
|
24
|
-
Configuration options in DEFAULT_CONFIG:
|
25
|
-
----------------------------------------
|
26
|
-
|
27
|
-
DEFAULT_CONFIG = {
|
28
|
-
:projects_dir => Dir.getwd,
|
29
|
-
:launch_server => true,
|
30
|
-
:launch_console => true,
|
31
|
-
:launch_spork_for_rspec => false,
|
32
|
-
:launch_spork_for_cuc => false,
|
33
|
-
:rails3 => false,
|
34
|
-
:prepend_command => nil, # example: 'rvm ruby-1.9.2-head'
|
35
|
-
}
|
36
|
-
|
37
|
-
Author
|
38
|
-
------
|
39
|
-
|
40
|
-
- Florent Guilleux (Author): github.com/Florent2 | florent2 AT gmail DOT com
|
41
|
-
|
42
|
-
- Alvaro Pereyra (Contributor): github.com/xenda | alvaro AT xendacentral DOT com
|
data/iterm_rails.gemspec
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
#!/usr/bin/env gem build
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
require "base64"
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = "go"
|
8
|
-
s.version = "0.0.1"
|
9
|
-
s.authors = ["Florent Guilleux", "Alvaro Pereyra"]
|
10
|
-
s.homepage = "http://github.com/xenda/iterm-rails"
|
11
|
-
s.summary = "A script to launch commands in differents iTerm tabs for a Rails project"
|
12
|
-
s.description = "#{s.summary}. inspired by http://github.com/chrisjpowers/iterm_window examples."
|
13
|
-
s.cert_chain = nil
|
14
|
-
s.email = Base64.decode64("YWx2YXJvQHhlbmRhY2VudHJhbC5jb20=\n")
|
15
|
-
s.has_rdoc = false
|
16
|
-
|
17
|
-
# files
|
18
|
-
s.files = `git ls-files`.split("\n")
|
19
|
-
|
20
|
-
Dir["bin/*"].map(&File.method(:basename))
|
21
|
-
s.default_executable = "go"
|
22
|
-
s.require_paths = ["lib"]
|
23
|
-
|
24
|
-
# Ruby version
|
25
|
-
s.required_ruby_version = ::Gem::Requirement.new("~> 1.9")
|
26
|
-
|
27
|
-
begin
|
28
|
-
require "changelog"
|
29
|
-
rescue LoadError
|
30
|
-
warn "You have to have changelog gem installed for post install message"
|
31
|
-
else
|
32
|
-
s.post_install_message = CHANGELOG.new.version_changes
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
data/iterm_rails.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "iterm_rails"
|
data/lib/iterm_rails.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# a script to launch commands in differents iTerm tabs for a Rails project: console, server, mate...
|
4
|
-
# inspired by http://github.com/chrisjpowers/iterm_window examples
|
5
|
-
|
6
|
-
# examples:
|
7
|
-
# iterm-rails /path/to/project
|
8
|
-
# iterm-rails project # you can set a default project directory (see configuration options below)
|
9
|
-
|
10
|
-
# you can override default configuration options:
|
11
|
-
# globally in ~/.iterm-rails.config
|
12
|
-
# per project in project/.iterm-rails.config
|
13
|
-
# see configuration options in DEFAULT_CONFIG below
|
14
|
-
|
15
|
-
|
16
|
-
require 'rubygems'
|
17
|
-
require 'iterm_window'
|
18
|
-
require 'pathname'
|
19
|
-
require 'yaml'
|
20
|
-
require 'socket'
|
21
|
-
require 'timeout'
|
22
|
-
|
23
|
-
module ItermRails
|
24
|
-
|
25
|
-
DEFAULT_CONFIG = {
|
26
|
-
:projects_dir => Dir.getwd,
|
27
|
-
:launch_server => true,
|
28
|
-
:launch_console => true,
|
29
|
-
:launch_spork_for_rspec => false,
|
30
|
-
:launch_spork_for_cuc => false,
|
31
|
-
:rails3 => false,
|
32
|
-
:prepend_command => nil, # example: 'rvm ruby-1.9.2-head'
|
33
|
-
}
|
34
|
-
|
35
|
-
def create_tab(project_path, *commands)
|
36
|
-
project_name = project_path.basename
|
37
|
-
open_tab :new_tab do
|
38
|
-
write "cd #{project_path}"
|
39
|
-
set_title "- #{project_name}"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def find_available_port_from(port_number)
|
44
|
-
result = port_number
|
45
|
-
result += 1 while is_port_open?(result)
|
46
|
-
result
|
47
|
-
end
|
48
|
-
|
49
|
-
def is_a_rails_project_directory?(project_path)
|
50
|
-
%w{app config db script}.all? { |directory| project_path.join(directory).exist? }
|
51
|
-
end
|
52
|
-
|
53
|
-
# from http://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-open
|
54
|
-
def is_port_open?(port_number)
|
55
|
-
begin
|
56
|
-
Timeout::timeout(1) do
|
57
|
-
begin
|
58
|
-
s = TCPSocket.new('localhost', port_number)
|
59
|
-
s.close
|
60
|
-
return true
|
61
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
62
|
-
return false
|
63
|
-
end
|
64
|
-
end
|
65
|
-
rescue Timeout::Error
|
66
|
-
end
|
67
|
-
|
68
|
-
return false
|
69
|
-
end
|
70
|
-
|
71
|
-
def merge_configs(config, custom_config_file_path)
|
72
|
-
if custom_config_file_path.exist?
|
73
|
-
config.merge YAML::load(File.open custom_config_file_path)
|
74
|
-
else
|
75
|
-
config
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
config = merge_configs DEFAULT_CONFIG, Pathname.new('~').expand_path.join('.iterm-rails.config')
|
80
|
-
|
81
|
-
raise "missing project path" if ARGV.first.nil?
|
82
|
-
project_path = Pathname.new ARGV.first
|
83
|
-
project_path = Pathname.new(config[:projects_dir]).join(project_path) if project_path.relative?
|
84
|
-
project_path = project_path.expand_path
|
85
|
-
raise "'#{project_path}' does not exist or is not a directory" if !project_path.directory?
|
86
|
-
raise "'#{project_path}' is not a Rails project directory" if !is_a_rails_project_directory?(project_path)
|
87
|
-
config = merge_configs config, project_path.join('.iterm-rails.config')
|
88
|
-
|
89
|
-
puts "open new window with tabs for '#{project_path}'"
|
90
|
-
puts " with config: #{config.inspect}"
|
91
|
-
|
92
|
-
Tab = Struct.new :title, :commands
|
93
|
-
tabs = []
|
94
|
-
|
95
|
-
if config[:launch_spork_for_rspec]
|
96
|
-
port = find_available_port_from 8989
|
97
|
-
tabs << Tab.new("spork #{port}", ["spork -p #{port}"])
|
98
|
-
end
|
99
|
-
|
100
|
-
if config[:launch_spork_for_cuc]
|
101
|
-
port = find_available_port_from 9989
|
102
|
-
tabs << Tab.new("spork cuc #{port}", ["spork cuc -p #{port}"])
|
103
|
-
end
|
104
|
-
|
105
|
-
if config[:launch_console]
|
106
|
-
command = if config[:rails3] then "rails console" else "script/console" end
|
107
|
-
tabs << Tab.new("console", [command])
|
108
|
-
end
|
109
|
-
|
110
|
-
tabs << Tab.new("main", ["mate ./ &"])
|
111
|
-
|
112
|
-
if config[:launch_console]
|
113
|
-
port = find_available_port_from 3000
|
114
|
-
command = if config[:rails3] then "rails server" else "script/server" end
|
115
|
-
tabs << Tab.new("server #{port}", ["#{command} -p #{port}"])
|
116
|
-
end
|
117
|
-
|
118
|
-
ItermWindow.open do
|
119
|
-
project_name = project_path.basename
|
120
|
-
tabs.each do |tab|
|
121
|
-
open_tab :new_tab do
|
122
|
-
write "cd #{project_path}"
|
123
|
-
write config[:prepend_command] unless config[:prepend_command] == "nil" || config[:prepend_command].empty?
|
124
|
-
tab.commands.each { |command| write command }
|
125
|
-
set_title "#{tab.title} - #{project_name}"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|