automux 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.md +25 -5
  2. data/bin/automux +6 -14
  3. data/data/automux/recipes/default.sh.erb +1 -1
  4. data/features/custom_recipes.feature +2 -2
  5. data/features/general_usage.feature +4 -4
  6. data/features/{session_hooks.feature → hooks.feature} +0 -0
  7. data/features/runtime_options.feature +18 -0
  8. data/features/setup_windows.feature +2 -2
  9. data/features/step_definitions/custom_recipes_steps.rb +0 -5
  10. data/features/step_definitions/shared_steps.rb +10 -0
  11. data/lib/automux.rb +2 -0
  12. data/lib/automux/cache.rb +1 -1
  13. data/lib/automux/cache/blueprint.rb +3 -1
  14. data/lib/automux/cache/recipe.rb +3 -1
  15. data/lib/automux/controller.rb +1 -1
  16. data/lib/automux/controller/base.rb +2 -2
  17. data/lib/automux/controller/blueprints.rb +1 -1
  18. data/lib/automux/controller/messages.rb +1 -1
  19. data/lib/automux/controller/recipes.rb +4 -4
  20. data/lib/automux/controller/support/rendering.rb +19 -18
  21. data/lib/automux/core.rb +2 -0
  22. data/lib/automux/core/blueprint.rb +3 -3
  23. data/lib/automux/core/error.rb +1 -1
  24. data/lib/automux/core/support/custom_accessors.rb +1 -1
  25. data/lib/automux/core/support/hooks_helper.rb +2 -5
  26. data/lib/automux/core/support/options_helper.rb +2 -5
  27. data/lib/automux/core/tmux/session.rb +28 -31
  28. data/lib/automux/core/tmux/window.rb +36 -28
  29. data/lib/automux/installation.rb +6 -6
  30. data/lib/automux/library.rb +1 -0
  31. data/lib/automux/library/file_options_parser.rb +37 -0
  32. data/lib/automux/library/mini_erb.rb +3 -3
  33. data/lib/automux/library/yaml_parser.rb +7 -21
  34. data/lib/automux/null.rb +8 -0
  35. data/lib/automux/null/base.rb +15 -0
  36. data/lib/automux/null/blueprint.rb +6 -0
  37. data/lib/automux/null/recipe.rb +6 -0
  38. data/lib/automux/redirector.rb +6 -0
  39. data/lib/automux/redirector/blueprint.rb +23 -0
  40. data/lib/automux/redirector/default.rb +32 -0
  41. data/lib/automux/redirector/setup.rb +12 -0
  42. data/lib/automux/version.rb +1 -1
  43. data/test/command_line.rb +7 -0
  44. data/test/session_test.rb +10 -5
  45. data/test/support/common_methods.rb +6 -0
  46. data/test/support/test_helper.rb +1 -0
  47. metadata +15 -4
data/README.md CHANGED
@@ -164,10 +164,28 @@ windows:
164
164
  name: test
165
165
  windows:
166
166
  - name: git
167
- panes: git pull '-r:' master
167
+ panes: git pull origin '-r:'
168
168
  ```
169
169
 
170
- * Note: The option needs to be surounded by quotes. It makes Automux's job easier.
170
+ #### Dynamic root values using opts.
171
+
172
+ **root** defaults to the current directory. One may use an opt to achieve dynamic assignment.
173
+
174
+ ```yaml
175
+ name: test
176
+ root: '-r:'
177
+ windows:
178
+ - panes: pwd
179
+ ```
180
+
181
+ `automux test -r projects` will change the directory to *projects* before starting Tmux.
182
+
183
+ `automux test` will use the current directory.
184
+
185
+ #### Note
186
+
187
+ * Since the opts are derived from the blueprint, the blueprint name needs to precede the opts as seen in the above commands.
188
+ * The option needs to be surounded by quotes. It makes Automux's job easier.
171
189
 
172
190
  ## Custom defined window indexes
173
191
 
@@ -209,7 +227,7 @@ Here the indexing will start from 2 onwards.
209
227
 
210
228
  > What would Tmux do?
211
229
 
212
- Automux is built on top of an ruby API for Tmux. Instead of providing a custom key for every possible Tmux option, its approach is to provide direct access to the session/window objects. This gives way for higher levels of customizations like allowing end users to add their own session/window methods and using them in the blueprints to letting them define their own recipes for logic. The following sections will look at some these approaches.
230
+ Automux is built on top of an ruby API for Tmux. Instead of providing a custom key for every possible Tmux option, its approach is to provide direct access to the session/window objects. This gives way for higher levels of customizations like allowing end users to add their own session/window methods and using them in the blueprints or letting them define their own recipes for logic. The following sections will look at some these approaches.
213
231
 
214
232
  ### Hooks with ERB
215
233
 
@@ -287,7 +305,7 @@ cd <%= root %>
287
305
 
288
306
  - if window.has_panes?
289
307
  - window.panes.each do |pane|
290
- = create_pane if pane.index > 0
308
+ = split_window if pane.index > 0
291
309
  = send_keys(window, pane.command)
292
310
  - end
293
311
  - end
@@ -296,13 +314,15 @@ cd <%= root %>
296
314
  = attach_session
297
315
  ```
298
316
 
299
- Its a simpler form of ERB much like [HAML](https://github.com/haml/haml) without indentation. The ERB is evaluated with session's context. Hence all methods defined for session are available here. The default recipe comes from the gem and cannot be overwritten. Custom recipes can be run like so:
317
+ Its a simpler form of ERB much like [HAML](https://github.com/haml/haml) without indentation. The ERB is evaluated with session's context. Hence all methods defined for session are available here. Custom recipes can be run like so:
300
318
 
301
319
  ```sh
302
320
  $ automux default custom_recipe
303
321
  ```
304
322
  _Here default is the default blueprint name._
305
323
 
324
+ * Note: The default recipe comes from the Gem and cannot be overwritten. Running `automux default default` will invoke the recipe defined in the Gem instead of any user defined default. The primary reason for this approach is not the burden end users with the necessity to update their default recipe in future releases.
325
+
306
326
  ## Bash Autocompletion
307
327
 
308
328
  Currently blueprint names can be autocompleted. A dedicated autocompletion shell script is in the pipeline. For now add the following to your `~/.bashrc` to get autocompletion for blueprint names.
data/bin/automux CHANGED
@@ -3,20 +3,12 @@
3
3
  lib_path = File.expand_path('../../lib', __FILE__)
4
4
  $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
5
5
 
6
+ ENV['AUTOMUX_ENV'] ||= 'production'
6
7
  require 'automux'
7
8
 
8
- args = ARGV.take_while { |argument| argument.match(/^\w/) }
9
+ probable_class_name = ARGV[0].to_s.to_sym.capitalize
9
10
 
10
- case args[0]
11
- when 'setup'
12
- Automux::Controller::Setup.new.clone_defaults
13
- when 'blueprint'
14
- params = { blueprint_name: args[2], clone_name: args[3] }
15
- Automux::Controller::Blueprints.new(params).public_send(args[1])
16
- else
17
- params = {
18
- blueprint_name: args[0] || 'default',
19
- recipe_name: args[1] || 'default'
20
- }
21
- Automux::Controller::Recipes.new(params).automate
22
- end
11
+ class_name = Automux::Redirector.constants.grep(probable_class_name).first
12
+ class_name ||= :Default
13
+
14
+ Automux::Redirector.const_get(class_name).new(ARGV).redirect
@@ -23,7 +23,7 @@ cd <%= root %>
23
23
  - end
24
24
 
25
25
  - window.panes.each do |pane|
26
- = create_pane if pane.index > 0
26
+ = split_window if pane.index > 0
27
27
  = send_keys(window, pane.command)
28
28
  - end
29
29
 
@@ -11,7 +11,7 @@ Feature: User using a custom recipe
11
11
  windows:
12
12
  - panes: vim
13
13
  """
14
- When I invoke Automux with the recipe "test_recipe" and the blueprint "default"
14
+ When I invoke Automux with the recipe "test_recipe" and the blueprint "test_sample"
15
15
  Then the rendered sequence of shell commands should be
16
16
  """
17
17
  echo using the test blueprint
@@ -29,7 +29,7 @@ Feature: User using a custom recipe
29
29
  = new_window(window)
30
30
 
31
31
  - window.panes.each do |pane|
32
- = create_pane if pane.index > 0
32
+ = split_window if pane.index > 0
33
33
  = send_keys(window, pane.command)
34
34
  - end
35
35
  - end
@@ -60,7 +60,7 @@ In order to run the shell commands matching the given blueprint
60
60
  tmux attach-session -t test
61
61
  """
62
62
 
63
- Scenario: Windows with clashing index values
63
+ Scenario: Windows with clashing indexes will be overwritten
64
64
  Given I have the following blueprint named "test_sample"
65
65
  """
66
66
  name: test
@@ -85,9 +85,9 @@ In order to run the shell commands matching the given blueprint
85
85
  tmux rename-window -t test:1 editor
86
86
  tmux send-keys -t test:1 "vim" C-m
87
87
 
88
- tmux new-window -t test:0 2> /dev/null
89
- tmux rename-window -t test:0 top
90
- tmux send-keys -t test:0 "top" C-m
88
+ tmux new-window -t test:1 2> /dev/null
89
+ tmux rename-window -t test:1 top
90
+ tmux send-keys -t test:1 "top" C-m
91
91
 
92
92
  tmux attach-session -t test
93
93
  """
File without changes
@@ -27,6 +27,7 @@ Feature: Providing runtime options for blueprints
27
27
  Given I have the following blueprint named "test_sample"
28
28
  """
29
29
  name: test
30
+ root: '-d:'
30
31
  windows:
31
32
  - name: git
32
33
  panes: git pull "-r:" master
@@ -82,3 +83,20 @@ Feature: Providing runtime options for blueprints
82
83
  tmux attach-session -t test
83
84
  """
84
85
 
86
+ Scenario: Passing recipe as the last argument after options
87
+ Given I have the following recipe named "test_recipe"
88
+ """
89
+ cd <%= root %>
90
+ """
91
+ And I have the following blueprint named "test_sample"
92
+ """
93
+ name: test
94
+ root: '-r:'
95
+ windows:
96
+ - panes: vim
97
+ """
98
+ When I invoke Automux with the arguments "test_sample -r projects test_recipe"
99
+ Then the rendered sequence of shell commands should be
100
+ """
101
+ cd projects
102
+ """
@@ -1,6 +1,6 @@
1
1
  Feature: Creating Window objects from user provided data
2
2
 
3
- Scenario: Window with conflicting indexes
3
+ Scenario: Window with conflicting indexes will be overwritten
4
4
  Given I have provided a blueprint with the following window information
5
5
  | name | index | panes |
6
6
  | first | 1 | top |
@@ -16,7 +16,7 @@ Feature: Creating Window objects from user provided data
16
16
  | 2 |
17
17
  And the window with the name "third" should have the following
18
18
  | index |
19
- | 3 |
19
+ | 1 |
20
20
  And the window with the name "fourth" should have the following
21
21
  | index |
22
22
  | 0 |
@@ -1,8 +1,3 @@
1
- Given(/^I have the following recipe named "(.+)"$/) do |name, string|
2
- path = File.join(Automux::Paths.recipes_container, "#{ name }.sh.erb")
3
- File.open(path, 'w') { |f| f.write(string) }
4
- end
5
-
6
1
  When(/^I invoke Automux with the recipe "(.+)" and the blueprint "(.+)"$/) do |recipe_name, blueprint_name|
7
2
  system %[bin/automux #{ blueprint_name } #{ recipe_name }]
8
3
  @results = File.read('/tmp/results')
@@ -41,3 +41,13 @@ When(/^I invoke Automux with the blueprint "(.*?)"$/) do |name|
41
41
  system %[bin/automux #{ name }]
42
42
  @results = File.read('/tmp/results')
43
43
  end
44
+
45
+ When(/^I invoke Automux with the arguments "(.*?)"$/) do |arguments|
46
+ system %[bin/automux #{ arguments }]
47
+ @results = File.read('/tmp/results')
48
+ end
49
+
50
+ Given(/^I have the following recipe named "(.+)"$/) do |name, string|
51
+ path = File.join(Automux::Paths.recipes_container, "#{ name }.sh.erb")
52
+ File.open(path, 'w') { |f| f.write(string) }
53
+ end
data/lib/automux.rb CHANGED
@@ -4,6 +4,8 @@ require 'automux/paths'
4
4
  require 'automux/library'
5
5
  require 'automux/core'
6
6
  require 'automux/controller'
7
+ require 'automux/null'
8
+ require 'automux/redirector'
7
9
  require 'automux/cache'
8
10
  require 'automux/initializers'
9
11
 
data/lib/automux/cache.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'automux/cache/blueprint'
2
2
  require 'automux/cache/recipe'
3
3
 
4
- module Automux::Cache
4
+ module Automux::Cache # :nodoc: all
5
5
  class << self
6
6
  def module_constants
7
7
  constants.select { |constant_name| const_get(constant_name).is_a?(Module) }
@@ -10,10 +10,12 @@ module Automux
10
10
  blueprint = Automux::Core::Blueprint.new(path)
11
11
  Instances[blueprint.name] = blueprint
12
12
  end
13
+
14
+ Instances[nil] = Instances['default']
13
15
  end
14
16
 
15
17
  def find_by_name(name)
16
- Instances[name]
18
+ Instances[name] || Automux::Null::Blueprint.new(name)
17
19
  end
18
20
  end
19
21
  end
@@ -10,10 +10,12 @@ module Automux
10
10
  recipe = Automux::Core::Recipe.new(path)
11
11
  Instances[recipe.name] = recipe
12
12
  end
13
+
14
+ Instances[nil] = Instances['default']
13
15
  end
14
16
 
15
17
  def find_by_name(name)
16
- Instances[name]
18
+ Instances[name] || Automux::Null::Recipe.new(name)
17
19
  end
18
20
 
19
21
  private ###
@@ -5,7 +5,7 @@ require 'automux/controller/recipes'
5
5
  require 'automux/controller/blueprints'
6
6
  require 'automux/controller/messages'
7
7
 
8
- module Automux::Controller
8
+ module Automux::Controller # :nodoc:
9
9
  class << self
10
10
  def base_inheriting_classes
11
11
  constants.select { |constant_name| const_get(constant_name) < Base }
@@ -1,6 +1,6 @@
1
1
  module Automux
2
2
  module Controller
3
- class Base
3
+ class Base # :nodoc:
4
4
  include Support::Rendering
5
5
  extend Support::Filters
6
6
 
@@ -15,7 +15,7 @@ module Automux
15
15
  end
16
16
 
17
17
  def check_blueprint
18
- notify_error "Unable to find blueprint named #{ params[:blueprint_name] }.yml" if @blueprint.nil?
18
+ notify_error "Unable to find blueprint named #{ @blueprint.name }.yml" if @blueprint.is_a?(Automux::Null::Blueprint)
19
19
  end
20
20
  end
21
21
  end
@@ -1,6 +1,6 @@
1
1
  module Automux
2
2
  module Controller
3
- class Blueprints < Base
3
+ class Blueprints < Base # :nodoc:
4
4
  before_filter :load_blueprint, only: [:edit, :copy, :cp, :delete, :rm]
5
5
  before_filter :check_blueprint, only: [:edit, :copy, :cp, :delete, :rm]
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Automux
2
2
  module Controller
3
- class Messages < Base
3
+ class Messages < Base # :nodoc:
4
4
  def error
5
5
  error = Automux::Core::Error.new(params[:message])
6
6
  @binding = error.get_binding
@@ -1,6 +1,6 @@
1
1
  module Automux
2
2
  module Controller
3
- class Recipes < Base
3
+ class Recipes < Base # :nodoc:
4
4
  before_filter :load_recipe, only: :automate
5
5
  before_filter :load_blueprint, only: :automate
6
6
  before_filter :check_blueprint, only: :automate
@@ -9,7 +9,7 @@ module Automux
9
9
 
10
10
  def automate
11
11
  @binding = @session.get_binding
12
- render @recipe.path
12
+ render_file @recipe.path
13
13
  end
14
14
 
15
15
  private ###
@@ -23,11 +23,11 @@ module Automux
23
23
  end
24
24
 
25
25
  def check_recipe
26
- notify_error "Unable to find recipe named #{ params[:recipe_name] }.sh.erb" if @recipe.nil?
26
+ notify_error "Unable to find recipe named #{ @recipe.name }.sh.erb" if @recipe.is_a?(Automux::Null::Recipe)
27
27
  end
28
28
 
29
29
  def load_and_setup_session
30
- @session = Automux::Core::Tmux::Session.new(@blueprint.read)
30
+ @session = Automux::Core::Tmux::Session.new(@blueprint.read(params[:options]))
31
31
  @session.setup
32
32
  end
33
33
  end
@@ -3,19 +3,18 @@ module Automux
3
3
  module Support
4
4
  module Rendering
5
5
 
6
+ def render(view)
7
+ path = deduce_full_path(view)
8
+ render_file(path)
9
+ end
10
+
6
11
  # There are two requirements to render a file.
7
12
  # 1. @binding
8
13
  # 2. file_name
9
- def render(view)
10
- path =
11
- # If the full path to the file is given, use that instead.
12
- if FileTest.exists?(view)
13
- view
14
- else
15
- deduce_full_path(view)
16
- end
17
-
18
- execute Automux::Library::MiniErb.new(File.read(path)).result(@binding)
14
+ def render_file(path)
15
+ result = Automux::Library::MiniErb.new(File.read(path)).result(@binding)
16
+ modified_result = remove_empty_lines(result)
17
+ environmental_execute modified_result
19
18
  end
20
19
 
21
20
  private ###
@@ -28,15 +27,17 @@ module Automux
28
27
  File.join(Paths.root, Paths.views, views_folder_name, "#{ view }.sh.erb")
29
28
  end
30
29
 
31
- def execute(result)
32
- modified_result = remove_empty_lines(result)
30
+ def environmental_execute(result)
31
+ send("#{ ENV['AUTOMUX_ENV'] }_execute", result)
32
+ end
33
+
34
+ def production_execute(result)
35
+ exec(result)
36
+ end
33
37
 
34
- if ENV['AUTOMUX_ENV'] == 'test'
35
- File.open('/tmp/results', 'w') { |f| f.write(modified_result) }
36
- exit
37
- else
38
- exec(modified_result)
39
- end
38
+ def test_execute(result)
39
+ File.open('/tmp/results', 'w') { |f| f.write(result) }
40
+ exit
40
41
  end
41
42
 
42
43
  # The recipe files can have empty lines for clarity. Remove them here.
data/lib/automux/core.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'forwardable'
1
2
  require 'automux/core/support'
2
3
  require 'automux/core/base'
3
4
  require 'automux/core/hook'
@@ -7,5 +8,6 @@ require 'automux/core/recipe'
7
8
  require 'automux/core/blueprint'
8
9
  require 'automux/core/error'
9
10
 
11
+
10
12
  module Automux::Core
11
13
  end
@@ -8,11 +8,11 @@ module Automux
8
8
  @path = path
9
9
  end
10
10
 
11
- def read
12
- Automux::Library::YamlParser.load_file(path)
11
+ def read(options = [])
12
+ Automux::Library::YamlParser.load_file(path, options)
13
13
  end
14
14
 
15
- def get_binding
15
+ def get_binding # :nodoc:
16
16
  binding
17
17
  end
18
18
 
@@ -7,7 +7,7 @@ module Automux
7
7
  @message = message
8
8
  end
9
9
 
10
- def get_binding
10
+ def get_binding # :nodoc:
11
11
  binding
12
12
  end
13
13
  end
@@ -1,7 +1,7 @@
1
1
  module Automux
2
2
  module Core
3
3
  module Support
4
- module CustomAccessors
4
+ module CustomAccessors # :nodoc:
5
5
  def dup_attr_reader(*names)
6
6
  names.each do |name|
7
7
  define_method name do
@@ -2,9 +2,6 @@ module Automux
2
2
  module Core
3
3
  module Support
4
4
  module HooksHelper
5
- attr_reader :data_hooks
6
- private :data_hooks
7
-
8
5
  def pre_hooks
9
6
  hooks.select(&:pre?)
10
7
  end
@@ -15,8 +12,8 @@ module Automux
15
12
 
16
13
  private ###
17
14
 
18
- def setup_hooks
19
- data_hooks.each do |type, commands|
15
+ def setup_hooks # :nodoc:
16
+ data.hooks.each do |type, commands|
20
17
  [commands].flatten.each do |command|
21
18
  @hooks << Hook.new(self, type, command)
22
19
  end
@@ -1,14 +1,11 @@
1
1
  module Automux
2
2
  module Core
3
3
  module Support
4
- module OptionsHelper
5
- attr_reader :data_options
6
- private :data_options
7
-
4
+ module OptionsHelper # :nodoc:
8
5
  private ###
9
6
 
10
7
  def setup_options
11
- data_options.each do |name, value|
8
+ data.options.each do |name, value|
12
9
  @options << Automux::Core::Option.new(name, value)
13
10
  end
14
11
  end
@@ -4,22 +4,31 @@ module Automux
4
4
  class Session < Base
5
5
  include Support::HooksHelper
6
6
  include Support::OptionsHelper
7
+ extend Forwardable
7
8
 
8
- attr_reader :data, :name, :root, :data_windows, :flags, :base_index
9
+ attr_reader :data, :base_index
9
10
  dup_attr_reader :windows, :hooks, :options
10
- private :data, :data_windows
11
+ def_delegators :data, :name, :root, :flags
11
12
 
12
13
  def initialize(blueprint_data)
13
- @data = blueprint_data
14
- @name = data['name']
15
- @root = data['root'] || '.'
16
- @data_windows = data['windows'] || []
17
- @data_hooks = data['hooks'] || []
18
14
  @windows = []
19
- @flags = data['flags']
20
15
  @hooks = []
21
- @data_options = data['options'] || []
22
16
  @options = []
17
+ @base_index = 0
18
+ @data = Data.new(blueprint_data)
19
+ end
20
+
21
+ class Data
22
+ attr_reader :windows, :hooks, :options, :flags, :name, :root
23
+
24
+ def initialize(attributes)
25
+ @windows = attributes['windows'] || []
26
+ @hooks = attributes['hooks'] || []
27
+ @options = attributes['options'] || []
28
+ @name = attributes['name']
29
+ @root = attributes['root'] || '.'
30
+ @flags = attributes['flags']
31
+ end
23
32
  end
24
33
 
25
34
  def start_server
@@ -54,8 +63,8 @@ module Automux
54
63
 
55
64
  # Links window from source session to current session. Window name or index must be provided.
56
65
  #
57
- # E.g.: link_window(primary, finch, 3)
58
- # This links a window named *finch* from an existing session named *primary* as 3rd window in current session.
66
+ # E.g.: +link_window+(primary, finch, 3)
67
+ # - links a window named _finch_ from an existing session named _primary_ as 3rd window in current session.
59
68
  def link_window(source_session_name, source_window_identifier, index = nil)
60
69
  %[tmux link-window -s #{ source_session_name }:#{ source_window_identifier } -t #{ name }:#{ index }]
61
70
  end
@@ -68,10 +77,16 @@ module Automux
68
77
  %[tmux select-layout -t #{ name }:#{ window.index } #{ window.layout }]
69
78
  end
70
79
 
71
- def create_pane
80
+ def split_window
72
81
  %[tmux split-window]
73
82
  end
74
83
 
84
+ def window_indexes
85
+ @windows.map(&:index).compact
86
+ end
87
+
88
+ # :stopdoc:
89
+
75
90
  def get_binding
76
91
  binding
77
92
  end
@@ -83,10 +98,6 @@ module Automux
83
98
  setup_hooks
84
99
  end
85
100
 
86
- def window_indexes
87
- @windows.map(&:index).compact
88
- end
89
-
90
101
  def next_available_window_index
91
102
  n = base_index + number_of_windows
92
103
  (Array(base_index..n) - window_indexes).first
@@ -106,18 +117,6 @@ module Automux
106
117
  @windows << window
107
118
  end
108
119
 
109
- # When multiple windows have been assigned the same index by the user, the additional window indexes will be removed.
110
- def remove_duplicate_indexes(original_data)
111
- non_indexed_data = original_data.select { |h| h['index'].to_s.empty? }
112
- indexed_data = original_data - non_indexed_data
113
-
114
- uniq_indexed_data = indexed_data.uniq { |h| h['index'] }
115
- conflicting_data = indexed_data - uniq_indexed_data
116
- removed_index_data = conflicting_data.each { |h| h.delete('index') }
117
-
118
- non_indexed_data + uniq_indexed_data + removed_index_data
119
- end
120
-
121
120
  def add_windows(windows_data)
122
121
  windows_data.each do |window_data|
123
122
  window = Automux::Core::Tmux::Window.new(self, window_data)
@@ -126,14 +125,12 @@ module Automux
126
125
  end
127
126
 
128
127
  def setup_windows
129
- windows_data = remove_duplicate_indexes(data_windows)
130
- add_windows(windows_data)
128
+ add_windows(data.windows)
131
129
  @windows.each(&:update_index)
132
130
  @windows.each(&:setup)
133
131
  end
134
132
 
135
133
  def setup_base_index
136
- @base_index = 0
137
134
  if option = options.find { |option| option.name == 'base-index' }
138
135
  @base_index = option.value.to_i
139
136
  end
@@ -4,58 +4,66 @@ module Automux
4
4
  class Window < Base
5
5
  include Support::HooksHelper
6
6
  include Support::OptionsHelper
7
+ extend Forwardable
7
8
 
8
- attr_reader :data, :session, :index, :root
9
+ attr_reader :data, :session, :index
9
10
  dup_attr_reader :panes, :hooks, :options
10
- private :data, :session
11
+ def_delegators :data, :name, :root, :layout
12
+ def_delegator :data, :is_optional, :is_optional?
11
13
 
12
- def initialize(session, data)
14
+ def initialize(session, window_data)
13
15
  @session = session
14
- @data = data
15
- @opt = data['opt']
16
- @index = data['index']
17
- @root = data['root']
18
- @data_hooks = data['hooks'] || []
19
16
  @hooks = []
20
- @data_options = data['options'] || []
21
17
  @options = []
22
18
  @panes = []
19
+ @data = Data.new(window_data)
20
+ @index = @data.index
23
21
  end
24
22
 
25
- def set_option(option)
26
- %[tmux set-window-option -t #{ session.name }:#{ index } #{ option.name } '#{ option.value }']
27
- end
23
+ class Data
24
+ attr_reader :opt, :index, :name, :root, :layout, :hooks, :options, :panes, :is_optional
28
25
 
29
- def name
30
- data['name']
26
+ def initialize(attributes)
27
+ @is_optional = attributes.has_key?('opt')
28
+ @opt = attributes['opt']
29
+ @index = attributes['index']
30
+ @name = attributes['name']
31
+ @root = attributes['root']
32
+ @layout = attributes['layout']
33
+ @hooks = attributes['hooks'] || []
34
+ @options = attributes['options'] || []
35
+ @panes = attributes['panes']
36
+ end
31
37
  end
32
38
 
33
- def setup
34
- setup_options
35
- setup_panes
36
- setup_hooks
39
+ def set_option(option)
40
+ %[tmux set-window-option -t #{ session.name }:#{ index } #{ option.name } '#{ option.value }']
37
41
  end
38
42
 
39
43
  def has_panes?
40
44
  !@panes.nil?
41
45
  end
42
46
 
43
- def layout
44
- data['layout']
47
+ def opted_in?
48
+ return true unless is_optional?
49
+
50
+ data.opt
45
51
  end
46
52
 
47
- def update_index
48
- @index ||= session.next_available_window_index
53
+ def change_root_command
54
+ %[cd #{ root }]
49
55
  end
50
56
 
51
- def opted_in?
52
- return true if @opt.nil?
57
+ # :stopdoc:
53
58
 
54
- @opt
59
+ def update_index
60
+ @index ||= session.next_available_window_index
55
61
  end
56
62
 
57
- def change_root_command
58
- %[cd #{ root }]
63
+ def setup
64
+ setup_options
65
+ setup_panes
66
+ setup_hooks
59
67
  end
60
68
 
61
69
  def get_binding
@@ -65,7 +73,7 @@ module Automux
65
73
  private ###
66
74
 
67
75
  def setup_panes
68
- [data['panes']].flatten.each do |command|
76
+ [data.panes].flatten.each do |command|
69
77
  pane = Automux::Core::Tmux::Pane.new(self, command)
70
78
  @panes << pane
71
79
  end
@@ -1,10 +1,10 @@
1
1
  module Automux
2
- module Installation
3
- MESSAGE = <<-END
4
- ********************************************************************************
5
- Please run the following the following command to setup default Automux folders:
6
- $ automux setup
7
- ********************************************************************************
2
+ module Installation # :nodoc:
3
+ MESSAGE = <<-END.gsub(/^\s+/, '')
4
+ ********************************************************************************
5
+ Please run the following the following command to setup default Automux folders:
6
+ $ automux setup
7
+ ********************************************************************************
8
8
  END
9
9
  end
10
10
  end
@@ -1,5 +1,6 @@
1
1
  require 'automux/library/mini_erb'
2
2
  require 'automux/library/yaml_parser'
3
+ require 'automux/library/file_options_parser'
3
4
 
4
5
  module Automux::Library
5
6
  end
@@ -0,0 +1,37 @@
1
+ require 'optparse'
2
+
3
+ module Automux
4
+ module Library
5
+ class FileOptionsParser # :nodoc:
6
+ attr_reader :path
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def getopts
13
+ options = file_opts_with_nil_values(path)
14
+
15
+ OptionParser.new do |parser|
16
+ options.keys.each do |opt_name|
17
+ parser.on(opt_name) { |value| options[opt_name] = value }
18
+ end
19
+ end.parse!
20
+
21
+ options
22
+ end
23
+
24
+ private ###
25
+
26
+ def file_opts_with_nil_values(path)
27
+ opts = get_file_opts(path)
28
+ Hash[opts.zip]
29
+ end
30
+
31
+ # Scan for patterns like "-\w" or '-\w' to get a opts list.
32
+ def get_file_opts(path)
33
+ File.read(path).scan(/['|"](-\w:?)['|"]/m).flatten
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,7 +2,7 @@ require 'erb'
2
2
 
3
3
  module Automux
4
4
  module Library
5
- class MiniErb < ERB
5
+ class MiniErb < ERB # :nodoc:
6
6
 
7
7
  def initialize(template)
8
8
  modified_template = erb_parseable_template(template)
@@ -14,8 +14,8 @@ module Automux
14
14
  # - [1, 2, 3] => % [1, 2, 3]
15
15
  # = [1, 2, 3] => <%= [1, 2, 3] %>
16
16
  def erb_parseable_template(string)
17
- string.gsub(/^\s*-(.+)$/, '%\1').
18
- gsub(/^\s*=(.+)$/, '<%=\1 %> ')
17
+ string.gsub(/^\s*-(.+)$/, '%\1')
18
+ .gsub(/^\s*=(.+)$/, '<%=\1 %> ')
19
19
  end
20
20
  end
21
21
  end
@@ -1,40 +1,26 @@
1
1
  require 'yaml'
2
- require 'optparse'
3
2
 
4
3
  module Automux
5
4
  module Library
6
- class YamlParser
5
+ class YamlParser # :nodoc:
7
6
  class << self
8
- def load_file(file)
9
- data_string = File.read(file)
10
- opts_replaced_string = replace_opts_with_user_input(data_string)
7
+ def load_file(file_path, parsed_options)
8
+ data_string = File.read(file_path)
9
+ opts_replaced_string = replace_opts(data_string, parsed_options)
11
10
  YAML.load(opts_replaced_string)
12
11
  end
13
12
 
14
13
  private ###
15
14
 
16
- # Scan blueprint for patterns like "-\w" or '-\w' to get a options list.
17
- # The options list is used by OptionsParser to read the options from commandline.
18
- def replace_opts_with_user_input(string)
19
- blueprint_opts = string.scan(/['|"]-(\w:?)['|"]/m).flatten
20
- user_input_values = get_options(blueprint_opts)
21
- replace_opts(string, user_input_values)
22
- end
23
-
24
15
  # Replace patterns like "-\w" with matching commandline option.
25
- def replace_opts(string, values)
26
- values.each do |k, v|
16
+ def replace_opts(string, parsed_options)
17
+ parsed_options.each do |k, v|
27
18
  # Interpolate #{ v } - to substitute literal booleans.
28
- string.gsub!(/['|"]-(#{ k }):?['|"]/m, "#{ v }")
19
+ string.gsub!(/['|"](#{ k }):?['|"]/m, "#{ v }")
29
20
  end
30
21
 
31
22
  string
32
23
  end
33
-
34
- def get_options(opts)
35
- ARGV.shift while ARGV[0].to_s.match(/^\w/)
36
- ARGV.getopts(*opts)
37
- end
38
24
  end
39
25
  end
40
26
  end
@@ -0,0 +1,8 @@
1
+ require 'automux/null/base'
2
+ require 'automux/null/blueprint'
3
+ require 'automux/null/recipe'
4
+
5
+ module Automux
6
+ module Null
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ module Automux
2
+ module Null
3
+ class Base
4
+ attr_reader :name
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def path
11
+ '/dev/null'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ module Automux
2
+ module Null
3
+ class Blueprint < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Automux
2
+ module Null
3
+ class Recipe < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'automux/redirector/default'
2
+ require 'automux/redirector/setup'
3
+ require 'automux/redirector/blueprint'
4
+
5
+ module Automux::Redirector
6
+ end
@@ -0,0 +1,23 @@
1
+ module Automux
2
+ module Redirector
3
+ class Blueprint # :nodoc:
4
+ attr_reader :action, :blueprint_name, :clone_name
5
+
6
+ def initialize(args)
7
+ @action = args[1]
8
+ @blueprint_name = args[2]
9
+ @clone_name = args[3]
10
+ end
11
+
12
+ def redirect
13
+ Automux::Controller::Blueprints.new(params).public_send(action)
14
+ end
15
+
16
+ private ###
17
+
18
+ def params
19
+ { blueprint_name: blueprint_name, clone_name: clone_name }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ module Automux
2
+ module Redirector
3
+ class Default # :nodoc:
4
+ attr_reader :blueprint_name, :recipe_name, :options
5
+
6
+ def initialize(argv)
7
+ @blueprint_name = non_opt_argument_or_nil(argv[0])
8
+ @options = get_options
9
+ @recipe_name = argv[1]
10
+ end
11
+
12
+ def redirect
13
+ Automux::Controller::Recipes.new(params).automate
14
+ end
15
+
16
+ private ###
17
+
18
+ def get_options
19
+ blueprint = Automux::Cache::Blueprint.find_by_name(blueprint_name)
20
+ Automux::Library::FileOptionsParser.new(blueprint.path).getopts
21
+ end
22
+
23
+ def params
24
+ { blueprint_name: blueprint_name, recipe_name: recipe_name, options: options }
25
+ end
26
+
27
+ def non_opt_argument_or_nil(value)
28
+ value.to_s.slice(/^\w+$/)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ module Automux
2
+ module Redirector
3
+ class Setup # :nodoc:
4
+ def initialize(args)
5
+ end
6
+
7
+ def redirect
8
+ Automux::Controller::Setup.new.clone_defaults
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Automux
2
2
  module Version
3
- STRING = '0.2.0'
3
+ STRING = '0.3.0'
4
4
  end
5
5
  end
@@ -0,0 +1,7 @@
1
+ require 'support/test_helper'
2
+
3
+ describe 'command_line' do
4
+ it "must work when invoked without arguments" do
5
+ system('bin/automux').must_equal true
6
+ end
7
+ end
data/test/session_test.rb CHANGED
@@ -2,15 +2,20 @@ require 'support/test_helper'
2
2
 
3
3
  describe 'Session' do
4
4
  it "should assign window indexes" do
5
-
6
5
  windows_data = [nil, nil, 1, 0].map do |i|
7
6
  HashFactory.build(:window, index: i)
8
7
  end
9
- data = HashFactory.build(:session, windows: windows_data)
10
-
11
- session = Automux::Core::Tmux::Session.new(data)
12
- session.setup_windows_and_hooks
13
8
 
9
+ session = setup_session_with_windows(windows_data)
14
10
  session.window_indexes.must_equal [2, 3, 1, 0]
15
11
  end
12
+
13
+ it "should assign overwrite conflicting indexes" do
14
+ windows_data = [nil, nil, 1, 1].map do |i|
15
+ HashFactory.build(:window, index: i)
16
+ end
17
+
18
+ session = setup_session_with_windows(windows_data)
19
+ session.window_indexes.must_equal [0, 2, 1, 1]
20
+ end
16
21
  end
@@ -0,0 +1,6 @@
1
+ def setup_session_with_windows(windows_data)
2
+ data = HashFactory.build(:session, windows: windows_data)
3
+ session = Automux::Core::Tmux::Session.new(data)
4
+ session.setup
5
+ session
6
+ end
@@ -5,3 +5,4 @@ require 'minitest/autorun'
5
5
  require 'automux'
6
6
  require 'support/hash_factory'
7
7
  require 'support/factories'
8
+ require 'support/common_methods'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: automux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-02 00:00:00.000000000 Z
12
+ date: 2013-04-07 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Highly configurable Tmux Automator
15
15
  email:
@@ -31,10 +31,10 @@ files:
31
31
  - features/custom_recipes.feature
32
32
  - features/error_messages.feature
33
33
  - features/general_usage.feature
34
+ - features/hooks.feature
34
35
  - features/managing_blueprints.feature
35
36
  - features/runtime_options.feature
36
37
  - features/session_and_window_options.feature
37
- - features/session_hooks.feature
38
38
  - features/setup_windows.feature
39
39
  - features/step_definitions/custom_recipes_steps.rb
40
40
  - features/step_definitions/managing_blueprints_steps.rb
@@ -77,9 +77,18 @@ files:
77
77
  - lib/automux/initializers/setup_editor.rb
78
78
  - lib/automux/installation.rb
79
79
  - lib/automux/library.rb
80
+ - lib/automux/library/file_options_parser.rb
80
81
  - lib/automux/library/mini_erb.rb
81
82
  - lib/automux/library/yaml_parser.rb
83
+ - lib/automux/null.rb
84
+ - lib/automux/null/base.rb
85
+ - lib/automux/null/blueprint.rb
86
+ - lib/automux/null/recipe.rb
82
87
  - lib/automux/paths.rb
88
+ - lib/automux/redirector.rb
89
+ - lib/automux/redirector/blueprint.rb
90
+ - lib/automux/redirector/default.rb
91
+ - lib/automux/redirector/setup.rb
83
92
  - lib/automux/version.rb
84
93
  - lib/automux/views/blueprints/copy.sh.erb
85
94
  - lib/automux/views/blueprints/create.sh.erb
@@ -88,6 +97,7 @@ files:
88
97
  - lib/automux/views/blueprints/index.sh.erb
89
98
  - lib/automux/views/messages/error.sh.erb
90
99
  - lib/automux/views/setup/clone_defaults.sh.erb
100
+ - test/command_line.rb
91
101
  - test/session_test.rb
92
102
  - test/support/common_methods.rb
93
103
  - test/support/factories.rb
@@ -130,10 +140,10 @@ test_files:
130
140
  - features/custom_recipes.feature
131
141
  - features/error_messages.feature
132
142
  - features/general_usage.feature
143
+ - features/hooks.feature
133
144
  - features/managing_blueprints.feature
134
145
  - features/runtime_options.feature
135
146
  - features/session_and_window_options.feature
136
- - features/session_hooks.feature
137
147
  - features/setup_windows.feature
138
148
  - features/step_definitions/custom_recipes_steps.rb
139
149
  - features/step_definitions/managing_blueprints_steps.rb
@@ -142,6 +152,7 @@ test_files:
142
152
  - features/support/env.rb
143
153
  - features/support/hooks.rb
144
154
  - features/support/transformations.rb
155
+ - test/command_line.rb
145
156
  - test/session_test.rb
146
157
  - test/support/common_methods.rb
147
158
  - test/support/factories.rb