automux 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +22 -0
- data/VERSION +1 -0
- data/automux.gemspec +18 -0
- data/bin/automux +22 -0
- data/data/automux/blueprints/default.yml +26 -0
- data/data/automux/recipes/default.sh.erb +46 -0
- data/features/custom_recipes.feature +63 -0
- data/features/error_messages.feature +8 -0
- data/features/general_usage.feature +180 -0
- data/features/managing_blueprints.feature +66 -0
- data/features/runtime_options.feature +84 -0
- data/features/session_and_window_options.feature +67 -0
- data/features/session_hooks.feature +68 -0
- data/features/setup_windows.feature +22 -0
- data/features/step_definitions/custom_recipes_steps.rb +9 -0
- data/features/step_definitions/managing_blueprints_steps.rb +9 -0
- data/features/step_definitions/setup_windows_steps.rb +18 -0
- data/features/step_definitions/shared_steps.rb +43 -0
- data/features/support/env.rb +8 -0
- data/features/support/hooks.rb +4 -0
- data/features/support/transformations.rb +6 -0
- data/lib/automux.rb +9 -0
- data/lib/automux/cache.rb +10 -0
- data/lib/automux/cache/blueprint.rb +20 -0
- data/lib/automux/cache/recipe.rb +27 -0
- data/lib/automux/controller.rb +14 -0
- data/lib/automux/controller/base.rb +18 -0
- data/lib/automux/controller/blueprints.rb +45 -0
- data/lib/automux/controller/messages.rb +11 -0
- data/lib/automux/controller/recipes.rb +39 -0
- data/lib/automux/controller/setup.rb +11 -0
- data/lib/automux/controller/support.rb +5 -0
- data/lib/automux/controller/support/filters.rb +55 -0
- data/lib/automux/controller/support/rendering.rb +54 -0
- data/lib/automux/core.rb +11 -0
- data/lib/automux/core/base.rb +7 -0
- data/lib/automux/core/blueprint.rb +31 -0
- data/lib/automux/core/error.rb +15 -0
- data/lib/automux/core/hook.rb +26 -0
- data/lib/automux/core/option.rb +20 -0
- data/lib/automux/core/recipe.rb +12 -0
- data/lib/automux/core/support.rb +6 -0
- data/lib/automux/core/support/custom_accessors.rb +15 -0
- data/lib/automux/core/support/hooks_helper.rb +28 -0
- data/lib/automux/core/support/options_helper.rb +18 -0
- data/lib/automux/core/tmux.rb +6 -0
- data/lib/automux/core/tmux/pane.rb +19 -0
- data/lib/automux/core/tmux/session.rb +137 -0
- data/lib/automux/core/tmux/window.rb +76 -0
- data/lib/automux/initializers.rb +2 -0
- data/lib/automux/initializers/custom_hooks.rb +4 -0
- data/lib/automux/initializers/setup_caches.rb +3 -0
- data/lib/automux/library.rb +5 -0
- data/lib/automux/library/mini_erb.rb +22 -0
- data/lib/automux/library/yaml_parser.rb +41 -0
- data/lib/automux/paths.rb +41 -0
- data/lib/automux/setup.rb +0 -0
- data/lib/automux/views/blueprints/copy.sh.erb +2 -0
- data/lib/automux/views/blueprints/create.sh.erb +2 -0
- data/lib/automux/views/blueprints/edit.sh.erb +1 -0
- data/lib/automux/views/messages/error.sh.erb +3 -0
- data/lib/automux/views/setup/clone_defaults.sh.erb +21 -0
- data/test/session_test.rb +16 -0
- data/test/support/common_methods.rb +0 -0
- data/test/support/factories.rb +13 -0
- data/test/support/hash_factory.rb +19 -0
- data/test/support/test_helper.rb +7 -0
- metadata +136 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
module Automux
|
2
|
+
module Controller
|
3
|
+
class Blueprints < Base
|
4
|
+
before_filter :load_blueprint, only: [:edit, :copy, :cp, :delete, :rm]
|
5
|
+
|
6
|
+
# blueprint_name.yml will be searched under $HOME/.automux/blueprints
|
7
|
+
# $ automux blueprint edit blueprint_name
|
8
|
+
def edit
|
9
|
+
@binding = @blueprint.get_binding
|
10
|
+
render 'edit'
|
11
|
+
end
|
12
|
+
|
13
|
+
# This copies the content from default.yml and opens the new file using $EDITOR
|
14
|
+
# $ automux blueprint create new_blueprint_name
|
15
|
+
def create
|
16
|
+
blueprint = Automux::Core::Blueprint.build_by_name(params[:name])
|
17
|
+
blueprint.source = Automux::Cache::Blueprint.find_by_name('default')
|
18
|
+
@binding = blueprint.get_binding
|
19
|
+
render 'create'
|
20
|
+
end
|
21
|
+
|
22
|
+
# $ automux blueprint copy source destination
|
23
|
+
def copy
|
24
|
+
clone_blueprint = Automux::Core::Blueprint.build_by_name(params[:clone_name])
|
25
|
+
clone_blueprint.source = @blueprint
|
26
|
+
@binding = clone_blueprint.get_binding
|
27
|
+
render 'copy'
|
28
|
+
end
|
29
|
+
alias_method :cp, :copy
|
30
|
+
|
31
|
+
# $ automux blueprint delete some_blueprint
|
32
|
+
def delete
|
33
|
+
@binding = @blueprint.get_binding
|
34
|
+
render 'delete'
|
35
|
+
end
|
36
|
+
alias_method :rm, :delete
|
37
|
+
|
38
|
+
private ###
|
39
|
+
|
40
|
+
def load_blueprint
|
41
|
+
@blueprint = Automux::Cache::Blueprint.find_by_name(params[:name])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Automux
|
2
|
+
module Controller
|
3
|
+
class Recipes < Base
|
4
|
+
before_filter :load_recipe, only: :automate
|
5
|
+
before_filter :load_blueprint, only: :automate
|
6
|
+
before_filter :check_blueprint, only: :automate
|
7
|
+
before_filter :check_recipe, only: :automate
|
8
|
+
before_filter :load_and_setup_session, only: :automate
|
9
|
+
|
10
|
+
def automate
|
11
|
+
@binding = @session.get_binding
|
12
|
+
render @recipe.path
|
13
|
+
end
|
14
|
+
|
15
|
+
private ###
|
16
|
+
|
17
|
+
def load_recipe
|
18
|
+
@recipe = Automux::Cache::Recipe.find_by_name(params[:recipe_name])
|
19
|
+
end
|
20
|
+
|
21
|
+
def load_blueprint
|
22
|
+
@blueprint = Automux::Cache::Blueprint.find_by_name(params[:blueprint_name])
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_blueprint
|
26
|
+
notify_error "Unable to find blueprint named #{ params[:blueprint_name] }.yml" if @blueprint.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_recipe
|
30
|
+
notify_error "Unable to find recipe named #{ params[:recipe_name] }.sh.erb" if @recipe.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_and_setup_session
|
34
|
+
@session = Automux::Core::Tmux::Session.new(@blueprint.read)
|
35
|
+
@session.setup
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Automux
|
2
|
+
module Controller
|
3
|
+
module Support
|
4
|
+
module Filters
|
5
|
+
attr_reader :filters
|
6
|
+
private :filters
|
7
|
+
|
8
|
+
# Filters is included in the Base controller and all the following methods are intended for its subclasses.
|
9
|
+
def inherited(base)
|
10
|
+
base.instance_variable_set '@filters', {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# before_filter does not define its logic right away.
|
14
|
+
def before_filter(filter_name, options)
|
15
|
+
[options[:only]].flatten.each do |action|
|
16
|
+
add_filter(filter_name, action)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This is a custom hook intended to run after the subclass definition is read.
|
21
|
+
# This helps in calling the before_filter at the top but defining its logic later.
|
22
|
+
# See: automux/initializers/custom_hooks.rb for invocation.
|
23
|
+
def after_inherited(base)
|
24
|
+
# E.g. filters = { automate: [:load_recipe, :load_session], edit: [:load_recipe] }
|
25
|
+
base.class_eval do
|
26
|
+
# |automate, [:load_recipe, :load_session]|
|
27
|
+
filters.each_pair do |name, filter_list|
|
28
|
+
|
29
|
+
# def automate_with_filters
|
30
|
+
# load_recipe
|
31
|
+
# load_session
|
32
|
+
# automate_without_filters
|
33
|
+
# end
|
34
|
+
define_method "#{ name }_with_filters" do
|
35
|
+
filter_list.each { |filter_name| send(filter_name) }
|
36
|
+
send("#{ name }_without_filters")
|
37
|
+
end
|
38
|
+
|
39
|
+
# alias_method_chain automate, filters
|
40
|
+
alias_method "#{ name }_without_filters", name
|
41
|
+
alias_method name, "#{ name }_with_filters"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private ###
|
47
|
+
|
48
|
+
def add_filter(filter_name, action)
|
49
|
+
filters[action] ||= []
|
50
|
+
filters[action] << filter_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Automux
|
2
|
+
module Controller
|
3
|
+
module Support
|
4
|
+
module Rendering
|
5
|
+
|
6
|
+
# There are two requirements to render a file.
|
7
|
+
# 1. @binding
|
8
|
+
# 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)
|
19
|
+
end
|
20
|
+
|
21
|
+
private ###
|
22
|
+
|
23
|
+
# The full file path will be deduced using current controller name.
|
24
|
+
# So for Blueprints, the file will be searched under $HOME/.automux/blueprints.
|
25
|
+
# The file will be a bash script with erb support. Hence the need of a @binding object.
|
26
|
+
def deduce_full_path(view)
|
27
|
+
views_folder_name = demodulize(self.class.name).downcase
|
28
|
+
File.join(Paths.root, Paths.views, views_folder_name, "#{ view }.sh.erb")
|
29
|
+
end
|
30
|
+
|
31
|
+
def execute(result)
|
32
|
+
modified_result = remove_empty_lines(result)
|
33
|
+
|
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
|
40
|
+
end
|
41
|
+
|
42
|
+
# The recipe files can have empty lines for clarity. Remove them here.
|
43
|
+
def remove_empty_lines(string)
|
44
|
+
string.split("\n").reject { |text| text.strip.empty? }.join("\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
# Remove all parent namespacing.
|
48
|
+
def demodulize(class_name)
|
49
|
+
class_name.split('::').last
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/automux/core.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'automux/core/support'
|
2
|
+
require 'automux/core/base'
|
3
|
+
require 'automux/core/hook'
|
4
|
+
require 'automux/core/option'
|
5
|
+
require 'automux/core/tmux'
|
6
|
+
require 'automux/core/recipe'
|
7
|
+
require 'automux/core/blueprint'
|
8
|
+
require 'automux/core/error'
|
9
|
+
|
10
|
+
module Automux::Core
|
11
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Automux
|
2
|
+
module Core
|
3
|
+
class Blueprint < Base
|
4
|
+
attr_reader :name, :path, :source_blueprint
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@name = File.basename(path, '.yml')
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def read
|
12
|
+
Automux::Library::YamlParser.load_file(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_binding
|
16
|
+
binding
|
17
|
+
end
|
18
|
+
|
19
|
+
def source=(blueprint)
|
20
|
+
@source_blueprint = blueprint
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def build_by_name(name)
|
25
|
+
path = File.join(Automux::Paths.blueprints_container, "#{ name }.yml")
|
26
|
+
new(path)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Automux
|
4
|
+
module Core
|
5
|
+
class Hook
|
6
|
+
PRE = 2
|
7
|
+
POST = 4
|
8
|
+
|
9
|
+
attr_reader :command, :type
|
10
|
+
private :type
|
11
|
+
|
12
|
+
def initialize(target, type, command)
|
13
|
+
@type = self.class.const_get(type.upcase)
|
14
|
+
@command = ERB.new(command).result(target.get_binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
def pre?
|
18
|
+
type == PRE
|
19
|
+
end
|
20
|
+
|
21
|
+
def post?
|
22
|
+
type == POST
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Automux
|
2
|
+
module Core
|
3
|
+
class Option
|
4
|
+
attr_reader :name, :value
|
5
|
+
|
6
|
+
BOOLEAN_DICTIONARY = { 'true' => :on, 'false' => :off }
|
7
|
+
|
8
|
+
def initialize(name, value)
|
9
|
+
@name = name
|
10
|
+
@value = translate_booleans(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
private ###
|
14
|
+
|
15
|
+
def translate_booleans(value)
|
16
|
+
value.to_s.gsub(/(true|false)/, BOOLEAN_DICTIONARY)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Automux
|
2
|
+
module Core
|
3
|
+
module Support
|
4
|
+
module HooksHelper
|
5
|
+
attr_reader :data_hooks
|
6
|
+
private :data_hooks
|
7
|
+
|
8
|
+
def pre_hooks
|
9
|
+
hooks.select(&:pre?)
|
10
|
+
end
|
11
|
+
|
12
|
+
def post_hooks
|
13
|
+
hooks.select(&:post?)
|
14
|
+
end
|
15
|
+
|
16
|
+
private ###
|
17
|
+
|
18
|
+
def setup_hooks
|
19
|
+
data_hooks.each do |type, commands|
|
20
|
+
[commands].flatten.each do |command|
|
21
|
+
@hooks << Hook.new(self, type, command)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Automux
|
2
|
+
module Core
|
3
|
+
module Support
|
4
|
+
module OptionsHelper
|
5
|
+
attr_reader :data_options
|
6
|
+
private :data_options
|
7
|
+
|
8
|
+
private ###
|
9
|
+
|
10
|
+
def setup_options
|
11
|
+
data_options.each do |name, value|
|
12
|
+
@options << Automux::Core::Option.new(name, value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|