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