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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +6 -15
- data/README.md +33 -47
- data/lib/dsu/base_cli.rb +13 -6
- data/lib/dsu/cli.rb +46 -55
- data/lib/dsu/command_services/add_entry_service.rb +21 -21
- data/lib/dsu/core/ruby/not_today.rb +11 -0
- data/lib/dsu/models/entry.rb +32 -21
- data/lib/dsu/models/entry_group.rb +41 -105
- data/lib/dsu/services/configuration_loader_service.rb +19 -2
- data/lib/dsu/services/entry_group_editor_service.rb +37 -89
- data/lib/dsu/services/stdout_redirector_service.rb +27 -0
- data/lib/dsu/subcommands/list.rb +83 -15
- data/lib/dsu/support/colorable.rb +1 -0
- data/lib/dsu/support/command_options/dsu_times.rb +33 -0
- data/lib/dsu/support/command_options/time.rb +77 -0
- data/lib/dsu/support/command_options/time_mneumonic.rb +127 -0
- data/lib/dsu/support/command_options/time_mneumonics.rb +15 -0
- data/lib/dsu/support/configurable.rb +15 -0
- data/lib/dsu/support/configuration.rb +13 -1
- data/lib/dsu/support/entry_group_fileable.rb +31 -6
- data/lib/dsu/support/entry_group_loadable.rb +13 -16
- data/lib/dsu/support/entry_group_viewable.rb +26 -8
- data/lib/dsu/support/times_sortable.rb +1 -3
- data/lib/dsu/validators/description_validator.rb +38 -0
- data/lib/dsu/validators/entries_validator.rb +43 -32
- data/lib/dsu/validators/time_validator.rb +11 -20
- data/lib/dsu/version.rb +1 -1
- data/lib/dsu/views/edited_entries/shared/errors.rb +39 -0
- data/lib/dsu/views/entry_group/edit.rb +89 -39
- data/lib/dsu/views/entry_group/show.rb +10 -4
- data/lib/dsu/views/shared/messages.rb +56 -0
- data/lib/dsu.rb +8 -2
- metadata +24 -12
- data/lib/dsu/support/commander/command.rb +0 -130
- data/lib/dsu/support/commander/command_help.rb +0 -62
- data/lib/dsu/support/commander/subcommand.rb +0 -45
- 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/
|
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::
|
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
|
29
|
-
|
30
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
entry_group.entries.
|
53
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
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
|
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)}.
|
42
|
+
prefix = "#{format('%03s', index + 1)}. "
|
43
43
|
description = colorize_string(string: entry.description, mode: :bold)
|
44
44
|
entry_info = "#{prefix} #{description}"
|
45
|
-
|
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:
|
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-
|
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:
|
34
|
+
name: activemodel
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0
|
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
|
49
|
+
version: '7.0'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 7.0.4.3
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
54
|
+
name: colorize
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
50
56
|
requirements:
|
51
57
|
- - "~>"
|
52
58
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
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:
|
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/
|
169
|
-
- lib/dsu/support/
|
170
|
-
- lib/dsu/support/
|
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
|