cli-mastermind 0.6.0 → 0.7.0

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