automux 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +25 -5
- data/bin/automux +6 -14
- data/data/automux/recipes/default.sh.erb +1 -1
- data/features/custom_recipes.feature +2 -2
- data/features/general_usage.feature +4 -4
- data/features/{session_hooks.feature → hooks.feature} +0 -0
- data/features/runtime_options.feature +18 -0
- data/features/setup_windows.feature +2 -2
- data/features/step_definitions/custom_recipes_steps.rb +0 -5
- data/features/step_definitions/shared_steps.rb +10 -0
- data/lib/automux.rb +2 -0
- data/lib/automux/cache.rb +1 -1
- data/lib/automux/cache/blueprint.rb +3 -1
- data/lib/automux/cache/recipe.rb +3 -1
- data/lib/automux/controller.rb +1 -1
- data/lib/automux/controller/base.rb +2 -2
- data/lib/automux/controller/blueprints.rb +1 -1
- data/lib/automux/controller/messages.rb +1 -1
- data/lib/automux/controller/recipes.rb +4 -4
- data/lib/automux/controller/support/rendering.rb +19 -18
- data/lib/automux/core.rb +2 -0
- data/lib/automux/core/blueprint.rb +3 -3
- data/lib/automux/core/error.rb +1 -1
- data/lib/automux/core/support/custom_accessors.rb +1 -1
- data/lib/automux/core/support/hooks_helper.rb +2 -5
- data/lib/automux/core/support/options_helper.rb +2 -5
- data/lib/automux/core/tmux/session.rb +28 -31
- data/lib/automux/core/tmux/window.rb +36 -28
- data/lib/automux/installation.rb +6 -6
- data/lib/automux/library.rb +1 -0
- data/lib/automux/library/file_options_parser.rb +37 -0
- data/lib/automux/library/mini_erb.rb +3 -3
- data/lib/automux/library/yaml_parser.rb +7 -21
- data/lib/automux/null.rb +8 -0
- data/lib/automux/null/base.rb +15 -0
- data/lib/automux/null/blueprint.rb +6 -0
- data/lib/automux/null/recipe.rb +6 -0
- data/lib/automux/redirector.rb +6 -0
- data/lib/automux/redirector/blueprint.rb +23 -0
- data/lib/automux/redirector/default.rb +32 -0
- data/lib/automux/redirector/setup.rb +12 -0
- data/lib/automux/version.rb +1 -1
- data/test/command_line.rb +7 -0
- data/test/session_test.rb +10 -5
- data/test/support/common_methods.rb +6 -0
- data/test/support/test_helper.rb +1 -0
- 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:'
|
167
|
+
panes: git pull origin '-r:'
|
168
168
|
```
|
169
169
|
|
170
|
-
|
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
|
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
|
-
=
|
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.
|
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
|
-
|
9
|
+
probable_class_name = ARGV[0].to_s.to_sym.capitalize
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
@@ -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 "
|
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
|
-
=
|
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
|
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:
|
89
|
-
tmux rename-window -t test:
|
90
|
-
tmux send-keys -t test:
|
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
|
-
|
|
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
data/lib/automux/cache.rb
CHANGED
@@ -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
|
data/lib/automux/cache/recipe.rb
CHANGED
@@ -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 ###
|
data/lib/automux/controller.rb
CHANGED
@@ -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 #{
|
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 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
|
-
|
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 #{
|
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
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
32
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
|
data/lib/automux/core/error.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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, :
|
9
|
+
attr_reader :data, :base_index
|
9
10
|
dup_attr_reader :windows, :hooks, :options
|
10
|
-
|
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
|
-
#
|
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
|
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
|
-
|
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
|
9
|
+
attr_reader :data, :session, :index
|
9
10
|
dup_attr_reader :panes, :hooks, :options
|
10
|
-
|
11
|
+
def_delegators :data, :name, :root, :layout
|
12
|
+
def_delegator :data, :is_optional, :is_optional?
|
11
13
|
|
12
|
-
def initialize(session,
|
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
|
-
|
26
|
-
|
27
|
-
end
|
23
|
+
class Data
|
24
|
+
attr_reader :opt, :index, :name, :root, :layout, :hooks, :options, :panes, :is_optional
|
28
25
|
|
29
|
-
|
30
|
-
|
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
|
34
|
-
|
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
|
44
|
-
|
47
|
+
def opted_in?
|
48
|
+
return true unless is_optional?
|
49
|
+
|
50
|
+
data.opt
|
45
51
|
end
|
46
52
|
|
47
|
-
def
|
48
|
-
|
53
|
+
def change_root_command
|
54
|
+
%[cd #{ root }]
|
49
55
|
end
|
50
56
|
|
51
|
-
|
52
|
-
return true if @opt.nil?
|
57
|
+
# :stopdoc:
|
53
58
|
|
54
|
-
|
59
|
+
def update_index
|
60
|
+
@index ||= session.next_available_window_index
|
55
61
|
end
|
56
62
|
|
57
|
-
def
|
58
|
-
|
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
|
76
|
+
[data.panes].flatten.each do |command|
|
69
77
|
pane = Automux::Core::Tmux::Pane.new(self, command)
|
70
78
|
@panes << pane
|
71
79
|
end
|
data/lib/automux/installation.rb
CHANGED
@@ -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
|
data/lib/automux/library.rb
CHANGED
@@ -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
|
-
|
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(
|
9
|
-
data_string = File.read(
|
10
|
-
opts_replaced_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,
|
26
|
-
|
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!(/['|"]
|
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
|
data/lib/automux/null.rb
ADDED
@@ -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
|
data/lib/automux/version.rb
CHANGED
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
|
data/test/support/test_helper.rb
CHANGED
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.
|
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-
|
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
|