dsu 0.1.0.alpha.5 → 1.1.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile.lock +6 -15
  5. data/README.md +33 -47
  6. data/lib/dsu/base_cli.rb +13 -6
  7. data/lib/dsu/cli.rb +46 -55
  8. data/lib/dsu/command_services/add_entry_service.rb +21 -21
  9. data/lib/dsu/core/ruby/not_today.rb +11 -0
  10. data/lib/dsu/models/entry.rb +32 -21
  11. data/lib/dsu/models/entry_group.rb +41 -105
  12. data/lib/dsu/services/configuration_loader_service.rb +19 -2
  13. data/lib/dsu/services/entry_group_editor_service.rb +37 -89
  14. data/lib/dsu/services/stdout_redirector_service.rb +27 -0
  15. data/lib/dsu/subcommands/list.rb +83 -15
  16. data/lib/dsu/support/colorable.rb +1 -0
  17. data/lib/dsu/support/command_options/dsu_times.rb +33 -0
  18. data/lib/dsu/support/command_options/time.rb +77 -0
  19. data/lib/dsu/support/command_options/time_mneumonic.rb +127 -0
  20. data/lib/dsu/support/command_options/time_mneumonics.rb +15 -0
  21. data/lib/dsu/support/configurable.rb +15 -0
  22. data/lib/dsu/support/configuration.rb +13 -1
  23. data/lib/dsu/support/entry_group_fileable.rb +31 -6
  24. data/lib/dsu/support/entry_group_loadable.rb +13 -16
  25. data/lib/dsu/support/entry_group_viewable.rb +26 -8
  26. data/lib/dsu/support/times_sortable.rb +1 -3
  27. data/lib/dsu/validators/description_validator.rb +38 -0
  28. data/lib/dsu/validators/entries_validator.rb +43 -32
  29. data/lib/dsu/validators/time_validator.rb +11 -20
  30. data/lib/dsu/version.rb +1 -1
  31. data/lib/dsu/views/edited_entries/shared/errors.rb +39 -0
  32. data/lib/dsu/views/entry_group/edit.rb +89 -39
  33. data/lib/dsu/views/entry_group/show.rb +10 -4
  34. data/lib/dsu/views/shared/messages.rb +56 -0
  35. data/lib/dsu.rb +8 -2
  36. metadata +24 -12
  37. data/lib/dsu/support/commander/command.rb +0 -130
  38. data/lib/dsu/support/commander/command_help.rb +0 -62
  39. data/lib/dsu/support/commander/subcommand.rb +0 -45
  40. data/lib/dsu/support/interactive/cli.rb +0 -161
@@ -1,19 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
4
- require 'active_support/core_ext/numeric/time'
5
3
  require_relative '../../models/entry_group'
6
- require_relative '../../support/colorable'
7
- require_relative '../../support/say'
8
- require_relative '../../support/time_formatable'
4
+ require_relative '../../support/configurable'
9
5
 
10
6
  module Dsu
11
7
  module Views
12
8
  module EntryGroup
13
9
  class Edit
14
- include Support::Colorable
15
- include Support::Say
16
- include Support::TimeFormatable
10
+ include Support::Configurable
17
11
 
18
12
  def initialize(entry_group:, options: {})
19
13
  raise ArgumentError, 'entry_group is nil' if entry_group.nil?
@@ -25,46 +19,102 @@ module Dsu
25
19
  @options = options || {}
26
20
  end
27
21
 
28
- def call
29
- # Just in case the entry group is invalid, we'll
30
- # validate it before displaying it.
22
+ def render
23
+ puts render_as_string
24
+ end
25
+
26
+ def render_as_string
27
+ # Just in case the entry group is invalid, we'll validate it before displaying it.
31
28
  entry_group.validate!
32
- render_entry_group!
33
- rescue ActiveModel::ValidationError
34
- puts "Error(s) encountered: #{entry_group.errors.full_messages}"
35
- raise
29
+
30
+ <<~EDIT_VIEW
31
+ #{banner_line}
32
+ # Editing DSU Entries for #{entry_group.time_formatted}
33
+ #{banner_line}
34
+
35
+ #{entry_group_view&.chomp}
36
+
37
+ #{banner_line}
38
+ # INSTRUCTIONS
39
+ #{banner_line}
40
+ # ADD a DSU entry: type an ENTRY DESCRIPTION on a new line.
41
+ # EDIT a DSU entry: change the existing ENTRY DESCRIPTION.
42
+ # DELETE a DSU entry: delete the ENTRY DESCRIPTION.
43
+ # NOTE: deleting all of the ENTRY DESCRIPTIONs will delete the entry group file;
44
+ # this is preferable if this is what you want to do :)
45
+ # REORDER a DSU entry: reorder the ENTRY DESCRIPTIONs in order preference.
46
+ #
47
+ # *** When you are done, save and close your editor ***
48
+ #{banner_line}
49
+ EDIT_VIEW
36
50
  end
37
- alias render call
38
51
 
39
52
  private
40
53
 
41
54
  attr_reader :entry_group, :options
42
55
 
43
- def render_entry_group!
44
- say "# Editing DSU Entries for #{formatted_time(time: entry_group.time)}"
45
- # TODO: Display entry group entries from the previous DSU date so they can be
46
- # easily copied over; or, add them to the current entry group entries below as
47
- # a "# [+|a|add] <entry group from previous DSU entry description>" (e.g. commented
48
- # out) by default?
49
- say ''
50
- say '# [SHA/COMMAND] [DESCRIPTION]'
51
-
52
- entry_group.entries.each do |entry|
53
- say "#{entry.uuid} #{entry.description.strip}"
56
+ def time
57
+ @time ||= entry_group.time
58
+ end
59
+
60
+ def banner_line
61
+ '#' * 80
62
+ end
63
+
64
+ def entry_group_view
65
+ return entry_group_entry_lines if entry_group.entries.any?
66
+ return previous_entry_group_entry_lines if carry_over_entries_to_today? && previous_entry_group?
67
+
68
+ <<~EDIT_VIEW
69
+ #{banner_line}
70
+ # ENTER DSU ENTRIES BELOW
71
+ #{banner_line}
72
+
73
+ EDIT_VIEW
74
+ end
75
+
76
+ def entry_group_entry_lines
77
+ raise 'No entries in entry group' if entry_group.entries.empty?
78
+
79
+ <<~EDIT_VIEW
80
+ #{banner_line}
81
+ # DSU ENTRIES
82
+ #{banner_line}
83
+
84
+ #{entry_group.entries.map(&:description).join("\n").chomp}
85
+ EDIT_VIEW
86
+ end
87
+
88
+ def previous_entry_group_entry_lines
89
+ raise 'carry_over_entries_to_today? is false' unless carry_over_entries_to_today?
90
+ raise 'Entries exist in entry_group' if entry_group.entries.any?
91
+ raise 'No previous entry group exists' unless previous_entry_group?
92
+
93
+ <<~EDIT_VIEW
94
+ #{banner_line}
95
+ # PREVIOUS DSU ENTRIES FROM #{previous_entry_group.time_formatted}
96
+ #{banner_line}
97
+
98
+ #{previous_entry_group.entries.map(&:description).join("\n").chomp}
99
+ EDIT_VIEW
100
+ end
101
+
102
+ def previous_entry_group?
103
+ previous_entry_group.present?
104
+ end
105
+
106
+ def previous_entry_group
107
+ # Go back a max of 7 days to find the previous entry group.
108
+ # TODO: Make this configurable or accept an option?
109
+ @previous_entry_group ||= (1..7).each do |days|
110
+ t = time.days_ago(days)
111
+ return Models::EntryGroup.load(time: t) if Support::EntryGroupFileable.entry_group_file_exists?(time: t)
54
112
  end
113
+ nil
114
+ end
55
115
 
56
- say ''
57
- say '# INSTRUCTIONS:'
58
- say '# ADD a DSU entry: use one of the following commands: [+|a|add] ' \
59
- 'followed by the description.'
60
- say '# EDIT a DSU entry: change the description.'
61
- say '# DELETE a DSU entry: delete the entry or replace the sha with one ' \
62
- 'of the following commands: [-|d|delete].'
63
- say '# NOTE: deleting all the entries will delete the entry group file; '
64
- say '# this is preferable if this is what you want to do :)'
65
- say '# REORDER a DSU entry: reorder the DSU entries in order preference.'
66
- say '#'
67
- say '# *** When you are done, save and close your editor ***'
116
+ def carry_over_entries_to_today?
117
+ configuration[:carry_over_entries_to_today]
68
118
  end
69
119
  end
70
120
  end
@@ -26,7 +26,7 @@ module Dsu
26
26
  end
27
27
 
28
28
  def call
29
- render_entry_group!
29
+ render!
30
30
  end
31
31
  alias render call
32
32
 
@@ -34,18 +34,24 @@ module Dsu
34
34
 
35
35
  attr_reader :entry_group, :options
36
36
 
37
- def render_entry_group!
37
+ def render!
38
38
  say formatted_time(time: entry_group.time), HIGHLIGHT
39
39
  say('(no entries available for this day)') and return if entry_group.entries.empty?
40
40
 
41
41
  entry_group.entries.each_with_index do |entry, index|
42
- prefix = "#{format('%03s', index + 1)}. #{entry.uuid}"
42
+ prefix = "#{format('%03s', index + 1)}. "
43
43
  description = colorize_string(string: entry.description, mode: :bold)
44
44
  entry_info = "#{prefix} #{description}"
45
- entry_info = "#{entry_info} (validation failed)" unless entry.valid?
45
+ unless entry.valid?
46
+ entry_info = "#{entry_info} (validation failed: #{entry_errors(entry_group_deleter_service)})"
47
+ end
46
48
  say entry_info
47
49
  end
48
50
  end
51
+
52
+ def entry_errors(entry)
53
+ entry.errors.full_messages.join(', ')
54
+ end
49
55
  end
50
56
  end
51
57
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../support/colorable'
4
+ require_relative '../../support/say'
5
+
6
+ module Dsu
7
+ module Views
8
+ module Shared
9
+ class Messages
10
+ include Support::Colorable
11
+ include Support::Say
12
+
13
+ MESSAGE_TYPES = %i[error info success warning].freeze
14
+
15
+ def initialize(messages:, message_type:, options: {})
16
+ messages = [messages] unless messages.is_a?(Array)
17
+
18
+ validate_arguments!(messages, message_type, options)
19
+
20
+ @messages = messages.select(&:present?)
21
+ @message_type = message_type
22
+ # We've inluded Support::Colorable, so simply upcase the message_type
23
+ # and convert it to a symbol; this will equate to the color we want.
24
+ @message_color = self.class.const_get(message_type.to_s.upcase)
25
+ @options = options || {}
26
+ @header = options[:header]
27
+ end
28
+
29
+ def render
30
+ return if messages.empty?
31
+
32
+ say header, message_color if header.present?
33
+
34
+ messages.each_with_index do |message, index|
35
+ say "#{index + 1}. #{message}", message_color
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :messages, :message_color, :message_type, :header, :options
42
+
43
+ def validate_arguments!(messages, message_type, options)
44
+ raise ArgumentError, 'messages is nil' if messages.nil?
45
+ raise ArgumentError, 'messages is the wrong object type' unless messages.is_a?(Array)
46
+ raise ArgumentError, 'messages elements are the wrong object type' unless messages.all?(String)
47
+ raise ArgumentError, 'message_type is nil' if message_type.nil?
48
+ raise ArgumentError, 'message_type is the wrong object type' unless message_type.is_a?(Symbol)
49
+ raise ArgumentError, 'message_type is not a valid message type' unless MESSAGE_TYPES.include?(message_type)
50
+ raise ArgumentError, 'options is nil' if options.nil?
51
+ raise ArgumentError, 'options is the wrong object type' unless options.is_a?(Hash)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
data/lib/dsu.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
4
- require 'active_support/core_ext/object/blank'
5
3
  require 'active_support/core_ext/hash/indifferent_access'
6
4
  require 'active_support/core_ext/numeric/time'
5
+ require 'active_support/core_ext/object/blank'
6
+ require 'pry-byebug' if ENV['DEV_ENV']
7
+ require 'thor'
8
+ require 'time'
9
+
10
+ Dir.glob("#{__dir__}/lib/core/**/*.rb").each do |file|
11
+ require file
12
+ end
7
13
 
8
14
  Dir.glob("#{__dir__}/dsu/**/*.rb").each do |file|
9
15
  require file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dsu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha.5
4
+ version: 1.1.0.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gene M. Angelo, Jr.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-12 00:00:00.000000000 Z
11
+ date: 2023-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -31,33 +31,39 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: 7.0.4
33
33
  - !ruby/object:Gem::Dependency
34
- name: colorize
34
+ name: activemodel
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.8.1
39
+ version: '7.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 7.0.4.3
40
43
  type: :runtime
41
44
  prerelease: false
42
45
  version_requirements: !ruby/object:Gem::Requirement
43
46
  requirements:
44
47
  - - "~>"
45
48
  - !ruby/object:Gem::Version
46
- version: 0.8.1
49
+ version: '7.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 7.0.4.3
47
53
  - !ruby/object:Gem::Dependency
48
- name: deco_lite
54
+ name: colorize
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
57
  - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '1.3'
59
+ version: 0.8.1
54
60
  type: :runtime
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
57
63
  requirements:
58
64
  - - "~>"
59
65
  - !ruby/object:Gem::Version
60
- version: '1.3'
66
+ version: 0.8.1
61
67
  - !ruby/object:Gem::Dependency
62
68
  name: os
63
69
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +155,7 @@ files:
149
155
  - lib/dsu/base_cli.rb
150
156
  - lib/dsu/cli.rb
151
157
  - lib/dsu/command_services/add_entry_service.rb
158
+ - lib/dsu/core/ruby/not_today.rb
152
159
  - lib/dsu/models/entry.rb
153
160
  - lib/dsu/models/entry_group.rb
154
161
  - lib/dsu/services/configuration_loader_service.rb
@@ -158,6 +165,7 @@ files:
158
165
  - lib/dsu/services/entry_group_reader_service.rb
159
166
  - lib/dsu/services/entry_group_writer_service.rb
160
167
  - lib/dsu/services/entry_hydrator_service.rb
168
+ - lib/dsu/services/stdout_redirector_service.rb
161
169
  - lib/dsu/services/temp_file_reader_service.rb
162
170
  - lib/dsu/services/temp_file_writer_service.rb
163
171
  - lib/dsu/subcommands/config.rb
@@ -165,9 +173,11 @@ files:
165
173
  - lib/dsu/subcommands/list.rb
166
174
  - lib/dsu/support/ask.rb
167
175
  - lib/dsu/support/colorable.rb
168
- - lib/dsu/support/commander/command.rb
169
- - lib/dsu/support/commander/command_help.rb
170
- - lib/dsu/support/commander/subcommand.rb
176
+ - lib/dsu/support/command_options/dsu_times.rb
177
+ - lib/dsu/support/command_options/time.rb
178
+ - lib/dsu/support/command_options/time_mneumonic.rb
179
+ - lib/dsu/support/command_options/time_mneumonics.rb
180
+ - lib/dsu/support/configurable.rb
171
181
  - lib/dsu/support/configuration.rb
172
182
  - lib/dsu/support/descriptable.rb
173
183
  - lib/dsu/support/entry_group_fileable.rb
@@ -175,15 +185,17 @@ files:
175
185
  - lib/dsu/support/entry_group_viewable.rb
176
186
  - lib/dsu/support/field_errors.rb
177
187
  - lib/dsu/support/folder_locations.rb
178
- - lib/dsu/support/interactive/cli.rb
179
188
  - lib/dsu/support/say.rb
180
189
  - lib/dsu/support/time_formatable.rb
181
190
  - lib/dsu/support/times_sortable.rb
191
+ - lib/dsu/validators/description_validator.rb
182
192
  - lib/dsu/validators/entries_validator.rb
183
193
  - lib/dsu/validators/time_validator.rb
184
194
  - lib/dsu/version.rb
195
+ - lib/dsu/views/edited_entries/shared/errors.rb
185
196
  - lib/dsu/views/entry_group/edit.rb
186
197
  - lib/dsu/views/entry_group/show.rb
198
+ - lib/dsu/views/shared/messages.rb
187
199
  - sig/dsu.rbs
188
200
  homepage: https://github.com/gangelo/dsu
189
201
  licenses:
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'command_help'
4
- require_relative 'subcommand'
5
-
6
- module Dsu
7
- module Support
8
- module Commander
9
- # https://www.toptal.com/ruby/ruby-dsl-metaprogramming-guide
10
- module Command
11
- class << self
12
- def included(base)
13
- base.extend ClassMethods
14
- base.engine.command_namespace to_command_namespace_symbol base.name
15
- base.engine.command_prompt base.engine.command_namespace
16
- binding.pry
17
- base.singleton_class.delegate :command_namespace, :command_namespaces, :commands,
18
- :command_add, :command_subcommand_add, :command_prompt, :command_parent,
19
- :help, to: :engine
20
- end
21
-
22
- private
23
-
24
- def to_command_namespace_symbol(namespace, join_token: '_')
25
- namespace.delete(':').split(/(?=[A-Z])/).join(join_token).downcase
26
- end
27
- end
28
-
29
- module ClassMethods
30
- def command_subcommand_create(command_parent:)
31
- new.tap do |subcommand|
32
- subcommand.extend Subcommand
33
- subcommand.command_parent command_parent
34
- end
35
- end
36
-
37
- def engine
38
- @engine ||= Engine.new(owning_command: self)
39
- end
40
-
41
- class Engine
42
- include CommandHelp
43
-
44
- attr_reader :owning_command
45
-
46
- def initialize(owning_command:)
47
- @owning_command = owning_command
48
- end
49
-
50
- def command_add(command:, desc:, long_desc: nil, options: {}, commands: [])
51
- self.commands[command_namespace] ||= {}
52
- self.commands[command_namespace][command] = {
53
- desc: desc,
54
- long_desc: long_desc,
55
- options: options,
56
- commands: commands,
57
- help: command_help_for(command: command, desc: desc,
58
- long_desc: long_desc, options: options, commands: commands)
59
- }
60
- end
61
-
62
- def command_subcommand_add(subcommand, command_parent: nil)
63
- command_parent ||= @owning_command
64
- subcommand = subcommand.command_subcommand_create command_parent: command_parent
65
- commands[command_namespace] ||= {}
66
- binding.pry
67
- subcommand.command_namespaces.each_with_index do |namespace, index|
68
- next if index.zero?
69
-
70
- target = commands.dig(*subcommand.command_namespaces[1..index])
71
- target ||= commands.dig(*subcommand.command_namespaces[0..index - 1])
72
- target[namespace] ||= {}
73
- end
74
- commands.dig(*subcommand.command_namespaces[0..])[subcommand.command_namespaces.last] = subcommand
75
-
76
- # subcommand.commands.each do |command_namespace, command|
77
- # command.each do |subcommand_command, data|
78
- # commands[self.command_namespace][command_namespace] ||= {}
79
- # commands[self.command_namespace][command_namespace][subcommand_command] = {
80
- # desc: data[:desc],
81
- # long_desc: data[:long_desc],
82
- # options: data[:options],
83
- # commands: data[:commands],
84
- # help: command_help_for(command: subcommand_command, namespaces: subcommand.command_namespaces, desc: data[:desc],
85
- # long_desc: data[:long_desc], options: data[:options], commands: data[:commands])
86
- # }
87
- # end
88
- # end
89
- end
90
-
91
- def command_namespaces(namespaces = [])
92
- command_parent&.command_namespaces(namespaces)
93
-
94
- namespaces << command_namespace
95
- namespaces
96
- end
97
-
98
- def command_namespace(namespace = nil)
99
- return @command_namespace || name if namespace.nil?
100
-
101
- @command_namespace = namespace
102
- end
103
-
104
- def command_prompt(value = nil)
105
- return @command_prompt || name if value.nil?
106
-
107
- @command_prompt = value
108
- end
109
-
110
- def command_parent(parent = nil)
111
- return @command_parent if parent.nil?
112
-
113
- @command_parent = parent
114
- end
115
-
116
- def commands
117
- @commands ||= {}
118
- end
119
-
120
- def help
121
- commands.each do |_command, command_data|
122
- puts "#{command_namespaces.join(' ')} #{command_data[:help]}"
123
- end
124
- end
125
- end
126
- end
127
- end
128
- end
129
- end
130
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dsu
4
- module Support
5
- module Commander
6
- module CommandHelp
7
- private
8
-
9
- # rubocop:disable Lint/UnusedMethodArgument
10
- def command_help_for(command:, desc:, namespaces: nil, long_desc: nil, options: {}, commands: [])
11
- namespaces ||= command_namespaces
12
- help =
13
- <<~HELP
14
- #{namespaces&.join(' ')} #{command}#{' [OPTIONS]' if options&.any?} - #{desc}
15
- #{'OPTIONS:' if options&.any?}
16
- #{options_help_for options}
17
- #{'OPTION ALIASES:' if any_option_aliases_for?(options)}
18
- #{options_aliases_help_for options}
19
- #{'---' unless long_desc.blank?}
20
- #{long_desc}
21
- HELP
22
- help.gsub(/\n{2,}/, "\n")
23
- end
24
- # rubocop:enable Lint/UnusedMethodArgument
25
-
26
- def options_help_for(options)
27
- return [] if options.blank?
28
-
29
- options.map do |option, data|
30
- type = option_to_a(data[:type])&.join(' | ')
31
- type = :boolean if type.blank?
32
- "#{option} <#{type}>, default: #{data[:default]}"
33
- end.join("\n")
34
- end
35
-
36
- def options_aliases_help_for(options)
37
- return unless any_option_aliases_for?(options)
38
-
39
- options.filter_map do |option, data|
40
- aliases = option_to_a(data[:aliases])&.join(' | ')
41
- <<~HELP
42
- #{option} aliases: [#{aliases}]
43
- HELP
44
- end.join("\n")
45
- end
46
-
47
- def any_option_aliases_for?(options)
48
- return false if options.blank?
49
-
50
- options.keys.any? { |key| options.dig(key, :aliases).any? }
51
- end
52
-
53
- def option_to_a(option)
54
- return [] if option.blank?
55
- return option if option.is_a? Array
56
-
57
- [option]
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dsu
4
- module Support
5
- module Commander
6
- # Subcommands should extend this module once they are instantiated
7
- # so that the Subcommand instance has access to all necessary
8
- # class methods for this subcommand to work.
9
- module Subcommand
10
- class << self
11
- def extended(mod)
12
- mod.singleton_class.delegate :command_namespace, :commands,
13
- :command_add, :command_subcommand_add, :command_prompt, :help, to: mod.class
14
- end
15
- end
16
-
17
- # Subcommand-specific instance methods.
18
- #
19
- # Define Subcommand-specific method equivalents of the Command class
20
- # methods needed to make this Subcommand instance unique.
21
-
22
- # def command_namespace(namespace = nil)
23
- # return @command_namespace || name if namespace.nil?
24
-
25
- # @command_namespace = namespace
26
- # end
27
-
28
- # Subcommands can be used by any Command, so the :command_parent needs
29
- # to be unique to this Subcommand instance.
30
- def command_parent(parent = nil)
31
- return @command_prompt if parent.nil?
32
-
33
- @command_prompt = parent
34
- end
35
-
36
- def command_namespaces(namespaces = [])
37
- command_parent&.command_namespaces(namespaces)
38
-
39
- namespaces << command_namespace
40
- namespaces
41
- end
42
- end
43
- end
44
- end
45
- end