automux 0.0.1
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.
- 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
|