dsu 0.1.0.alpha.5 → 1.1.0.alpha.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.
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