dsu 1.2.1 → 2.0.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/CHANGELOG.md +55 -21
- data/Gemfile.lock +7 -7
- data/README.md +28 -35
- data/bin/console +23 -1
- data/bin/dsu +3 -0
- data/bin/setup +14 -3
- data/exe/dsu +23 -1
- data/exe/dsu_migrate.rb +43 -0
- data/lib/core/ruby/color_theme_colors.rb +16 -0
- data/lib/core/ruby/color_theme_mode.rb +42 -0
- data/lib/core/ruby/not_today.rb +7 -0
- data/lib/core/ruby/wrap_and_join.rb +31 -0
- data/lib/dsu/base_cli.rb +19 -23
- data/lib/dsu/cli.rb +47 -37
- data/lib/dsu/command_services/add_entry_service.rb +10 -21
- data/lib/dsu/crud/json_file.rb +139 -0
- data/lib/dsu/crud/raw_json_file.rb +51 -0
- data/lib/dsu/env.rb +21 -0
- data/lib/dsu/migration/service.rb +196 -0
- data/lib/dsu/migration/version.rb +7 -0
- data/lib/dsu/models/color_theme.rb +270 -0
- data/lib/dsu/models/configuration.rb +160 -0
- data/lib/dsu/models/entry.rb +6 -2
- data/lib/dsu/models/entry_group.rb +143 -42
- data/lib/dsu/models/migration_version.rb +48 -0
- data/lib/dsu/presenters/base_presenter.rb +32 -0
- data/lib/dsu/presenters/color_theme_presenter.rb +50 -0
- data/lib/dsu/presenters/color_theme_show_presenter.rb +49 -0
- data/lib/dsu/presenters/configuration_presenter.rb +45 -0
- data/lib/dsu/presenters/entry_group_presenter.rb +35 -0
- data/lib/dsu/presenters/entry_presenter.rb +25 -0
- data/lib/dsu/services/color_theme/hydrator_service.rb +42 -0
- data/lib/dsu/services/configuration/hydrator_service.rb +42 -0
- data/lib/dsu/services/entry/hydrator_service.rb +33 -0
- data/lib/dsu/services/entry_group/editor_service.rb +107 -0
- data/lib/dsu/services/entry_group/hydrator_service.rb +37 -0
- data/lib/dsu/services/migration_version/hydrator_service.rb +36 -0
- data/lib/dsu/services/stderr_redirector_service.rb +27 -0
- data/lib/dsu/services/temp_file/reader_service.rb +33 -0
- data/lib/dsu/services/temp_file/writer_service.rb +35 -0
- data/lib/dsu/subcommands/base_subcommand.rb +14 -0
- data/lib/dsu/subcommands/config.rb +92 -32
- data/lib/dsu/subcommands/edit.rb +3 -3
- data/lib/dsu/subcommands/list.rb +70 -93
- data/lib/dsu/subcommands/theme.rb +159 -0
- data/lib/dsu/support/ask.rb +14 -19
- data/lib/dsu/support/color_themable.rb +34 -0
- data/lib/dsu/support/command_help_colorizeable.rb +27 -0
- data/lib/dsu/support/command_hookable.rb +60 -0
- data/lib/dsu/support/command_options/dsu_times.rb +32 -21
- data/lib/dsu/support/command_options/time.rb +7 -1
- data/lib/dsu/support/command_options/time_mneumonic.rb +7 -1
- data/lib/dsu/support/descriptable.rb +6 -4
- data/lib/dsu/support/entry_group_viewable.rb +28 -4
- data/lib/dsu/support/fileable.rb +94 -0
- data/lib/dsu/support/presentable.rb +11 -0
- data/lib/dsu/support/subcommand_help_colorizeable.rb +27 -0
- data/lib/dsu/support/time_comparable.rb +19 -0
- data/lib/dsu/support/time_formatable.rb +12 -0
- data/lib/dsu/support/times_sortable.rb +48 -14
- data/lib/dsu/support/utils.rb +11 -0
- data/lib/dsu/validators/color_theme_validator.rb +74 -0
- data/lib/dsu/validators/entries_validator.rb +4 -8
- data/lib/dsu/validators/version_validator.rb +29 -0
- data/lib/dsu/version.rb +2 -1
- data/lib/dsu/views/color_theme/index.rb +62 -0
- data/lib/dsu/views/color_theme/show.rb +106 -0
- data/lib/dsu/views/configuration/show.rb +41 -0
- data/lib/dsu/views/entry_group/edit.rb +3 -5
- data/lib/dsu/views/entry_group/shared/no_entries_to_display.rb +41 -0
- data/lib/dsu/views/entry_group/show.rb +16 -15
- data/lib/dsu/views/shared/error.rb +17 -0
- data/lib/dsu/views/shared/info.rb +17 -0
- data/lib/dsu/views/shared/message.rb +85 -0
- data/lib/dsu/views/shared/model_errors.rb +31 -0
- data/lib/dsu/views/shared/success.rb +17 -0
- data/lib/dsu/views/shared/warning.rb +17 -0
- data/lib/dsu.rb +22 -1
- data/lib/seed_data/themes/cherry.json +79 -0
- data/lib/seed_data/themes/default.json +79 -0
- data/lib/seed_data/themes/lemon.json +79 -0
- data/lib/seed_data/themes/matrix.json +79 -0
- data/lib/seed_data/themes/whiteout.json +79 -0
- metadata +70 -25
- data/lib/dsu/core/ruby/not_today.rb +0 -11
- data/lib/dsu/services/ai/tense_translator_service.rb +0 -63
- data/lib/dsu/services/configuration_loader_service.rb +0 -55
- data/lib/dsu/services/entry_group_deleter_service.rb +0 -31
- data/lib/dsu/services/entry_group_editor_service.rb +0 -96
- data/lib/dsu/services/entry_group_hydrator_service.rb +0 -43
- data/lib/dsu/services/entry_group_reader_service.rb +0 -36
- data/lib/dsu/services/entry_group_writer_service.rb +0 -46
- data/lib/dsu/services/entry_hydrator_service.rb +0 -35
- data/lib/dsu/services/temp_file_reader_service.rb +0 -31
- data/lib/dsu/services/temp_file_writer_service.rb +0 -33
- data/lib/dsu/support/colorable.rb +0 -14
- data/lib/dsu/support/configurable.rb +0 -15
- data/lib/dsu/support/configuration.rb +0 -112
- data/lib/dsu/support/entry_group_fileable.rb +0 -49
- data/lib/dsu/support/entry_group_loadable.rb +0 -49
- data/lib/dsu/support/folder_locations.rb +0 -21
- data/lib/dsu/support/say.rb +0 -40
- data/lib/dsu/views/edited_entries/shared/errors.rb +0 -39
- data/lib/dsu/views/shared/messages.rb +0 -56
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../base_cli'
|
4
|
+
require_relative '../support/ask'
|
5
|
+
require_relative '../support/subcommand_help_colorizeable'
|
6
|
+
|
7
|
+
module Dsu
|
8
|
+
module Subcommands
|
9
|
+
class BaseSubcommand < Dsu::BaseCLI
|
10
|
+
include Support::Ask
|
11
|
+
include Support::SubcommandHelpColorizable
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative '../
|
3
|
+
require_relative '../models/configuration'
|
4
|
+
require_relative '../views/configuration/show'
|
5
|
+
require_relative '../views/shared/model_errors'
|
6
|
+
require_relative '../views/shared/success'
|
7
|
+
require_relative '../views/shared/warning'
|
8
|
+
require_relative 'base_subcommand'
|
5
9
|
|
6
10
|
module Dsu
|
7
11
|
module Subcommands
|
8
|
-
class Config <
|
9
|
-
include Dsu::Support::Configuration
|
10
|
-
|
12
|
+
class Config < BaseSubcommand
|
11
13
|
default_command :help
|
12
14
|
|
13
15
|
class << self
|
@@ -19,59 +21,117 @@ module Dsu
|
|
19
21
|
desc 'info', 'Displays information about this gem configuration'
|
20
22
|
long_desc <<-LONG_DESC
|
21
23
|
NAME
|
22
|
-
|
24
|
+
|
23
25
|
`dsu config info` -- Displays information about this gem configuration.
|
24
26
|
|
25
27
|
SYNOPSIS
|
26
|
-
|
28
|
+
|
27
29
|
dsu config info
|
28
30
|
LONG_DESC
|
29
31
|
def info
|
30
|
-
|
32
|
+
configuration = Models::Configuration.new
|
33
|
+
Views::Configuration::Show.new(config: configuration).call
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
if ENV['DEV_ENV']
|
37
|
+
desc 'init', 'Creates and initializes a .dsu file in your home folder'
|
38
|
+
long_desc <<-LONG_DESC
|
39
|
+
NAME
|
36
40
|
|
37
|
-
|
41
|
+
`dsu config init` -- will create and initialize a .dsu file ("#{Dsu::Support::Fileable.root_folder}/.dsu") that you may edit. Otherwise, the default configuration will be used.
|
38
42
|
|
39
|
-
|
43
|
+
SYNOPSIS
|
40
44
|
|
41
|
-
|
45
|
+
dsu config init
|
42
46
|
|
43
|
-
|
47
|
+
CONFIGURATION FILE OPTIONS
|
44
48
|
|
45
|
-
|
49
|
+
The following configuration file options are available:
|
46
50
|
|
47
|
-
|
51
|
+
version:
|
48
52
|
|
49
|
-
|
53
|
+
The configuration version - DO NOT ALTER THIS VALUE!
|
50
54
|
|
51
|
-
|
55
|
+
editor:
|
52
56
|
|
53
|
-
|
57
|
+
The default editor to use when editing entry groups if the EDITOR environment variable on your system is not set. The default is 'nano'. You'll need to change the default editor on Windows systems.
|
54
58
|
|
55
|
-
|
59
|
+
entries_display_order:
|
56
60
|
|
57
|
-
|
61
|
+
The order by which entries will be displayed, :asc or :desc (ascending or descending, respectively).
|
58
62
|
|
59
|
-
|
63
|
+
Default: :desc
|
60
64
|
|
61
|
-
|
65
|
+
entries_file_name:
|
62
66
|
|
63
|
-
|
67
|
+
The entries file name format. It is recommended that you do not change this. The file name must include `%Y`, `%m` and `%d` `Time` formatting specifiers to make sure the file name is unique and able to be located by `dsu` functions. For example, the default file name is `%Y-%m-%d.json`; however, something like `%m-%d-%Y.json` or `entry-group-%m-%d-%Y.json` would work as well.
|
64
68
|
|
65
|
-
|
69
|
+
ATTENTION: Please keep in mind that if you change this value `dsu` will not recognize entry files using a different format. You would (at this time), have to manually rename any existing entry file names to the new format.
|
66
70
|
|
67
|
-
|
71
|
+
Default: '%Y-%m-%d.json'
|
68
72
|
|
69
|
-
|
73
|
+
entries_folder:
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
+
This is the folder where `dsu` stores entry files. You may change this to anything you want. `dsu` will create this folder for you, as long as your system's write permissions allow this.
|
76
|
+
|
77
|
+
ATTENTION: Please keep in mind that if you change this value `dsu` will not be able to find entry files in any previous folder. You would (at this time), have to manually mode any existing entry files to this new folder.
|
78
|
+
|
79
|
+
Default: "'#{Dsu::Support::Fileable.root_folder}/dsu/entries'"
|
80
|
+
LONG_DESC
|
81
|
+
def init
|
82
|
+
exit 1 if configuration_errors_or_wanings?
|
83
|
+
|
84
|
+
Models::Configuration.default.tap do |configuration|
|
85
|
+
configuration.save!
|
86
|
+
messages = ["Configuration file (#{Models::Configuration.config_file}) created."]
|
87
|
+
Views::Shared::Success.new(messages: messages).render
|
88
|
+
Views::Configuration::Show.new(config: configuration).render
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
desc 'delete', 'Deletes the configuration file'
|
93
|
+
long_desc <<-LONG_DESC
|
94
|
+
NAME
|
95
|
+
|
96
|
+
`dsu config delete` -- Deletes the configuration.
|
97
|
+
|
98
|
+
SYNOPSIS
|
99
|
+
|
100
|
+
dsu config delete
|
101
|
+
|
102
|
+
NOTES
|
103
|
+
|
104
|
+
Deleting the dsu configuration file will simply cause dsu to use the default configuration options (`Dsu::Models::Configuration::DEFAULT_CONFIGURATION`).
|
105
|
+
LONG_DESC
|
106
|
+
def delete
|
107
|
+
unless Models::Configuration.exist?
|
108
|
+
messages = ["Configuration file (#{Models::Configuration.config_file}) does not exist."]
|
109
|
+
Views::Shared::Warning.new(messages: messages).render
|
110
|
+
exit 1
|
111
|
+
end
|
112
|
+
Models::Configuration.delete!
|
113
|
+
messages = ["Configuration file (#{Models::Configuration.config_file}) deleted."]
|
114
|
+
Views::Shared::Success.new(messages: messages).render
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def configuration_errors_or_wanings?
|
121
|
+
if Models::Configuration.exist?
|
122
|
+
messages = ["Configuration file (#{Models::Configuration.config_file}) already exists"]
|
123
|
+
Views::Shared::Warning.new(messages: messages).render
|
124
|
+
elsif !Dir.exist?(Models::Configuration.config_folder)
|
125
|
+
messages = ["Destination folder for configuration file (#{Models::Configuration.config_folder}) does not exist"] # rubocop:disable Layout/LineLength
|
126
|
+
Views::Shared::Error.new(messages: messages).render
|
127
|
+
else
|
128
|
+
configuration = Models::Configuration.default
|
129
|
+
return false if configuration.valid?
|
130
|
+
|
131
|
+
Views::Shared::ModelErrors.new(model: configuration).render
|
132
|
+
end
|
133
|
+
|
134
|
+
true
|
75
135
|
end
|
76
136
|
end
|
77
137
|
end
|
data/lib/dsu/subcommands/edit.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'base_subcommand'
|
4
4
|
require_relative '../models/entry_group'
|
5
5
|
require_relative '../views/entry_group/show'
|
6
6
|
|
7
7
|
module Dsu
|
8
8
|
module Subcommands
|
9
|
-
class Edit <
|
9
|
+
class Edit < BaseSubcommand
|
10
10
|
map %w[d] => :date
|
11
11
|
map %w[n] => :today
|
12
12
|
map %w[t] => :tomorrow
|
@@ -53,7 +53,7 @@ module Dsu
|
|
53
53
|
entry_group = Models::EntryGroup.edit(time: Time.parse(date))
|
54
54
|
Views::EntryGroup::Show.new(entry_group: entry_group).render
|
55
55
|
rescue ArgumentError => e
|
56
|
-
|
56
|
+
puts apply_theme("Error: #{e.message}", theme_color: color_theme.error)
|
57
57
|
exit 1
|
58
58
|
end
|
59
59
|
end
|
data/lib/dsu/subcommands/list.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../base_cli'
|
4
3
|
require_relative '../support/command_options/dsu_times'
|
4
|
+
require_relative '../support/command_options/time_mneumonic'
|
5
5
|
require_relative '../support/time_formatable'
|
6
|
+
require_relative '../views/entry_group/shared/no_entries_to_display'
|
7
|
+
require_relative '../views/shared/error'
|
8
|
+
require_relative 'base_subcommand'
|
6
9
|
|
7
10
|
module Dsu
|
8
11
|
module Subcommands
|
9
|
-
class List <
|
10
|
-
include Support::CommandOptions::
|
12
|
+
class List < BaseSubcommand
|
13
|
+
include Support::CommandOptions::TimeMneumonic
|
11
14
|
include Support::TimeFormatable
|
12
15
|
|
13
16
|
map %w[d] => :date
|
@@ -21,10 +24,11 @@ module Dsu
|
|
21
24
|
long_desc <<-LONG_DESC
|
22
25
|
Displays the DSU entries for today. This command has no options.
|
23
26
|
LONG_DESC
|
27
|
+
option :include_all, type: :boolean, aliases: '-a', desc: 'Include dates that have no DSU entries'
|
24
28
|
def today
|
25
29
|
time = Time.now
|
26
|
-
times = sorted_dsu_times_for(times: [time, time
|
27
|
-
view_list_for(times: times)
|
30
|
+
times = sorted_dsu_times_for(times: [time.yesterday, time])
|
31
|
+
view_list_for(times: times, options: options)
|
28
32
|
end
|
29
33
|
|
30
34
|
desc 'tomorrow, t',
|
@@ -32,10 +36,11 @@ module Dsu
|
|
32
36
|
long_desc <<-LONG_DESC
|
33
37
|
Displays the DSU entries for tomorrow. This command has no options.
|
34
38
|
LONG_DESC
|
39
|
+
option :include_all, type: :boolean, aliases: '-a', desc: 'Include dates that have no DSU entries'
|
35
40
|
def tomorrow
|
36
41
|
time = Time.now
|
37
|
-
times = sorted_dsu_times_for(times: [time
|
38
|
-
view_list_for(times: times)
|
42
|
+
times = sorted_dsu_times_for(times: [time, time.tomorrow])
|
43
|
+
view_list_for(times: times, options: options)
|
39
44
|
end
|
40
45
|
|
41
46
|
desc 'yesterday, y',
|
@@ -43,10 +48,11 @@ module Dsu
|
|
43
48
|
long_desc <<-LONG_DESC
|
44
49
|
Displays the DSU entries for yesterday. This command has no options.
|
45
50
|
LONG_DESC
|
51
|
+
option :include_all, type: :boolean, aliases: '-a', desc: 'Include dates that have no DSU entries'
|
46
52
|
def yesterday
|
47
53
|
time = Time.now
|
48
54
|
times = sorted_dsu_times_for(times: [time.yesterday, time.yesterday.yesterday])
|
49
|
-
view_list_for(times: times)
|
55
|
+
view_list_for(times: times, options: options)
|
50
56
|
end
|
51
57
|
|
52
58
|
desc 'date, d DATE|MNEUMONIC',
|
@@ -54,130 +60,101 @@ module Dsu
|
|
54
60
|
long_desc <<-LONG_DESC
|
55
61
|
Displays the DSU entries for the DATE or MNEUMONIC provided.
|
56
62
|
|
57
|
-
\x5
|
58
63
|
#{date_option_description}
|
59
64
|
|
60
|
-
\x5
|
61
65
|
#{mneumonic_option_description}
|
62
66
|
LONG_DESC
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
option :include_all, type: :boolean, aliases: '-a', desc: 'Include dates that have no DSU entries'
|
68
|
+
def date(date_or_mneumonic)
|
69
|
+
time = if time_mneumonic?(date_or_mneumonic)
|
70
|
+
time_from_mneumonic(command_option: date_or_mneumonic)
|
66
71
|
else
|
67
|
-
Time.parse(
|
72
|
+
Time.parse(date_or_mneumonic)
|
68
73
|
end
|
69
74
|
times = sorted_dsu_times_for(times: [time, time.yesterday])
|
70
|
-
view_list_for(times: times)
|
75
|
+
view_list_for(times: times, options: options)
|
71
76
|
rescue ArgumentError => e
|
72
|
-
|
73
|
-
exit 1
|
77
|
+
Views::Shared::Error.new(messages: e.message).render
|
74
78
|
end
|
75
79
|
|
76
|
-
desc 'dates
|
80
|
+
desc 'dates|dd OPTIONS',
|
77
81
|
'Displays the DSU entries for the OPTIONS provided'
|
78
82
|
long_desc <<~LONG_DESC
|
79
83
|
NAME
|
80
|
-
|
81
|
-
|
84
|
+
|
85
|
+
$ dsu dates|dd OPTIONS -- will display the DSU entries for the OPTIONS provided.
|
82
86
|
|
83
87
|
SYNOPSIS
|
84
|
-
|
85
|
-
|
88
|
+
|
89
|
+
$ dsu dates|dd OPTIONS
|
86
90
|
|
87
91
|
OPTIONS
|
88
|
-
|
92
|
+
|
89
93
|
-a|--include-all true|false: If true, all DSU dates within the specified range will be displayed. If false, DSU dates between the first and last DSU dates that have NO entries will NOT be displayed.. The default is taken from the dsu configuration setting :include_all, see `dsu config info`.
|
90
94
|
|
91
|
-
\x5
|
92
95
|
-f|--from DATE|MNEMONIC: The DATE or MNEUMONIC that represents the start of the range of DSU dates to display. If a relative mneumonic is used (+/-n, e.g +1, -1, etc.), the date calculated will be relative to the current date (e.g. `<MNEUMONIC>.to_i.days.from_now(Time.now)`).
|
93
96
|
|
94
|
-
\x5
|
95
97
|
-t|--to DATE|MNEMONIC: The DATE or MNEUMONIC that represents the end of the range of DSU dates to display. If a relative mneumonic is used (+/-n, e.g +1, -1, etc.), the date calculated will be relative to the date that resulting from the `--from` option date calculation.
|
96
98
|
|
97
|
-
\x5
|
98
99
|
#{date_option_description}
|
99
100
|
|
100
|
-
\x5
|
101
101
|
#{mneumonic_option_description}
|
102
102
|
|
103
|
-
\x5
|
104
103
|
EXAMPLES
|
105
104
|
|
106
|
-
\x5
|
107
105
|
NOTE: All examples are subject to the `--include-all` option.
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
107
|
+
The below will display the DSU entries for the range of dates from 1/1 to 1/4:
|
108
|
+
|
109
|
+
$ dsu list dates --from 1/1 --to +3
|
110
|
+
|
111
|
+
This will display the DSU entries for the range of dates from 1/2 to 1/5:
|
112
|
+
|
113
|
+
$ dsu list dates --from 1/5 --to -3
|
114
|
+
|
115
|
+
This (assuming "today" is 1/10) will display the DSU entries for the last week 1/10 to 1/3:
|
116
|
+
|
117
|
+
$ dsu list dates --from today --to -7
|
118
|
+
|
119
|
+
This (assuming "today" is 5/23) will display the DSU entries for the last week 5/16 to 5/22.
|
120
|
+
This example simply illustrates the fact that you can use relative mneumonics for
|
121
|
+
both `--from` and `--to` options; this doesn't mean you should do so...
|
122
|
+
|
123
|
+
While you can use relative mneumonics for both `--from` and `--to` options,
|
124
|
+
there is always a more intuitive way. The below example basically lists one week
|
125
|
+
of DSU entries back 1 week from yesterday's date:
|
126
|
+
|
127
|
+
$ dsu list dates --from -7 --to +6
|
128
|
+
|
129
|
+
The above can be accomplished MUCH easier by simply using the `yesterday` mneumonic...
|
130
|
+
|
131
|
+
This (assuming "today" is 5/23) will display the DSU entries back 1 week from yesterday's date 5/16 to 5/22:
|
132
|
+
|
133
|
+
$ dsu list dates --from yesterday --to -6
|
136
134
|
LONG_DESC
|
137
135
|
# -f, --from FROM [DATE|MNEMONIC] (e.g. -f, --from 1/1[/yyy]|n|t|y|today|tomorrow|yesterday)
|
138
|
-
option :from, type: :string, aliases: '-f', banner: 'DATE|MNEMONIC'
|
136
|
+
option :from, type: :string, required: true, aliases: '-f', banner: 'DATE|MNEMONIC'
|
139
137
|
# -t, --to TO [DATE|MNEMONIC] (e.g. -t, --to 1/1[/yyy]|n|t|y|today|tomorrow|yesterday)
|
140
|
-
option :to, type: :string, aliases: '-t', banner: 'DATE|MNEMONIC'
|
141
|
-
|
138
|
+
option :to, type: :string, required: true, aliases: '-t', banner: 'DATE|MNEMONIC'
|
142
139
|
# Include dates that have no DSU entries.
|
143
|
-
option :include_all, type: :boolean, aliases: '-a'
|
140
|
+
option :include_all, type: :boolean, aliases: '-a', desc: 'Include dates that have no DSU entries'
|
144
141
|
def dates
|
145
|
-
options = configuration.merge(self.options)
|
146
|
-
times =
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
view_entry_groups(times: times, options: options) do |total_entry_groups|
|
151
|
-
nothing_to_display_banner_for(times) if total_entry_groups.zero?
|
142
|
+
options = configuration.to_h.merge(self.options).with_indifferent_access
|
143
|
+
times, errors = Support::CommandOptions::DsuTimes.dsu_times_for(from_option: options[:from], to_option: options[:to]) # rubocop:disable Layout/LineLength
|
144
|
+
if errors.any?
|
145
|
+
Views::Shared::Error.new(messages: errors).render
|
146
|
+
return
|
152
147
|
end
|
153
|
-
rescue ArgumentError => e
|
154
|
-
say "Error: #{e.message}", ERROR
|
155
|
-
exit 1
|
156
|
-
end
|
157
|
-
|
158
|
-
private
|
159
|
-
|
160
|
-
def nothing_to_display_banner_for(entry_group_times)
|
161
|
-
entry_group_times.sort!
|
162
|
-
time_range = "#{formatted_time(time: entry_group_times.first)} " \
|
163
|
-
"through #{formatted_time(time: entry_group_times.last)}"
|
164
|
-
say "(nothing to display for #{time_range})", INFO
|
165
|
-
end
|
166
148
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
times_first_and_last = [times.first, times.last]
|
174
|
-
times.each do |time|
|
175
|
-
view_options = options.dup
|
176
|
-
view_options[:include_all] = true if times_first_and_last.include?(time)
|
177
|
-
view_entry_group(time: time, options: view_options) do
|
178
|
-
puts
|
179
|
-
end
|
149
|
+
# NOTE: special sort here, unlike the other commands where rules for
|
150
|
+
# displaying DSU entries are applied; this is more of a list command.
|
151
|
+
times = times_sort(times: times, entries_display_order: options[:entries_display_order])
|
152
|
+
view_entry_groups(times: times, options: options) do |total_entry_groups, _total_entry_groups_not_shown|
|
153
|
+
# nothing_to_display_banner_for(times) if total_entry_groups.zero?
|
154
|
+
Views::EntryGroup::Shared::NoEntriesToDisplay.new(times: times, options: options) if total_entry_groups.zero?
|
180
155
|
end
|
156
|
+
rescue ArgumentError => e
|
157
|
+
Views::Shared::Error.new(messages: e.message).render
|
181
158
|
end
|
182
159
|
end
|
183
160
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../env'
|
4
|
+
require_relative '../support/fileable'
|
5
|
+
require_relative '../views/color_theme/index'
|
6
|
+
require_relative '../views/color_theme/show'
|
7
|
+
require_relative '../views/shared/error'
|
8
|
+
require_relative '../views/shared/info'
|
9
|
+
require_relative 'base_subcommand'
|
10
|
+
|
11
|
+
module Dsu
|
12
|
+
module Subcommands
|
13
|
+
class Theme < BaseSubcommand
|
14
|
+
map %w[c] => :create if Dsu.env.test?
|
15
|
+
map %w[d] => :delete if Dsu.env.test?
|
16
|
+
map %w[l] => :list
|
17
|
+
map %w[s] => :show
|
18
|
+
map %w[u] => :use
|
19
|
+
|
20
|
+
if Dsu.env.test?
|
21
|
+
desc 'create THEME_NAME [OPTIONS]',
|
22
|
+
'Creates a dsu color theme named THEME_NAME.'
|
23
|
+
long_desc <<-LONG_DESC
|
24
|
+
Create a dsu color theme named THEME_NAME in the #{Support::Fileable.themes_folder} folder.
|
25
|
+
|
26
|
+
SYNOPSIS
|
27
|
+
|
28
|
+
`dsu create THEME_NAME [-d|--description DESCRIPTION]`
|
29
|
+
|
30
|
+
OPTIONS:
|
31
|
+
|
32
|
+
-d|--description DESCRIPTION: Creates the dsu color theme with having DESCRIPTION as the color theme description.
|
33
|
+
|
34
|
+
DESCRIPTION:
|
35
|
+
|
36
|
+
Must be be between 2 and 256 characters (inclusive) in length.
|
37
|
+
LONG_DESC
|
38
|
+
option :description, type: :string, aliases: '-d', banner: 'DESCRIPTION'
|
39
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
40
|
+
def create(theme_name)
|
41
|
+
if Models::ColorTheme.exist?(theme_name: theme_name)
|
42
|
+
Views::Shared::Error.new(messages: "Color theme \"#{theme_name}\" already exists.").render
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
prompt = color_theme.prompt_with_options(prompt: "Create color theme \"#{theme_name}\"?", options: %w[y N])
|
46
|
+
if yes?(prompt, options: options)
|
47
|
+
theme_hash = Models::ColorTheme::DEFAULT_THEME.dup
|
48
|
+
theme_hash[:description] = options[:description] || "#{theme_name.capitalize} color theme"
|
49
|
+
Models::ColorTheme.new(theme_name: theme_name, theme_hash: theme_hash).save!
|
50
|
+
Views::Shared::Info.new(messages: "\nCreated color theme \"#{theme_name}\".").render
|
51
|
+
true
|
52
|
+
else
|
53
|
+
Views::Shared::Info.new(messages: "\nCanceled.").render
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'delete THEME_NAME',
|
59
|
+
'Deletes the existing dsu color theme THEME_NAME.'
|
60
|
+
long_desc <<-LONG_DESC
|
61
|
+
NAME
|
62
|
+
|
63
|
+
`dsu delete [THEME_NAME]` -- will delete the dsu color theme named THEME_NAME located in the #{Support::Fileable.themes_folder} folder.
|
64
|
+
LONG_DESC
|
65
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
66
|
+
def delete(theme_name)
|
67
|
+
display_dsu_header
|
68
|
+
|
69
|
+
if theme_name == Models::ColorTheme::DEFAULT_THEME_NAME
|
70
|
+
display_dsu_header
|
71
|
+
Views::Shared::Error.new(messages: "Color theme \"#{theme_name}\" cannot be deleted.").render
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
unless Models::ColorTheme.exist?(theme_name: theme_name)
|
76
|
+
Views::Shared::Error.new(messages: "Color theme \"#{theme_name}\" does not exist.").render
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
prompt = color_theme.prompt_with_options(prompt: "Delete color theme \"#{theme_name}\"?",
|
81
|
+
options: %w[y N])
|
82
|
+
if yes?(prompt, options: options)
|
83
|
+
Models::ColorTheme.delete!(theme_name: theme_name)
|
84
|
+
Views::Shared::Info.new(messages: "\nDeleted color theme \"#{theme_name}\".").render
|
85
|
+
else
|
86
|
+
Views::Shared::Info.new(messages: "\nCanceled.").render
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc 'list',
|
92
|
+
'Lists the available dsu color themes.'
|
93
|
+
long_desc <<-LONG_DESC
|
94
|
+
NAME
|
95
|
+
|
96
|
+
`dsu list` -- lists the available dsu color themes located in the #{Support::Fileable.themes_folder} folder.
|
97
|
+
LONG_DESC
|
98
|
+
def list
|
99
|
+
Views::ColorTheme::Index.new.render
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'use THEME_NAME',
|
103
|
+
'Sets THEME_NAME as the current DSU color theme.'
|
104
|
+
long_desc <<-LONG_DESC
|
105
|
+
NAME
|
106
|
+
|
107
|
+
`dsu theme use [THEME_NAME]` -- sets the dsu color theme to THEME_NAME.
|
108
|
+
|
109
|
+
SYNOPSIS
|
110
|
+
|
111
|
+
If THEME_NAME is not provided, the default theme will be used.
|
112
|
+
If THEME_NAME does not exist, you will be given the option to create a new theme.
|
113
|
+
|
114
|
+
LONG_DESC
|
115
|
+
option :prompts, type: :hash, default: {}, hide: true, aliases: '-p'
|
116
|
+
def use(theme_name = Models::ColorTheme::DEFAULT_THEME_NAME)
|
117
|
+
if Dsu.env.test? && !Models::ColorTheme.exist?(theme_name: theme_name)
|
118
|
+
display_dsu_header
|
119
|
+
return unless create(theme_name)
|
120
|
+
end
|
121
|
+
|
122
|
+
unless Models::ColorTheme.exist?(theme_name: theme_name)
|
123
|
+
display_dsu_header
|
124
|
+
Views::Shared::Error.new(messages: "Color theme \"#{theme_name}\" does not exist.").render
|
125
|
+
return
|
126
|
+
end
|
127
|
+
|
128
|
+
configuration.theme_name = theme_name
|
129
|
+
configuration.save!
|
130
|
+
# We need to display the header after the theme is updated so that it is displayed in the
|
131
|
+
# correct theme color.
|
132
|
+
display_dsu_header
|
133
|
+
Views::Shared::Info.new(messages: "Using color theme \"#{theme_name}\".").render
|
134
|
+
end
|
135
|
+
|
136
|
+
desc 'show THEME_NAME',
|
137
|
+
'Displays the dsu color theme.'
|
138
|
+
long_desc <<-LONG_DESC
|
139
|
+
NAME
|
140
|
+
|
141
|
+
`dsu show THEME_NAME` -- displays the dsu color theme for THEME_NAME.
|
142
|
+
LONG_DESC
|
143
|
+
def show(theme_name = configuration.theme_name)
|
144
|
+
if Dsu::Models::ColorTheme.exist?(theme_name: theme_name)
|
145
|
+
Views::ColorTheme::Show.new(theme_name: theme_name).render
|
146
|
+
return
|
147
|
+
end
|
148
|
+
|
149
|
+
Views::Shared::Error.new(messages: "Color theme \"#{theme_name}\" does not exist.").render
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def display_dsu_header
|
155
|
+
self.class.display_dsu_header
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/dsu/support/ask.rb
CHANGED
@@ -5,34 +5,29 @@ require 'thor'
|
|
5
5
|
module Dsu
|
6
6
|
module Support
|
7
7
|
module Ask
|
8
|
-
ASK_YES = %w[y yes].freeze
|
9
|
-
# ASK_NO = %w[n no].freeze
|
10
|
-
# ASK_CANCEL = %w[c cancel].freeze
|
11
|
-
# ASK_YES_NO_CANCEL = ASK_YES.concat(ASK_NO).concat(ASK_CANCEL).freeze
|
12
|
-
|
13
8
|
def ask(prompt)
|
14
9
|
options = {}
|
15
10
|
Thor::LineEditor.readline(prompt, options)
|
16
11
|
end
|
17
12
|
|
18
|
-
def yes?(prompt,
|
19
|
-
|
20
|
-
end
|
13
|
+
def yes?(prompt, options: {})
|
14
|
+
auto_prompt = auto_prompt(prompt, options)
|
21
15
|
|
22
|
-
|
23
|
-
# ask_with(prompt: prompt, values: ASK_NO)
|
24
|
-
# end
|
16
|
+
return auto_prompt unless auto_prompt.nil?
|
25
17
|
|
26
|
-
|
27
|
-
|
28
|
-
# end
|
18
|
+
Thor::Base.shell.new.yes?(prompt)
|
19
|
+
end
|
29
20
|
|
30
|
-
|
21
|
+
private
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
def auto_prompt(prompt, options)
|
24
|
+
prompt = Utils.strip_escapes(prompt)
|
25
|
+
@auto_prompt ||= begin
|
26
|
+
value = options.dig('prompts', prompt)
|
27
|
+
value = (value == 'true' unless value.nil?)
|
28
|
+
value
|
29
|
+
end
|
30
|
+
end
|
36
31
|
end
|
37
32
|
end
|
38
33
|
end
|