divide 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61c2bb7c29d7587d40f76bf342714e839bf1f579
4
- data.tar.gz: d1fb8ec3ac33f6fa0424eb0e820f5078432e732d
3
+ metadata.gz: e2638293acbd8a4d7977f9f41d0efd5f503317ac
4
+ data.tar.gz: 972a61cb4e0c8037faefc8b2103a6e1cbed4159a
5
5
  SHA512:
6
- metadata.gz: d889eb570a31453eebfb0ea9ec3071782e5a686ccdd5d05e6a17d1eedc42494c9abc6639103993ba2f168d85e4b5bb2d2b411bf39bc8dc78bd8581996860fca8
7
- data.tar.gz: 0289c2c966d691a89850c063db86dc82446609037cd2a12ccbf121c200c166864011104ddcb98deb241e2bf85fdb8d4e1030a1f2daa0e56f1900320448972140
6
+ metadata.gz: 89c9dd0d15666f6953e29dc3f7c80fcba32e3ff728a5ea30eec616b43f4086229c33621090425e5e96701c696bce24a1b2d37aa739c30eded6dd12276f5e221c
7
+ data.tar.gz: fb17df6ab1db78fa3043e054333d0e548e80d2028153e01d98e7cc40921b6466075352951610c48654ff9377e344121e043d022fe2658ec98387fb09bbf61cc9
data/README.md CHANGED
@@ -1,25 +1,70 @@
1
1
  # Divide
2
- Start Procfile processes in different Terminal.app tabs
2
+ Start `Procfile` processes in different Terminal/iTerm tabs.
3
3
 
4
- ## Installation
5
- ```
4
+ I’m well aware of [foreman][], but it starts all processes in the same tab which can be inconvenient.<br>
5
+ I’m well aware of [tmux][], but obviously not everyone’s using it (if you do, check out [teamocil][]).
6
+
7
+ ## Usage
8
+ ```sh
6
9
  $ gem install divide
10
+ $ divide
7
11
  ```
8
12
 
9
- ## Usage
13
+ ## Options
14
+ **Divide** is option-free. You may however overwrite any options of your `Procfile` processes by passing them to `divide`.
15
+
16
+ ```
17
+ # Procfile
18
+ web: bundle exec unicorn -c ./config/unicorn.rb
19
+ ```
20
+
21
+ ```sh
22
+ $ divide -c ./another_folder/unicorn.rb
23
+ # => bundle exec unicorn -c ./another_folder/unicorn.rb
24
+ ```
25
+
26
+ ### ENV
27
+ **Divide** automatically loads `.env` file and overwrite any `$VARIABLE` of your processes.
28
+
29
+ ```
30
+ # .env
31
+ PORT=1337
32
+ RACK_ENV=development
33
+ ```
10
34
  ```
35
+ # Procfile
36
+ web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb -E $RACK_ENV
37
+ ```
38
+
39
+ ```sh
11
40
  $ divide
12
- $ divide -p 1337
41
+ # => bundle exec unicorn -p 1337 -c ./config/unicorn.rb -E development
13
42
  ```
14
- ## License
15
- MIT (See [LICENSE][])
16
43
 
17
- ---
44
+ ### $PORT
45
+ If you don’t specify a port, **Divide** will overwrite `$PORT` with 5000.
18
46
 
19
- I’m well aware of [foreman][], but it starts all processes in the same tab which can be inconvenient.<br>
20
- I’m well aware of [tmux][], but obviously not everyone’s using it (if you do, check out [teamocil][]).
47
+ ```
48
+ # Procfile
49
+ web: bundle exec rails s -p $PORT
50
+ ```
51
+
52
+ ```sh
53
+ $ divide
54
+ # => bundle exec rails s -p 5000
55
+ ```
56
+
57
+ ## Contributing
58
+ Why yes! You’re welcome to submit any [issue][] or [pull request][] as long as everything’s green when you `bundle exec rake spec`. Meanwhile, you can give these folks a tap on the back for helping out:
59
+
60
+ - [@remiprev](https://github.com/remiprev)
61
+
62
+ ## License
63
+ Copyright © 2013 Etienne Lemay. See [LICENSE][] for details.
21
64
 
22
- [LICENSE]: /LICENSE.md
23
65
  [foreman]: https://github.com/dollar/foreman
24
66
  [tmux]: http://tmux.sourceforge.net
25
67
  [teamocil]: https://github.com/remiprev/teamocil
68
+ [issue]: https://github.com/EtienneLem/divide/issues
69
+ [pull request]: https://github.com/EtienneLem/divide/pulls
70
+ [LICENSE]: /LICENSE.md
data/Rakefile CHANGED
@@ -1,3 +1,15 @@
1
1
  # Rubygems
2
2
  require 'bundler'
3
+ Bundler.require(:development)
4
+
3
5
  Bundler::GemHelper.install_tasks
6
+ require "rspec/core/rake_task"
7
+
8
+ # RSpec
9
+ task :default => :spec
10
+
11
+ desc "Run all specs"
12
+ RSpec::Core::RakeTask.new(:spec) do |task|
13
+ task.pattern = "spec/**/*_spec.rb"
14
+ task.rspec_opts = "--colour --format=documentation"
15
+ end
data/bin/divide CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
3
5
  require 'divide'
4
- exit Divide.run(ARGV)
6
+ Divide::CLI.new(ARGV)
@@ -1,13 +1,15 @@
1
1
  require File.expand_path('../lib/divide/version', __FILE__)
2
2
 
3
3
  spec = Gem::Specification.new do |s|
4
- s.name = 'divide'
5
- s.author = 'Etienne Lemay'
6
- s.email = 'etienne@heliom.ca'
7
- s.homepage = 'https://github.com/EtienneLem/'
8
- s.summary = 'Start Procfile processes in different Terminal.app tabs'
4
+ s.name = 'divide'
5
+ s.author = 'Etienne Lemay'
6
+ s.email = 'etienne@heliom.ca'
7
+ s.homepage = 'https://github.com/EtienneLem/'
8
+ s.license = 'MIT'
9
+ s.summary = 'Divide Procfile processes'
10
+ s.description = 'Start Procfile processes in different Terminal.app tabs'
9
11
 
10
- s.version = Divide::VERSION
12
+ s.version = Divide::VERSION
11
13
  s.platform = Gem::Platform::RUBY
12
14
 
13
15
  s.files = %w(LICENSE.md README.md Rakefile divide.gemspec)
@@ -18,4 +20,6 @@ spec = Gem::Specification.new do |s|
18
20
  s.executables << 'divide'
19
21
 
20
22
  s.require_paths << 'lib'
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rspec', '~> 2.13'
21
25
  end
@@ -1,29 +1,7 @@
1
1
  require 'divide/version'
2
2
  require 'divide/extractor'
3
- require 'divide/terminal_bridge'
3
+ require 'divide/terminal_bridge/terminal'
4
+ require 'divide/terminal_bridge/iterm'
5
+ require 'divide/cli'
4
6
 
5
- module Divide
6
- def self.run(argv)
7
- @options = argv.each_slice(2).to_a
8
- terminal.exec(processes)
9
- 1
10
- end
11
-
12
- def self.processes
13
- no_profile unless extracted_processes = extractor.extract_processes!
14
- extracted_processes.to_a.map { |a| a[1] }
15
- end
16
-
17
- def self.no_profile
18
- puts "#{Dir.pwd}: There is no Procfile in this directory"
19
- exit
20
- end
21
-
22
- def self.terminal
23
- @terminal ||= Divide::TerminalBridge.new
24
- end
25
-
26
- def self.extractor
27
- @extractor ||= Divide::Extractor.new(@options)
28
- end
29
- end
7
+ module Divide; end
@@ -0,0 +1,72 @@
1
+ module Divide
2
+ class CLI
3
+ attr_reader :options
4
+
5
+ def initialize(argv=[])
6
+ @options = argv.each_slice(2).to_a
7
+
8
+ show_version if argv.grep(/^-v|--version$/).any?
9
+ show_help if argv.grep(/^-h|--help$/).any?
10
+
11
+ error(:app_not_supported) unless terminal
12
+
13
+ processes = extract_processes
14
+ start_processes(processes)
15
+ end
16
+
17
+ def start_processes(processes)
18
+ terminal.exec(processes)
19
+ end
20
+
21
+ def extract_processes
22
+ error(:no_procfile) unless extracted_processes
23
+ extracted_processes.to_a.map { |a| a[1] }
24
+ end
25
+
26
+ def error(type)
27
+ errors = {
28
+ no_procfile: "#{current_directory}: There is no Procfile in this directory",
29
+ app_not_supported: "#{current_app_name} is not yet supported, please fill in a request https://github.com/EtienneLem/divide/issues",
30
+ }
31
+
32
+ exit_with_message(errors[type], 1)
33
+ end
34
+
35
+ def show_version
36
+ exit_with_message("Divide #{VERSION}")
37
+ end
38
+
39
+ def show_help
40
+ exit_with_message("Usage: divide [options]")
41
+ end
42
+
43
+ def exit_with_message(message, code=0)
44
+ STDOUT.puts(message)
45
+ exit code
46
+ end
47
+
48
+ def current_app_name
49
+ @current_app_name ||= TerminalBridge.current_app_name
50
+ end
51
+
52
+ def extracted_processes
53
+ @extracted_processes ||= extractor.extract_processes!
54
+ end
55
+
56
+ def current_directory
57
+ @current_directory ||= Dir.pwd
58
+ end
59
+
60
+ def terminal
61
+ @terminal ||= case current_app_name.downcase
62
+ when 'terminal' then TerminalBridge::Terminal.new
63
+ when 'iterm' then TerminalBridge::ITerm.new
64
+ else nil
65
+ end
66
+ end
67
+
68
+ def extractor
69
+ @extractor ||= Extractor.new(@options)
70
+ end
71
+ end
72
+ end
@@ -1,34 +1,58 @@
1
1
  require 'yaml'
2
2
 
3
- class Divide::Extractor
4
- def initialize(options=[])
5
- @procfile_content = File.read('./Procfile') rescue ''
6
- @options = options
3
+ module Divide
4
+ class Extractor
5
+ DEFAULT_ENV = { 'PORT' => '5000' }.merge(ENV)
7
6
 
8
- overwrite_options
9
- overwrite_port
10
- end
7
+ def initialize(options=[])
8
+ @options = options
9
+
10
+ overwrite_env_variables
11
+ overwrite_options
12
+ end
13
+
14
+ def procfile_content
15
+ @procfile_content ||= File.read('./Procfile') rescue ''
16
+ end
17
+
18
+ def env_content
19
+ @env_content ||= File.read('./.env') rescue ''
20
+ end
11
21
 
12
- def overwrite_options
13
- splitted_procfile = @procfile_content.split(/\s/)
22
+ def overwrite_options
23
+ splitted_content = procfile_content.split(/\s/)
14
24
 
15
- @options.each do |option|
16
- key = option[0]
17
- value = option[1]
25
+ @options.each do |option|
26
+ next if option.length < 2
18
27
 
19
- key_index = splitted_procfile.index(key)
20
- value_to_overwrite = splitted_procfile[key_index + 1]
28
+ key = option[0]
29
+ value = option[1]
21
30
 
22
- @procfile_content.sub!(value_to_overwrite, value)
31
+ if key_index = splitted_content.index(key)
32
+ value_to_overwrite = splitted_content[key_index + 1]
33
+ procfile_content.sub!(value_to_overwrite, value)
34
+ end
35
+ end
23
36
  end
24
- end
25
37
 
26
- def overwrite_port
27
- @procfile_content.sub!('$PORT', ENV['PORT'] || '5000')
28
- end
38
+ def extract_processes!
39
+ return nil if procfile_content.empty?
40
+ YAML.load(procfile_content)
41
+ end
29
42
 
30
- def extract_processes!
31
- return nil if @procfile_content.empty?
32
- YAML.load(@procfile_content)
43
+ def env_variables
44
+ @env_variables ||= begin
45
+ env_content.split(/\n/).inject({}) do |memo, line|
46
+ variable, value = line.split(/=/)
47
+ memo.merge variable => value
48
+ end
49
+ end
50
+ end
51
+
52
+ def overwrite_env_variables
53
+ DEFAULT_ENV.merge(env_variables).each do |variable, value|
54
+ procfile_content.gsub!("$#{variable}", value)
55
+ end
56
+ end
33
57
  end
34
58
  end
@@ -1,40 +1,68 @@
1
- class Divide::TerminalBridge
2
- def apple_script(cmd)
3
- cmd = cmd.join("' -e '") if cmd.is_a?(Array)
4
- `osascript -e '#{cmd}'`
5
- end
1
+ module Divide
2
+ class TerminalBridge
3
+ attr_reader :app_name
6
4
 
7
- def tell_terminal(cmd)
8
- %(tell app "Terminal" to #{cmd})
9
- end
5
+ # Class methods
6
+ def self.execute(command)
7
+ `#{command}`
8
+ end
10
9
 
11
- def do_script(script)
12
- tell_terminal %(do script "#{script}" in front window)
13
- end
10
+ def self.apple_script(command)
11
+ command = command.join("' -e '") if command.is_a?(Array)
12
+ execute("osascript -e '#{command}'")
13
+ end
14
14
 
15
- def keystroke(app, key)
16
- splits = key.split('+')
15
+ def self.current_app_name
16
+ @current_app_name ||= apple_script('tell app "System Events" to get name of the first process whose frontmost is true').strip
17
+ end
17
18
 
18
- if splits.length > 1
19
- modifier_key = splits[0]
20
- key = splits[1]
21
- else
22
- modifier_key = nil
23
- key = splits[0]
19
+ # Instance methods
20
+ def initialize
21
+ @app_name = bridge.current_app_name
24
22
  end
25
23
 
26
- modifier = modifier_key ? " using #{modifier_key} down" : ''
27
- %(tell app "System Events" to tell process "#{app}" to keystroke "#{key}"#{modifier})
28
- end
24
+ def bridge
25
+ @bridge ||= Divide::TerminalBridge
26
+ end
29
27
 
30
- def exec(commands)
31
- scripts = commands.map { |c| do_script(c) }
32
- scripts_with_new_tabs = insert_between(scripts, keystroke('Terminal', 'command+t'))
28
+ def tell_current_app(cmd)
29
+ %(tell app "#{@app_name}" to #{cmd})
30
+ end
33
31
 
34
- apple_script(scripts_with_new_tabs)
35
- end
32
+ def open_new_tab_in_current_directory
33
+ [open_new_tab, go_to_current_directory]
34
+ end
36
35
 
37
- def insert_between(scripts, insert_between)
38
- scripts.flat_map { |s| [s, insert_between] }[0...-1]
36
+ def go_to_current_directory
37
+ do_script "cd #{Dir.pwd}"
38
+ end
39
+
40
+ def keystroke(key)
41
+ splits = key.split('+')
42
+
43
+ if splits.length > 1
44
+ modifier_key = splits[0]
45
+ key = splits[1]
46
+ else
47
+ modifier_key = nil
48
+ key = splits[0]
49
+ end
50
+
51
+ modifier = modifier_key ? " using #{modifier_key} down" : ''
52
+ %(tell app "System Events" to tell process "#{@app_name}" to keystroke "#{key}"#{modifier})
53
+ end
54
+
55
+ def exec(commands)
56
+ commands = Array(commands)
57
+
58
+ scripts = commands.map { |c| do_script(c) }
59
+ scripts_with_new_tabs = insert_between(scripts, open_new_tab_in_current_directory).flatten
60
+
61
+ bridge.apple_script(scripts_with_new_tabs)
62
+ end
63
+
64
+ def insert_between(array, insert_between)
65
+ array.flat_map { |a| [a, insert_between] }[0...-1]
66
+ end
39
67
  end
40
68
  end
@@ -0,0 +1,13 @@
1
+ require 'divide/terminal_bridge'
2
+
3
+ module Divide
4
+ class TerminalBridge::ITerm < TerminalBridge
5
+ def do_script(script)
6
+ tell_current_app %(tell the first terminal to tell the last session to write text "#{script}")
7
+ end
8
+
9
+ def open_new_tab
10
+ tell_current_app %(tell the first terminal to launch session "Default Session")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'divide/terminal_bridge'
2
+
3
+ module Divide
4
+ class TerminalBridge::Terminal < TerminalBridge
5
+ def do_script(script)
6
+ tell_current_app %(do script "#{script}" in front window)
7
+ end
8
+
9
+ def open_new_tab
10
+ keystroke 'command+t'
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Divide
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
metadata CHANGED
@@ -1,16 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: divide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Etienne Lemay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-25 00:00:00.000000000 Z
12
- dependencies: []
13
- description:
11
+ date: 2013-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.13'
41
+ description: Start Procfile processes in different Terminal.app tabs
14
42
  email: etienne@heliom.ca
15
43
  executables:
16
44
  - divide
@@ -21,13 +49,17 @@ files:
21
49
  - README.md
22
50
  - Rakefile
23
51
  - divide.gemspec
52
+ - lib/divide/cli.rb
24
53
  - lib/divide/extractor.rb
54
+ - lib/divide/terminal_bridge/iterm.rb
55
+ - lib/divide/terminal_bridge/terminal.rb
25
56
  - lib/divide/terminal_bridge.rb
26
57
  - lib/divide/version.rb
27
58
  - lib/divide.rb
28
59
  - bin/divide
29
60
  homepage: https://github.com/EtienneLem/
30
- licenses: []
61
+ licenses:
62
+ - MIT
31
63
  metadata: {}
32
64
  post_install_message:
33
65
  rdoc_options: []
@@ -49,5 +81,5 @@ rubyforge_project:
49
81
  rubygems_version: 2.0.0
50
82
  signing_key:
51
83
  specification_version: 4
52
- summary: Start Procfile processes in different Terminal.app tabs
84
+ summary: Divide Procfile processes
53
85
  test_files: []