cli-mastermind 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9078a8e331150ebe62b1ecf44270422c93855b869510f34d57e983895a3b7fcf
4
- data.tar.gz: c7bb2f6a630aa6b62319e409f238b88a1a81a4baa3a8e76737b1290e15efd2fc
3
+ metadata.gz: c548ef96d5f0b89113a1110cae2deae76be3c15fd4380727fe74c84bcda29766
4
+ data.tar.gz: f189bc224bc60e7ee496b5704df921b3cfd0d37ecb831990889c2666305628b8
5
5
  SHA512:
6
- metadata.gz: 1ec54b9f8e61defa6dd76c40cdd6d46fbba1afb6e173e47f25e0042ed69b7ca4ae32d4dd75ca924af55c22f4a10e2f4f22d2ab907f71abac789e9b08248ed7f9
7
- data.tar.gz: ef03260db00aa0062ed9514ae5bd6e201274d89778dccafa1f74b94c1bf2566665513e4ae4fd638b1c717e1586990275d3c4786a3952b721d6bd74849c3a4554
6
+ metadata.gz: cc898bb8b3ade138634ebd11fbcd6ab830c60e874528759acbbf9c95ba42b2db7a7d66551d34de8f379a74842bdf2850c2e81860cd66310cddcab86a49ce591c
7
+ data.tar.gz: b2f01d7795e3b1ec527d1d3e74ab53b8f9fe250c4e647c7af004b2569b92a463ba11254d136eceb14fe06ea6c8963dd857ffbfc58075bec00a3d5e7963d0eb58
@@ -7,6 +7,8 @@ require 'cli/mastermind/errors'
7
7
  require 'cli/mastermind/user_interface'
8
8
  require 'cli/mastermind/loader'
9
9
  require 'cli/mastermind/plan'
10
+ require 'cli/mastermind/parent_plan'
11
+ require 'cli/mastermind/executable_plan'
10
12
  require 'cli/mastermind/version'
11
13
 
12
14
  module CLI
@@ -76,16 +76,7 @@ module CLI
76
76
  # Loads all plan files added using +add_plans+
77
77
  # @see Plan.load
78
78
  def load_plans
79
- @plans = {}
80
-
81
- top_level_plan = Plan.new('temporary_plan')
82
-
83
- @plan_files.each do |file|
84
- plans = Plan.load file
85
- top_level_plan.add_children plans
86
- end
87
-
88
- @plans = top_level_plan.children
79
+ @plans = Loader.load_all(@plan_files)
89
80
  end
90
81
 
91
82
  def execute_plan(*plan_stack, arguments: nil)
@@ -0,0 +1,14 @@
1
+ module CLI
2
+ module Mastermind
3
+ class ExecutablePlan
4
+ include Plan
5
+
6
+ def call(options=nil)
7
+ case @block.arity
8
+ when 1, -1 then instance_exec(options, &@block)
9
+ else instance_exec(&@block)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -27,6 +27,19 @@ module CLI::Mastermind
27
27
  def load(filename)
28
28
  raise NotImplementedError
29
29
  end
30
+
31
+ # Loads a particular plan from the filesystem.
32
+ def load_all(files)
33
+ temp_plan = ParentPlan.new('temporary plan')
34
+
35
+ plans = files.map do |file|
36
+ ext = File.extname(file)
37
+ loader = Loader.find_loader(ext)
38
+ temp_plan.add_children loader.load(file)
39
+ end
40
+
41
+ temp_plan.children
42
+ end
30
43
  end
31
44
  end
32
45
  end
@@ -31,7 +31,7 @@ module CLI::Mastermind
31
31
  end
32
32
 
33
33
  def plot(name, &block)
34
- plan = Plan.new name, @description, @filename
34
+ plan = ParentPlan.new name, @description, @filename
35
35
  @description = nil
36
36
  @plans << plan
37
37
  plan.add_children DSL.new(@filename, &block).plans
@@ -43,7 +43,7 @@ module CLI::Mastermind
43
43
  end
44
44
  alias_method :desc, :description
45
45
 
46
- def plan(name, plan_class = Plan, &block)
46
+ def plan(name, plan_class = ExecutablePlan, &block)
47
47
  @plans << plan_class.new(name, @description, @filename, &block)
48
48
  @description = nil
49
49
  end
@@ -0,0 +1,61 @@
1
+ module CLI
2
+ module Mastermind
3
+ class ParentPlan
4
+ include Plan
5
+
6
+ # Used in the interactive plan selector to display child plans
7
+ attr_reader :children
8
+
9
+ def initialize(name, description=nil, filename=nil, &block)
10
+ super
11
+
12
+ @children = {}
13
+ end
14
+
15
+ # Get the child plan with the specified +name+
16
+ def get_child(name)
17
+ @children[name]
18
+ end
19
+ alias_method :[], :get_child
20
+ alias_method :dig, :get_child
21
+
22
+ def add_children(plans)
23
+ raise InvalidPlanError, 'Cannot add child plans to a plan with an action' unless @block.nil?
24
+ plans.each(&method(:incorporate_plan))
25
+ end
26
+
27
+ def has_children?
28
+ true
29
+ end
30
+
31
+ private
32
+
33
+ def incorporate_plan(plan)
34
+ # If this namespace isn't taken just add the plan
35
+ if @children.has_key? plan.name
36
+
37
+ # Otherwise, we need to handle a name collision
38
+ existing_plan = @children[plan.name]
39
+
40
+ # If both plans have children, we merge them together
41
+ if existing_plan.has_children? and plan.has_children?
42
+ existing_plan.add_children plan.children.values
43
+
44
+ return existing_plan
45
+ end
46
+
47
+ # Otherwise, the plan defined later wins and overwrites the existing plan
48
+
49
+ # Warn the user that this is happening, unless we're running tests.
50
+ warn <<~PLAN_COLLISON.strip unless defined? RSpec
51
+ Plan name collision encountered when loading plans from "#{plan.filename}" that cannot be merged.
52
+ "#{plan.name}" was previously defined in "#{existing_plan.filename}".
53
+ Plans from "#{plan.filename}" will be used instead.
54
+ PLAN_COLLISON
55
+ end
56
+
57
+ @children[plan.name] = plan
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,78 +1,62 @@
1
- require 'cli/mastermind/plan/interface'
2
-
3
1
  module CLI
4
2
  module Mastermind
5
- class Plan
6
- include Interface
7
-
8
- # Used in the interactive plan selector to display child plans
9
- attr_reader :children
10
-
11
- # Loads a particular plan from the filesystem.
12
- # @see Loader
13
- def self.load(filename)
14
- ext = File.extname(filename)
15
- loader = Loader.find_loader(ext)
16
- loader.load(filename)
3
+ # The plan interface is everything that is required in order for an object
4
+ # to be usable as a plan.
5
+ #
6
+ # Objects adhering to this interface must implement their own +call+ method.
7
+ # This method is what is invoked by Mastermind to execute a plan.
8
+ #
9
+ # Mastermind assumes that any plan it encounters could have children, hence
10
+ # the +has_children?+ method here. Since the default PlanfileLoader doesn't
11
+ # permit custom plan classes when defining a plan with children, it's assumed
12
+ # that any custom plans (which include this interface) won't have any children
13
+ # at all.
14
+ module Plan
15
+ extend Forwardable
16
+
17
+ def self.included(base)
18
+ base.class_eval do
19
+ # The name of the plan. Used to specify the plan from the command line
20
+ # or from the interactive menu
21
+ attr_reader :name
22
+
23
+ # Displayed in the non-interactive list of available plans
24
+ attr_reader :description
25
+
26
+ # The file this plan was loaded from, if any
27
+ attr_reader :filename
28
+
29
+ # Provides shorter names for the plan
30
+ attr_reader :aliases
31
+
32
+ include UserInterface
33
+ end
17
34
  end
18
35
 
19
36
  def initialize(name, description=nil, filename=nil, &block)
20
- super
21
-
22
- @children = {}
23
- end
24
-
25
- # Get the child plan with the specified +name+
26
- def get_child(name)
27
- @children[name]
28
- end
29
- alias_method :[], :get_child
30
- alias_method :dig, :get_child
31
-
32
- def add_children(plans)
33
- raise InvalidPlanError, 'Cannot add child plans to a plan with an action' unless @block.nil?
34
- plans.each(&method(:incorporate_plan))
37
+ @name = name.to_s.freeze
38
+ @description = description.freeze
39
+ @filename = filename
40
+ @block = block
41
+ @aliases = Set.new
35
42
  end
36
43
 
37
44
  def has_children?
38
- @children.any?
45
+ false
39
46
  end
40
47
 
41
48
  def call(options=nil)
42
- case @block.arity
43
- when 1, -1 then instance_exec(options, &@block)
44
- else instance_exec(&@block)
45
- end
49
+ raise NotImplementedError
46
50
  end
47
51
 
48
- private
49
-
50
- def incorporate_plan(plan)
51
- # If this namespace isn't taken just add the plan
52
- if @children.has_key? plan.name
53
-
54
- # Otherwise, we need to handle a name collision
55
- existing_plan = @children[plan.name]
56
-
57
- # If both plans have children, we merge them together
58
- if existing_plan.has_children? and plan.has_children?
59
- existing_plan.add_children plan.children.values
60
-
61
- return existing_plan
62
- end
63
-
64
- # Otherwise, the plan defined later wins and overwrites the existing plan
65
-
66
- # Warn the user that this is happening, unless we're running tests.
67
- warn <<~PLAN_COLLISON.strip unless defined? RSpec
68
- Plan name collision encountered when loading plans from "#{plan.filename}" that cannot be merged.
69
- "#{plan.name}" was previously defined in "#{existing_plan.filename}".
70
- Plans from "#{plan.filename}" will be used instead.
71
- PLAN_COLLISON
72
- end
73
-
74
- @children[plan.name] = plan
52
+ def add_alias(alias_to)
53
+ config.define_alias(alias_to.to_s, name)
54
+ @aliases.add alias_to
75
55
  end
56
+
57
+ # Delegate configuration to the top-level configuration object
58
+ def_delegator :'CLI::Mastermind', :configuration
59
+ alias_method :config, :configuration
76
60
  end
77
61
  end
78
62
  end
@@ -7,7 +7,7 @@ module CLI
7
7
 
8
8
  module VERSION
9
9
  RELEASE = 0
10
- MAJOR = 6
10
+ MAJOR = 7
11
11
  MINOR = 0
12
12
  PATCH = nil
13
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cli-mastermind
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hall
@@ -77,10 +77,11 @@ files:
77
77
  - lib/cli/mastermind/arg_parse.rb
78
78
  - lib/cli/mastermind/configuration.rb
79
79
  - lib/cli/mastermind/errors.rb
80
+ - lib/cli/mastermind/executable_plan.rb
80
81
  - lib/cli/mastermind/loader.rb
81
82
  - lib/cli/mastermind/loader/planfile_loader.rb
83
+ - lib/cli/mastermind/parent_plan.rb
82
84
  - lib/cli/mastermind/plan.rb
83
- - lib/cli/mastermind/plan/interface.rb
84
85
  - lib/cli/mastermind/user_interface.rb
85
86
  - lib/cli/mastermind/version.rb
86
87
  homepage: https://github.com/chall8908/cli-mastermind
@@ -1,62 +0,0 @@
1
- module CLI::Mastermind
2
- class Plan
3
- # The plan interface is everything that is required in order for an object
4
- # to be usable as a plan.
5
- #
6
- # Objects adhering to this interface must implement their own +call+ method.
7
- # This method is what is invoked by Mastermind to execute a plan.
8
- #
9
- # Mastermind assumes that any plan it encounters could have children, hence
10
- # the +has_children?+ method here. Since the default PlanfileLoader doesn't
11
- # permit custom plan classes when defining a plan with children, it's assumed
12
- # that any custom plans (which include this interface) won't have any children
13
- # at all.
14
- module Interface
15
- extend Forwardable
16
-
17
- def self.included(base)
18
- base.class_eval do
19
- # The name of the plan. Used to specify the plan from the command line
20
- # or from the interactive menu
21
- attr_reader :name
22
-
23
- # Displayed in the non-interactive list of available plans
24
- attr_reader :description
25
-
26
- # The file this plan was loaded from, if any
27
- attr_reader :filename
28
-
29
- # Provides shorter names for the plan
30
- attr_reader :aliases
31
-
32
- include UserInterface
33
- end
34
- end
35
-
36
- def initialize(name, description=nil, filename=nil, &block)
37
- @name = name.to_s.freeze
38
- @description = description.freeze
39
- @filename = filename
40
- @block = block
41
- @aliases = Set.new
42
- end
43
-
44
- def has_children?
45
- false
46
- end
47
-
48
- def call(options=nil)
49
- raise NotImplementedError
50
- end
51
-
52
- def add_alias(alias_to)
53
- config.define_alias(alias_to.to_s, name)
54
- @aliases.add alias_to
55
- end
56
-
57
- # Delegate configuration to the top-level configuration object
58
- def_delegator :'CLI::Mastermind', :configuration
59
- alias_method :config, :configuration
60
- end
61
- end
62
- end