doing 2.1.41 → 2.1.44
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/CHANGELOG.md +67 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/bin/commands/again.rb +1 -3
- data/bin/commands/changes.rb +60 -34
- data/bin/commands/commands.rb +77 -52
- data/bin/commands/commands_accepting.rb +57 -53
- data/bin/commands/config.rb +2 -2
- data/bin/commands/finish.rb +94 -68
- data/bin/commands/flag.rb +5 -1
- data/bin/commands/grep.rb +12 -2
- data/bin/commands/last.rb +2 -0
- data/bin/commands/now.rb +151 -107
- data/bin/commands/on.rb +20 -5
- data/bin/commands/recent.rb +4 -1
- data/bin/commands/show.rb +8 -0
- data/bin/commands/since.rb +6 -2
- data/bin/commands/template.rb +14 -25
- data/bin/commands/today.rb +4 -1
- data/bin/commands/undo.rb +4 -6
- data/bin/commands/view.rb +36 -73
- data/bin/commands/views.rb +102 -5
- data/bin/commands/yesterday.rb +3 -1
- data/bin/doing +31 -4
- data/docs/doc/Array.html +14 -3
- data/docs/doc/BooleanTermParser/Clause.html +1 -1
- data/docs/doc/BooleanTermParser/Operator.html +1 -1
- data/docs/doc/BooleanTermParser/Query.html +1 -1
- data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
- data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
- data/docs/doc/BooleanTermParser.html +1 -1
- data/docs/doc/Doing/ArrayCleanup.html +316 -0
- data/docs/doc/Doing/ArrayNestedHash.html +1 -1
- data/docs/doc/Doing/ArrayTags.html +1 -1
- data/docs/doc/Doing/CSVExport.html +1 -1
- data/docs/doc/Doing/CalendarImport.html +1 -1
- data/docs/doc/Doing/Change.html +74 -3
- data/docs/doc/Doing/Changes.html +3 -3
- data/docs/doc/Doing/ChronifyArray.html +1 -1
- data/docs/doc/Doing/ChronifyNumeric.html +1 -1
- data/docs/doc/Doing/ChronifyString.html +1 -1
- data/docs/doc/Doing/Color.html +1 -1
- data/docs/doc/Doing/Completion/BashCompletions.html +1 -1
- data/docs/doc/Doing/Completion/FishCompletions.html +1 -1
- data/docs/doc/Doing/Completion/StringUtils.html +1 -1
- data/docs/doc/Doing/Completion/ZshCompletions.html +1 -1
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +82 -2
- data/docs/doc/Doing/DayOneRenderer.html +1 -1
- data/docs/doc/Doing/DayoneExport.html +1 -1
- data/docs/doc/Doing/DoingImport.html +1 -1
- data/docs/doc/Doing/Entry.html +109 -4
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
- data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
- data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
- data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
- data/docs/doc/Doing/Errors/NoResults.html +1 -1
- data/docs/doc/Doing/Errors/PluginException.html +1 -1
- data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
- data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
- data/docs/doc/Doing/Errors.html +1 -1
- data/docs/doc/Doing/HTMLExport.html +1 -1
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +1 -1
- data/docs/doc/Doing/ItemDates.html +1 -1
- data/docs/doc/Doing/ItemQuery.html +1 -1
- data/docs/doc/Doing/ItemState.html +1 -1
- data/docs/doc/Doing/ItemTags.html +1 -1
- data/docs/doc/Doing/Items.html +2 -1
- data/docs/doc/Doing/JSONExport.html +1 -1
- data/docs/doc/Doing/Logger.html +1 -1
- data/docs/doc/Doing/MarkdownExport.html +1 -1
- data/docs/doc/Doing/Note.html +3 -2
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +181 -76
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/PromptChoose.html +1 -1
- data/docs/doc/Doing/PromptFZF.html +1 -1
- data/docs/doc/Doing/PromptInput.html +1 -1
- data/docs/doc/Doing/PromptSTD.html +1 -1
- data/docs/doc/Doing/PromptYN.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/StringHighlight.html +1 -1
- data/docs/doc/Doing/StringNormalize.html +35 -1
- data/docs/doc/Doing/StringQuery.html +1 -1
- data/docs/doc/Doing/StringTags.html +1 -1
- data/docs/doc/Doing/StringTransform.html +35 -1
- data/docs/doc/Doing/StringTruncate.html +1 -1
- data/docs/doc/Doing/StringURL.html +1 -1
- data/docs/doc/Doing/SymbolNormalize.html +1 -1
- data/docs/doc/Doing/TaskPaperExport.html +1 -1
- data/docs/doc/Doing/TemplateExport.html +1 -1
- data/docs/doc/Doing/TemplateString.html +3 -3
- data/docs/doc/Doing/TimingImport.html +1 -1
- data/docs/doc/Doing/Types.html +23 -18
- data/docs/doc/Doing/Util/Backup.html +2 -156
- data/docs/doc/Doing/Util.html +66 -9
- data/docs/doc/Doing/Version.html +1 -1
- data/docs/doc/Doing/WWID.html +84 -3
- data/docs/doc/Doing.html +4 -4
- data/docs/doc/FalseClass.html +11 -1
- data/docs/doc/GLI/Commands/Help.html +1 -1
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +461 -6
- data/docs/doc/Numeric.html +1 -1
- data/docs/doc/Object.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +5 -5
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +68 -3
- data/docs/doc/TrueClass.html +11 -1
- data/docs/doc/_index.html +16 -9
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +529 -417
- data/docs/doc/top-level-namespace.html +11 -1
- data/doing.rdoc +169 -13
- data/lib/completion/_doing.zsh +13 -13
- data/lib/completion/doing.bash +22 -22
- data/lib/completion/doing.fish +24 -1
- data/lib/doing/add_options.rb +48 -1
- data/lib/doing/array/array.rb +2 -0
- data/lib/doing/array/cleanup.rb +31 -0
- data/lib/doing/changelog/change.rb +13 -5
- data/lib/doing/changelog/changes.rb +11 -2
- data/lib/doing/changelog/entry.rb +9 -2
- data/lib/doing/configuration.rb +28 -3
- data/lib/doing/good.rb +18 -1
- data/lib/doing/hash.rb +126 -22
- data/lib/doing/normalize.rb +13 -0
- data/lib/doing/note.rb +1 -1
- data/lib/doing/pager.rb +9 -3
- data/lib/doing/plugin_manager.rb +30 -5
- data/lib/doing/prompt/choose.rb +1 -1
- data/lib/doing/prompt/input.rb +1 -1
- data/lib/doing/string/transform.rb +6 -0
- data/lib/doing/types.rb +9 -8
- data/lib/doing/util.rb +12 -6
- data/lib/doing/util_backup.rb +55 -48
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid/display.rb +4 -1
- data/lib/doing/wwid/editor.rb +6 -3
- data/lib/doing/wwid/interactive.rb +10 -20
- data/lib/doing/wwid/modify.rb +2 -0
- data/lib/doing/wwid/wwid.rb +21 -3
- data/lib/doing.rb +12 -3
- metadata +4 -2
data/bin/commands/since.rb
CHANGED
|
@@ -15,7 +15,7 @@ command :since do |c|
|
|
|
15
15
|
add_options(:time_display, c)
|
|
16
16
|
add_options(:tag_filter, c)
|
|
17
17
|
add_options(:search, c)
|
|
18
|
-
|
|
18
|
+
add_options(:save, c)
|
|
19
19
|
c.action do |_global_options, options, args|
|
|
20
20
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
21
21
|
|
|
@@ -25,7 +25,7 @@ command :since do |c|
|
|
|
25
25
|
|
|
26
26
|
date_string.sub!(/(day) (\d)/, '\1 at \2')
|
|
27
27
|
date_string.sub!(/(\d+)d( ago)?/, '\1 days ago')
|
|
28
|
-
|
|
28
|
+
Doing.original_options[:date_begin] = date_string
|
|
29
29
|
start = date_string.chronify(guess: :begin)
|
|
30
30
|
finish = Time.now
|
|
31
31
|
|
|
@@ -37,5 +37,9 @@ command :since do |c|
|
|
|
37
37
|
options[:sort_tags] = options[:tag_sort]
|
|
38
38
|
|
|
39
39
|
Doing::Pager.page @wwid.list_date([start, finish], options[:section], options[:times], options[:output], options).chomp
|
|
40
|
+
if options[:save]
|
|
41
|
+
options[:after] = Doing.original_options[:date_begin] if Doing.original_options[:date_begin].good?
|
|
42
|
+
Doing.config.save_view(options.to_view, options[:save].downcase)
|
|
43
|
+
end
|
|
40
44
|
end
|
|
41
45
|
end
|
data/bin/commands/template.rb
CHANGED
|
@@ -28,34 +28,23 @@ command :template do |c|
|
|
|
28
28
|
else
|
|
29
29
|
$stdout.puts "Available templates: #{Doing::Plugins.plugin_templates.join(', ')}"
|
|
30
30
|
end
|
|
31
|
-
return
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
if args.empty?
|
|
35
|
-
type = Doing::Prompt.choose_from(Doing::Plugins.plugin_templates, sorted: false, prompt: 'Select template type > ')
|
|
36
|
-
type.sub!(/ \(.*?\)$/, '').strip!
|
|
37
|
-
options[:save] = Doing::Prompt.yn("Save to #{options[:path]}? (No outputs to STDOUT)", default_response: false)
|
|
38
31
|
else
|
|
39
|
-
type = args[0]
|
|
40
|
-
end
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
if args.empty?
|
|
34
|
+
type = Doing::Prompt.choose_from(Doing::Plugins.plugin_templates, sorted: false, prompt: 'Select template type > ')
|
|
35
|
+
type.sub!(/ \(.*?\)$/, '').strip!
|
|
36
|
+
options[:save] = Doing::Prompt.yn("Save to #{options[:path]}? (No outputs to STDOUT)", default_response: false)
|
|
37
|
+
else
|
|
38
|
+
type = args[0]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
raise InvalidPluginType, "No type specified, use `doing template [#{Doing::Plugins.plugin_templates.join('|')}]`" unless type
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
if options[:save]
|
|
44
|
+
Doing::Plugins.template_for_trigger(type, save_to: options[:path])
|
|
45
|
+
else
|
|
46
|
+
$stdout.puts Doing::Plugins.template_for_trigger(type, save_to: nil)
|
|
47
|
+
end
|
|
48
48
|
end
|
|
49
|
-
|
|
50
|
-
# case args[0]
|
|
51
|
-
# when /html|haml/i
|
|
52
|
-
# $stdout.puts @wwid.haml_template
|
|
53
|
-
# when /css/i
|
|
54
|
-
# $stdout.puts @wwid.css_template
|
|
55
|
-
# when /markdown|md|erb/i
|
|
56
|
-
# $stdout.puts @wwid.markdown_template
|
|
57
|
-
# else
|
|
58
|
-
# exit_now! 'Invalid type specified, must be HAML or CSS'
|
|
59
|
-
# end
|
|
60
49
|
end
|
|
61
50
|
end
|
data/bin/commands/today.rb
CHANGED
|
@@ -15,6 +15,7 @@ command :today do |c|
|
|
|
15
15
|
add_options(:output_template, c, default_template: 'today')
|
|
16
16
|
add_options(:time_filter, c)
|
|
17
17
|
add_options(:time_display, c)
|
|
18
|
+
add_options(:save, c)
|
|
18
19
|
|
|
19
20
|
c.action do |_global_options, options, _args|
|
|
20
21
|
raise InvalidPlugin.new('output', options[:output]) if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
@@ -22,7 +23,9 @@ command :today do |c|
|
|
|
22
23
|
options[:times] = true if options[:totals]
|
|
23
24
|
options[:sort_tags] = options[:tag_sort]
|
|
24
25
|
filter_options = %i[after before times duration from section sort_tags totals tag_order template config_template only_timed].each_with_object({}) { |k, hsh| hsh[k] = options[k] }
|
|
25
|
-
|
|
26
|
+
filter_options[:today] = true
|
|
26
27
|
Doing::Pager.page @wwid.today(options[:times], options[:output], filter_options).chomp
|
|
28
|
+
filter_options[:title] = options[:title]
|
|
29
|
+
Doing.config.save_view(filter_options.to_view, options[:save].downcase) if options[:save]
|
|
27
30
|
end
|
|
28
31
|
end
|
data/bin/commands/undo.rb
CHANGED
|
@@ -28,7 +28,7 @@ command :undo do |c|
|
|
|
28
28
|
c.action do |_global_options, options, args|
|
|
29
29
|
file = options[:file] || @wwid.doing_file
|
|
30
30
|
count = args.empty? ? 1 : args[0].to_i
|
|
31
|
-
raise InvalidArgument,
|
|
31
|
+
raise InvalidArgument, 'Invalid count specified for undo' unless count&.positive?
|
|
32
32
|
|
|
33
33
|
if options[:prune]
|
|
34
34
|
Doing::Util::Backup.prune_backups(file, options[:prune])
|
|
@@ -38,12 +38,10 @@ command :undo do |c|
|
|
|
38
38
|
else
|
|
39
39
|
Doing::Util::Backup.redo_backup(file, count: count)
|
|
40
40
|
end
|
|
41
|
+
elsif options[:interactive]
|
|
42
|
+
Doing::Util::Backup.select_backup(file)
|
|
41
43
|
else
|
|
42
|
-
|
|
43
|
-
Doing::Util::Backup.select_backup(file)
|
|
44
|
-
else
|
|
45
|
-
Doing::Util::Backup.restore_last_backup(file, count: count)
|
|
46
|
-
end
|
|
44
|
+
Doing::Util::Backup.restore_last_backup(file, count: count)
|
|
47
45
|
end
|
|
48
46
|
end
|
|
49
47
|
end
|
data/bin/commands/view.rb
CHANGED
|
@@ -15,28 +15,24 @@ command :view do |c|
|
|
|
15
15
|
c.arg_name 'COUNT'
|
|
16
16
|
c.flag %i[c count], must_match: /^\d+$/, type: Integer
|
|
17
17
|
|
|
18
|
-
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
19
|
-
c.arg_name 'FORMAT'
|
|
20
|
-
c.flag %i[o output]
|
|
21
|
-
|
|
22
18
|
c.desc 'Age (oldest|newest)'
|
|
23
19
|
c.arg_name 'AGE'
|
|
24
|
-
c.flag %i[age],
|
|
20
|
+
c.flag %i[age], type: AgeSymbol
|
|
25
21
|
|
|
26
22
|
c.desc 'Show time intervals on @done tasks'
|
|
27
23
|
c.switch %i[t times], default_value: true, negatable: true
|
|
28
24
|
|
|
29
25
|
c.desc 'Show elapsed time on entries without @done tag'
|
|
30
|
-
c.switch [:duration]
|
|
26
|
+
c.switch [:duration], default_value: false, negatable: false
|
|
31
27
|
|
|
32
28
|
c.desc 'Show intervals with totals at the end of output'
|
|
33
29
|
c.switch [:totals], default_value: false, negatable: false
|
|
34
30
|
|
|
35
31
|
c.desc 'Include colors in output'
|
|
36
|
-
c.switch [:color],
|
|
32
|
+
c.switch [:color], negatable: true
|
|
37
33
|
|
|
38
34
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
39
|
-
c.switch %i[h hilite], default_value:
|
|
35
|
+
c.switch %i[h hilite], default_value: false, negatable: true
|
|
40
36
|
|
|
41
37
|
c.desc 'Sort tags by (name|time)'
|
|
42
38
|
c.arg_name 'KEY'
|
|
@@ -53,8 +49,9 @@ command :view do |c|
|
|
|
53
49
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
54
50
|
|
|
55
51
|
add_options(:search, c)
|
|
56
|
-
add_options(:
|
|
52
|
+
add_options(:tag_filter_no_defaults, c)
|
|
57
53
|
add_options(:date_filter, c)
|
|
54
|
+
add_options(:output_template_no_defaults, c)
|
|
58
55
|
|
|
59
56
|
c.action do |global_options, options, args|
|
|
60
57
|
options[:fuzzy] = false
|
|
@@ -85,83 +82,55 @@ command :view do |c|
|
|
|
85
82
|
Doing.setting('current_section')
|
|
86
83
|
end
|
|
87
84
|
|
|
88
|
-
view = @wwid.
|
|
85
|
+
view = @wwid.view_to_options(title)
|
|
89
86
|
|
|
90
87
|
if view
|
|
91
|
-
|
|
92
|
-
only_timed = if (view.key?('only_timed') && view['only_timed']) || options[:only_timed]
|
|
93
|
-
true
|
|
94
|
-
else
|
|
95
|
-
false
|
|
96
|
-
end
|
|
88
|
+
options = Doing::Util.deep_merge_hashes(view, options)
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
options[:totals] = view[:totals] unless options[:totals]
|
|
91
|
+
options[:only_timed] = view[:only_timed] unless options[:only_timed]
|
|
92
|
+
options[:times] = view[:times] if options[:times]
|
|
93
|
+
options[:duration] = view[:duration] unless options[:duration]
|
|
94
|
+
options[:hilite] = view[:hilite] unless options[:hilite]
|
|
100
95
|
|
|
101
|
-
|
|
96
|
+
page_title = options[:title] || title.cap_first
|
|
102
97
|
tag_filter = false
|
|
103
|
-
if options[:tag]
|
|
98
|
+
if options[:tag] && options[:tag].good
|
|
104
99
|
tag_filter = { 'tags' => [], 'bool' => 'OR' }
|
|
105
|
-
bool = options[:bool]
|
|
100
|
+
bool = options[:bool].normalize_bool
|
|
106
101
|
tag_filter['bool'] = bool
|
|
107
102
|
tag_filter['tags'] = if bool == :pattern
|
|
108
103
|
options[:tag]
|
|
109
104
|
else
|
|
110
105
|
options[:tag].gsub(/[, ]+/, ' ').split(' ').map(&:strip)
|
|
111
106
|
end
|
|
112
|
-
|
|
107
|
+
options[:tags] = nil
|
|
108
|
+
options[:bool] = bool
|
|
109
|
+
elsif options[:tags]
|
|
113
110
|
tag_filter = { 'tags' => [], 'bool' => 'OR' }
|
|
114
|
-
bool =
|
|
111
|
+
bool = options[:bool] ? options[:bool].normalize_bool : :pattern
|
|
115
112
|
tag_filter['bool'] = bool
|
|
116
|
-
tag_filter['tags'] = if
|
|
117
|
-
bool == :pattern ?
|
|
113
|
+
tag_filter['tags'] = if options[:tags].instance_of?(Array)
|
|
114
|
+
bool == :pattern ? options[:tags].join(' ').strip : options[:tags].map(&:strip)
|
|
118
115
|
else
|
|
119
|
-
bool == :pattern ?
|
|
116
|
+
bool == :pattern ? options[:tags].strip : options[:tags].gsub(/[, ]+/, ' ').split(' ').map(&:strip)
|
|
120
117
|
end
|
|
118
|
+
options[:tags] = nil
|
|
119
|
+
options[:bool] = bool
|
|
121
120
|
end
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
options[:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
options[:count]
|
|
128
|
-
elsif view.key?('count')
|
|
129
|
-
view['count']
|
|
130
|
-
else
|
|
131
|
-
10
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
section = if options[:section]
|
|
135
|
-
section
|
|
136
|
-
else
|
|
137
|
-
view['section'] || Doing.setting('current_section')
|
|
138
|
-
end
|
|
139
|
-
order = if view.key?('order')
|
|
140
|
-
view['order'].normalize_order
|
|
141
|
-
else
|
|
142
|
-
:asc
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
totals = if options[:totals]
|
|
146
|
-
true
|
|
147
|
-
else
|
|
148
|
-
view['totals'] || false
|
|
149
|
-
end
|
|
150
|
-
tag_order = options[:tag_order] || view['tag_order']&.normalize_order || :asc
|
|
151
|
-
|
|
152
|
-
options[:times] = true if totals
|
|
122
|
+
section = options[:section] || Doing.setting('current_section')
|
|
123
|
+
order = options[:order]&.normalize_order || :asc
|
|
124
|
+
totals = options[:totals] || false
|
|
125
|
+
tag_order = options[:tag_order]&.normalize_order || :asc
|
|
153
126
|
output_format = options[:output]&.downcase || 'template'
|
|
154
127
|
|
|
155
|
-
options[:
|
|
156
|
-
options[:tag_sort]
|
|
157
|
-
elsif view.key?('tag_sort')
|
|
158
|
-
view['tag_sort'].normalize_tag_sort
|
|
159
|
-
else
|
|
160
|
-
false
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
%w[before after from duration].each { |k| options[k.to_sym] = view[k] if view.key?(k) && !options[k.to_sym] }
|
|
128
|
+
options[:times] = true if totals
|
|
164
129
|
|
|
130
|
+
options.rename_key(:tag_sort, :sort_tags)
|
|
131
|
+
options[:sort_tags] ||= :name
|
|
132
|
+
options.rename_key(:date_format, :format)
|
|
133
|
+
options.rename_key(:color, :highlight)
|
|
165
134
|
search = nil
|
|
166
135
|
|
|
167
136
|
if options[:search]
|
|
@@ -172,12 +141,8 @@ command :view do |c|
|
|
|
172
141
|
options[:age] ||= :newest
|
|
173
142
|
|
|
174
143
|
opts = options.clone
|
|
175
|
-
|
|
176
|
-
opts[:count]
|
|
177
|
-
opts[:format] = date_format
|
|
178
|
-
opts[:highlight] = options[:color]
|
|
179
|
-
opts[:hilite] = options[:hilite]
|
|
180
|
-
opts[:only_timed] = only_timed
|
|
144
|
+
|
|
145
|
+
opts[:count] ||= 10
|
|
181
146
|
opts[:order] = order
|
|
182
147
|
opts[:output] = options[:interactive] ? nil : options[:output]
|
|
183
148
|
opts[:output] = output_format
|
|
@@ -186,8 +151,6 @@ command :view do |c|
|
|
|
186
151
|
opts[:section] = section
|
|
187
152
|
opts[:tag_filter] = tag_filter
|
|
188
153
|
opts[:tag_order] = tag_order
|
|
189
|
-
opts[:tags_color] = tags_color
|
|
190
|
-
opts[:template] = template
|
|
191
154
|
opts[:totals] = totals
|
|
192
155
|
opts[:view_template] = title
|
|
193
156
|
|
data/bin/commands/views.rb
CHANGED
|
@@ -1,11 +1,108 @@
|
|
|
1
1
|
# @@views
|
|
2
|
-
desc 'List available custom views'
|
|
2
|
+
desc 'List available custom views. Specify view names to see YAML configurations.'
|
|
3
|
+
arg_name 'NAME(S)', optional: true
|
|
3
4
|
command :views do |c|
|
|
5
|
+
c.example 'doing views', desc: 'list all views'
|
|
6
|
+
c.example 'doing views -c', desc: 'list views in column, ideal for shell completion'
|
|
7
|
+
c.example 'doing views color', desc: 'dump the YAML for a single view'
|
|
8
|
+
c.example 'doing views -e color', desc: 'edit the YAML configuration for a single view'
|
|
9
|
+
c.example 'doing views -e -o json color finished', desc: 'edit multiple view configs as JSON'
|
|
10
|
+
|
|
4
11
|
c.desc 'List in single column'
|
|
5
|
-
c.switch %i[c column], default_value: false
|
|
12
|
+
c.switch %i[c column], default_value: false, negatable: false
|
|
13
|
+
|
|
14
|
+
c.desc 'Open YAML for view in editor (requires argument)'
|
|
15
|
+
c.switch %i[e editor], negatable: false
|
|
16
|
+
|
|
17
|
+
c.desc 'Output/edit view in alternative format (json, yaml)'
|
|
18
|
+
c.arg_name 'FORMAT'
|
|
19
|
+
c.flag %i[o output], must_match: /^[jy]/i, default_value: 'yaml'
|
|
20
|
+
|
|
21
|
+
c.desc 'Delete view config'
|
|
22
|
+
c.switch %i[r remove], negatable: false
|
|
23
|
+
|
|
24
|
+
c.action do |_global_options, options, args|
|
|
25
|
+
cmd = Doing::ViewsCommand.new(options, args, @wwid)
|
|
26
|
+
|
|
27
|
+
if args.count.positive?
|
|
28
|
+
if options[:remove]
|
|
29
|
+
cmd.remove_views
|
|
30
|
+
elsif options[:editor]
|
|
31
|
+
cmd.edit_views
|
|
32
|
+
else
|
|
33
|
+
cmd.output_views
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
cmd.list_views
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module Doing
|
|
42
|
+
# views Command
|
|
43
|
+
class ViewsCommand
|
|
44
|
+
def initialize(options, args, wwid)
|
|
45
|
+
@options = options
|
|
46
|
+
@args = args
|
|
47
|
+
@wwid = wwid
|
|
48
|
+
|
|
49
|
+
@views = {}
|
|
50
|
+
args.each do |v|
|
|
51
|
+
view = @wwid.get_view(v)
|
|
52
|
+
raise InvalidArgument, 'Unrecognized view' unless view
|
|
53
|
+
|
|
54
|
+
@views[v] = view if view
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def list_views
|
|
59
|
+
joiner = @options[:column] ? "\n" : "\t"
|
|
60
|
+
print @wwid.views.join(joiner)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def save_view(view, res)
|
|
64
|
+
val = if res.nil? || !res.key?(view) || res[view]&.empty?
|
|
65
|
+
nil
|
|
66
|
+
else
|
|
67
|
+
res[view]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
Doing.set("views.#{view}", val)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def remove_views
|
|
74
|
+
@args.each do |v|
|
|
75
|
+
Doing.set("views.#{v}", nil)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
save_config
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def edit_views
|
|
82
|
+
res = if @options[:output] =~ /^j/i
|
|
83
|
+
JSON.parse(@wwid.fork_editor(JSON.pretty_generate(@views), message: nil))
|
|
84
|
+
else
|
|
85
|
+
YAML.safe_load(@wwid.fork_editor(YAML.dump(@views), message: nil))
|
|
86
|
+
end
|
|
87
|
+
@args.each do |v|
|
|
88
|
+
save_view(v, res)
|
|
89
|
+
end
|
|
90
|
+
save_config
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def output_views
|
|
94
|
+
out = if @options[:output] =~ /^j/i
|
|
95
|
+
JSON.pretty_generate(@views)
|
|
96
|
+
else
|
|
97
|
+
YAML.dump(@views)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
Doing::Pager.page out
|
|
101
|
+
end
|
|
6
102
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
103
|
+
def save_config
|
|
104
|
+
Doing::Util.write_to_file(Doing.config.config_file, YAML.dump(Doing.settings), backup: true)
|
|
105
|
+
Doing.logger.warn('Config:', "#{Doing.config.config_file} updated")
|
|
106
|
+
end
|
|
10
107
|
end
|
|
11
108
|
end
|
data/bin/commands/yesterday.rb
CHANGED
|
@@ -14,6 +14,7 @@ command :yesterday do |c|
|
|
|
14
14
|
add_options(:output_template, c, default_template: 'today')
|
|
15
15
|
add_options(:time_filter, c)
|
|
16
16
|
add_options(:time_display, c)
|
|
17
|
+
add_options(:save, c)
|
|
17
18
|
|
|
18
19
|
c.action do |_global_options, options, _args|
|
|
19
20
|
raise InvalidPlugin.new('output', options[:output]) if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
@@ -22,7 +23,8 @@ command :yesterday do |c|
|
|
|
22
23
|
|
|
23
24
|
opt = options.clone
|
|
24
25
|
opt[:order] = Doing.setting(['templates', options[:config_template], 'order'])
|
|
25
|
-
|
|
26
|
+
opt[:yesterday] = true
|
|
26
27
|
Doing::Pager.page @wwid.yesterday(options[:section], options[:times], options[:output], opt).chomp
|
|
28
|
+
Doing.config.save_view(opt.to_view, options[:save].downcase) if options[:save]
|
|
27
29
|
end
|
|
28
30
|
end
|
data/bin/doing
CHANGED
|
@@ -26,7 +26,7 @@ include Doing::Errors
|
|
|
26
26
|
|
|
27
27
|
version Doing::VERSION
|
|
28
28
|
hide_commands_without_desc true
|
|
29
|
-
autocomplete_commands
|
|
29
|
+
autocomplete_commands false
|
|
30
30
|
wrap_help_text :one_line unless $stdout.isatty
|
|
31
31
|
|
|
32
32
|
include Doing::Types
|
|
@@ -88,14 +88,33 @@ accept TagSortSymbol do |value|
|
|
|
88
88
|
value.normalize_tag_sort(Doing.config.fetch('tag_sort', :name))
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
accept ExportTemplate do |value|
|
|
92
|
+
if value !~ Doing::Plugins.plugin_regex(type: :export)
|
|
93
|
+
raise Doing::Errors::InvalidPlugin.new('output', value)
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
tpl = nil
|
|
98
|
+
|
|
99
|
+
Doing::Plugins.plugins[:export].each do |k, options|
|
|
100
|
+
next unless value =~ /^(#{options[:trigger].normalize_trigger})$/i
|
|
101
|
+
|
|
102
|
+
tpl = k
|
|
103
|
+
break
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
tpl.nil? ? 'template' : value
|
|
107
|
+
end
|
|
108
|
+
|
|
91
109
|
accept TemplateName do |value|
|
|
92
110
|
res = Doing.setting('templates').keys.select { |k| k =~ value.to_rx(distance: 2) }
|
|
93
|
-
raise InvalidArgument, "Unknown template: #{value}" unless res.good?
|
|
111
|
+
raise Doing::Errors::InvalidArgument, "Unknown template: #{value}" unless res.good?
|
|
94
112
|
|
|
95
113
|
res.group_by(&:length).min.last[0]
|
|
96
114
|
end
|
|
97
115
|
|
|
98
116
|
accept DateBeginString do |value|
|
|
117
|
+
Doing.original_options[:date_begin] = value
|
|
99
118
|
res = if value =~ REGEX_TIME
|
|
100
119
|
value
|
|
101
120
|
else
|
|
@@ -107,6 +126,7 @@ accept DateBeginString do |value|
|
|
|
107
126
|
end
|
|
108
127
|
|
|
109
128
|
accept DateEndString do |value|
|
|
129
|
+
Doing.original_options[:date_end] = value
|
|
110
130
|
res = if value =~ REGEX_TIME
|
|
111
131
|
value
|
|
112
132
|
else
|
|
@@ -118,6 +138,7 @@ accept DateEndString do |value|
|
|
|
118
138
|
end
|
|
119
139
|
|
|
120
140
|
accept DateRangeString do |value|
|
|
141
|
+
Doing.original_options[:date_range] = value
|
|
121
142
|
start, finish = value.split_date_range
|
|
122
143
|
raise InvalidTimeExpression, 'Invalid range' unless start
|
|
123
144
|
|
|
@@ -126,6 +147,7 @@ accept DateRangeString do |value|
|
|
|
126
147
|
end
|
|
127
148
|
|
|
128
149
|
accept DateRangeOptionalString do |value|
|
|
150
|
+
Doing.original_options[:date_range] = value
|
|
129
151
|
start, finish = value.split_date_range
|
|
130
152
|
raise InvalidTimeExpression, 'Invalid range' unless start
|
|
131
153
|
|
|
@@ -133,6 +155,7 @@ accept DateRangeOptionalString do |value|
|
|
|
133
155
|
end
|
|
134
156
|
|
|
135
157
|
accept DateIntervalString do |value|
|
|
158
|
+
Doing.original_options[:date_interval] = value
|
|
136
159
|
res = value.chronify_qty
|
|
137
160
|
raise InvalidTimeExpression, 'Invalid time quantity' unless res
|
|
138
161
|
|
|
@@ -233,16 +256,20 @@ pre do |global, _command, _options, _args|
|
|
|
233
256
|
end
|
|
234
257
|
|
|
235
258
|
on_error do |exception|
|
|
236
|
-
|
|
259
|
+
case exception
|
|
260
|
+
when GLI::UnknownCommand
|
|
237
261
|
if ARGV.count > 1
|
|
262
|
+
exit run(['view'].concat(ARGV.unshift(@command))) if @wwid.get_view(@command, fallback: false)
|
|
238
263
|
exit run(['now'].concat(ARGV.unshift(@command)))
|
|
239
264
|
else
|
|
265
|
+
exit run(['view'].concat(ARGV.unshift(@command))) if @wwid.get_view(@command, fallback: false)
|
|
266
|
+
|
|
240
267
|
Doing::Color.coloring = $stdout.isatty
|
|
241
268
|
Doing.logger.error('Unknown Command:', @command)
|
|
242
269
|
Doing.logger.output_results
|
|
243
270
|
false
|
|
244
271
|
end
|
|
245
|
-
|
|
272
|
+
when SystemExit
|
|
246
273
|
false
|
|
247
274
|
else
|
|
248
275
|
# Doing.logger.error('Fatal:', exception)
|
data/docs/doc/Array.html
CHANGED
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
|
|
90
90
|
<dl>
|
|
91
91
|
<dt>Includes:</dt>
|
|
92
|
-
<dd>ArrayNestedHash, ArrayTags, <span class='object_link'><a href="Doing/ChronifyArray.html" title="Doing::ChronifyArray (module)">Doing::ChronifyArray</a></span></dd>
|
|
92
|
+
<dd>ArrayCleanup, ArrayNestedHash, ArrayTags, <span class='object_link'><a href="Doing/ChronifyArray.html" title="Doing::ChronifyArray (module)">Doing::ChronifyArray</a></span></dd>
|
|
93
93
|
</dl>
|
|
94
94
|
|
|
95
95
|
|
|
@@ -106,7 +106,17 @@
|
|
|
106
106
|
|
|
107
107
|
</div>
|
|
108
108
|
|
|
109
|
-
<div
|
|
109
|
+
<h2>Overview</h2><div class="docstring">
|
|
110
|
+
<div class="discussion">
|
|
111
|
+
<p>Array helpers</p>
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="tags">
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
</div><div id="subclasses">
|
|
110
120
|
<h2>Direct Known Subclasses</h2>
|
|
111
121
|
<p class="children"><span class='object_link'><a href="Doing/Items.html" title="Doing::Items (class)">Doing::Items</a></span>, <span class='object_link'><a href="Doing/Note.html" title="Doing::Note (class)">Doing::Note</a></span></p>
|
|
112
122
|
</div>
|
|
@@ -188,6 +198,7 @@
|
|
|
188
198
|
|
|
189
199
|
|
|
190
200
|
|
|
201
|
+
|
|
191
202
|
|
|
192
203
|
<div id="instance_method_details" class="method_details_list">
|
|
193
204
|
<h2>Instance Method Details</h2>
|
|
@@ -277,7 +288,7 @@ has content</p>
|
|
|
277
288
|
</div>
|
|
278
289
|
|
|
279
290
|
<div id="footer">
|
|
280
|
-
Generated on
|
|
291
|
+
Generated on Mon Mar 21 07:53:15 2022 by
|
|
281
292
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
282
293
|
0.9.27 (ruby-3.0.1).
|
|
283
294
|
</div>
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
</div>
|
|
284
284
|
|
|
285
285
|
<div id="footer">
|
|
286
|
-
Generated on
|
|
286
|
+
Generated on Mon Mar 21 07:53:16 2022 by
|
|
287
287
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
288
288
|
0.9.27 (ruby-3.0.1).
|
|
289
289
|
</div>
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
</div>
|
|
163
163
|
|
|
164
164
|
<div id="footer">
|
|
165
|
-
Generated on
|
|
165
|
+
Generated on Mon Mar 21 07:53:16 2022 by
|
|
166
166
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
167
167
|
0.9.27 (ruby-3.0.1).
|
|
168
168
|
</div>
|
|
@@ -407,7 +407,7 @@
|
|
|
407
407
|
</div>
|
|
408
408
|
|
|
409
409
|
<div id="footer">
|
|
410
|
-
Generated on
|
|
410
|
+
Generated on Mon Mar 21 07:53:16 2022 by
|
|
411
411
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
412
412
|
0.9.27 (ruby-3.0.1).
|
|
413
413
|
</div>
|
|
@@ -125,7 +125,7 @@ parser. In order to do that, a new "clause" node is added to the parse
|
|
|
125
125
|
</div>
|
|
126
126
|
|
|
127
127
|
<div id="footer">
|
|
128
|
-
Generated on
|
|
128
|
+
Generated on Mon Mar 21 07:53:16 2022 by
|
|
129
129
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
130
130
|
0.9.27 (ruby-3.0.1).
|
|
131
131
|
</div>
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
116
|
<div id="footer">
|
|
117
|
-
Generated on
|
|
117
|
+
Generated on Mon Mar 21 07:53:16 2022 by
|
|
118
118
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
119
119
|
0.9.27 (ruby-3.0.1).
|
|
120
120
|
</div>
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
</div>
|
|
106
106
|
|
|
107
107
|
<div id="footer">
|
|
108
|
-
Generated on
|
|
108
|
+
Generated on Mon Mar 21 07:53:15 2022 by
|
|
109
109
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
110
110
|
0.9.27 (ruby-3.0.1).
|
|
111
111
|
</div>
|