doing 2.1.26 → 2.1.30
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/.yardoc/checksums +15 -20
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +52 -0
- data/Dockerfile +5 -5
- data/Dockerfile-2.6 +5 -5
- data/Dockerfile-2.7 +5 -4
- data/Dockerfile-3.0 +5 -4
- data/Gemfile.lock +2 -1
- data/README.md +1 -1
- data/Rakefile +2 -3
- data/bin/commands/add_section.rb +2 -0
- data/bin/commands/again.rb +23 -65
- data/bin/commands/archive.rb +20 -61
- data/bin/commands/cancel.rb +27 -69
- data/bin/commands/changes.rb +53 -12
- data/bin/commands/colors.rb +4 -2
- data/bin/commands/commands.rb +4 -2
- data/bin/commands/commands_accepting.rb +62 -11
- data/bin/commands/completion.rb +10 -7
- data/bin/commands/config.rb +8 -8
- data/bin/commands/done.rb +3 -17
- data/bin/commands/finish.rb +7 -30
- data/bin/commands/flag.rb +15 -51
- data/bin/commands/grep.rb +12 -28
- data/bin/commands/import.rb +3 -33
- data/bin/commands/last.rb +3 -36
- data/bin/commands/meanwhile.rb +3 -13
- data/bin/commands/note.rb +13 -52
- data/bin/commands/now.rb +15 -21
- data/bin/commands/on.rb +3 -4
- data/bin/commands/open.rb +3 -3
- data/bin/commands/recent.rb +3 -4
- data/bin/commands/redo.rb +6 -2
- data/bin/commands/reset.rb +19 -52
- data/bin/commands/rotate.rb +5 -36
- data/bin/commands/select.rb +23 -41
- data/bin/commands/show.rb +28 -74
- data/bin/commands/since.rb +3 -4
- data/bin/commands/tag.rb +4 -34
- data/bin/commands/tags.rb +5 -32
- data/bin/commands/today.rb +3 -4
- data/bin/commands/view.rb +36 -73
- data/bin/commands/yesterday.rb +4 -5
- data/bin/doing +150 -13
- data/docs/doc/Array.html +3 -502
- 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/Color.html +62 -56
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +35 -1
- 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/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/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +1 -1
- data/docs/doc/Doing/Items.html +2 -2
- data/docs/doc/Doing/LogAdapter.html +1 -1
- data/docs/doc/Doing/Note.html +2 -2
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Types.html +41 -1
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +10 -10
- data/docs/doc/Doing.html +3 -3
- data/docs/doc/FalseClass.html +35 -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 +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 +287 -3155
- data/docs/doc/Symbol.html +40 -6
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +35 -1
- data/docs/doc/_index.html +5 -10
- 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 +278 -678
- data/docs/doc/top-level-namespace.html +2 -2
- data/doing.gemspec +1 -0
- data/doing.rdoc +297 -206
- data/lib/completion/_doing.zsh +32 -32
- data/lib/completion/doing.bash +30 -30
- data/lib/completion/doing.fish +87 -77
- data/lib/doing/array/array.rb +4 -0
- data/lib/doing/array/nested_hash.rb +17 -0
- data/lib/doing/{array.rb → array/tags.rb} +7 -25
- data/lib/doing/changelog/change.rb +26 -11
- data/lib/doing/changelog/changes.rb +37 -8
- data/lib/doing/changelog/version.rb +11 -3
- data/lib/doing/{array_chronify.rb → chronify/array.rb} +0 -0
- data/lib/doing/chronify/chronify.rb +5 -0
- data/lib/doing/{numeric_chronify.rb → chronify/numeric.rb} +0 -0
- data/lib/doing/{string_chronify.rb → chronify/string.rb} +0 -0
- data/lib/doing/colors.rb +115 -54
- data/lib/doing/completion/zsh_completion.rb +5 -0
- data/lib/doing/configuration.rb +9 -5
- data/lib/doing/good.rb +8 -0
- data/lib/doing/help_monkey_patch.rb +6 -5
- data/lib/doing/item.rb +5 -5
- data/lib/doing/items.rb +2 -2
- data/lib/doing/log_adapter.rb +35 -2
- data/lib/doing/normalize.rb +188 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/html_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +1 -1
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +3 -1
- data/lib/doing/prompt.rb +1 -3
- data/lib/doing/section.rb +1 -1
- data/lib/doing/string/highlight.rb +95 -0
- data/lib/doing/string/query.rb +129 -0
- data/lib/doing/string/string.rb +12 -0
- data/lib/doing/string/tags.rb +164 -0
- data/lib/doing/string/transform.rb +168 -0
- data/lib/doing/string/truncate.rb +75 -0
- data/lib/doing/string/url.rb +82 -0
- data/lib/doing/template_string.rb +0 -22
- data/lib/doing/types.rb +8 -0
- data/lib/doing/util.rb +13 -9
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +54 -36
- data/lib/doing.rb +5 -6
- data/lib/examples/plugins/wiki_export/wiki_export.rb +1 -1
- data/lib/helpers/threaded_tests.rb +15 -2
- data/scripts/deploy.rb +107 -0
- data/scripts/runtests.sh +4 -0
- metadata +39 -8
- data/lib/doing/string.rb +0 -765
- data/lib/doing/symbol.rb +0 -28
data/bin/commands/show.rb
CHANGED
|
@@ -18,69 +18,20 @@ command :show do |c|
|
|
|
18
18
|
c.example 'doing show Ideas @doing --from "mon to fri"', desc: 'Show entries tagged @doing from the Ideas section added between monday and friday of the current week.'
|
|
19
19
|
c.example 'doing show --interactive Later @doing', desc: 'Create a menu from entries from the Later section tagged @doing to perform batch actions'
|
|
20
20
|
|
|
21
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Use `--tag pick` for a menu of available tags. Wildcards allowed (*, ?). Added for compatibility with other commands'
|
|
22
|
-
c.arg_name 'TAG'
|
|
23
|
-
c.flag [:tag], type: TagArray
|
|
24
|
-
|
|
25
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
26
|
-
c.arg_name 'QUERY'
|
|
27
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
28
|
-
|
|
29
|
-
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
|
30
|
-
c.arg_name 'BOOLEAN'
|
|
31
|
-
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
32
|
-
|
|
33
21
|
c.desc 'Max count to show'
|
|
34
22
|
c.arg_name 'MAX'
|
|
35
23
|
c.flag %i[c count], default_value: 0, must_match: /^\d+$/, type: Integer
|
|
36
24
|
|
|
37
25
|
c.desc 'Age (oldest|newest)'
|
|
38
26
|
c.arg_name 'AGE'
|
|
39
|
-
c.flag %i[a age], default_value:
|
|
40
|
-
|
|
41
|
-
c.desc 'Show entries older than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
42
|
-
c.arg_name 'DATE_STRING'
|
|
43
|
-
c.flag [:before], type: DateBeginString
|
|
44
|
-
|
|
45
|
-
c.desc 'Show entries newer than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
46
|
-
c.arg_name 'DATE_STRING'
|
|
47
|
-
c.flag [:after], type: DateEndString
|
|
48
|
-
|
|
49
|
-
c.desc %(
|
|
50
|
-
Date range to show, or a single day to filter date on.
|
|
51
|
-
Date range argument should be quoted. Date specifications can be natural language.
|
|
52
|
-
To specify a range, use "to" or "through": `doing show --from "monday 8am to friday 5pm"`.
|
|
53
|
-
|
|
54
|
-
If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
|
|
55
|
-
by time of day.
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
c.arg_name 'DATE_OR_RANGE'
|
|
59
|
-
c.flag [:from], type: DateRangeString
|
|
60
|
-
|
|
61
|
-
c.desc 'Search filter, surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
|
|
62
|
-
c.arg_name 'QUERY'
|
|
63
|
-
c.flag [:search]
|
|
27
|
+
c.flag %i[a age], default_value: :newest, type: AgeSymbol
|
|
64
28
|
|
|
65
29
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
66
30
|
c.switch %i[h hilite], default_value: @settings.dig('search', 'highlight')
|
|
67
31
|
|
|
68
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
69
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
70
|
-
|
|
71
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
72
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
73
|
-
|
|
74
|
-
c.desc 'Show items that *don\'t* match search/tag/date filters'
|
|
75
|
-
c.switch [:not], default_value: false, negatable: false
|
|
76
|
-
|
|
77
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
78
|
-
c.arg_name 'TYPE'
|
|
79
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
80
|
-
|
|
81
32
|
c.desc 'Sort order (asc/desc)'
|
|
82
33
|
c.arg_name 'ORDER'
|
|
83
|
-
c.flag %i[s sort], must_match: REGEX_SORT_ORDER, default_value:
|
|
34
|
+
c.flag %i[s sort], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
84
35
|
|
|
85
36
|
c.desc 'Show time intervals on @done tasks'
|
|
86
37
|
c.switch %i[t times], default_value: true, negatable: true
|
|
@@ -92,14 +43,13 @@ command :show do |c|
|
|
|
92
43
|
c.switch [:totals], default_value: false, negatable: false
|
|
93
44
|
|
|
94
45
|
c.desc 'Sort tags by (name|time)'
|
|
95
|
-
default = '
|
|
96
|
-
default = @settings['tag_sort'] || 'name'
|
|
46
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
97
47
|
c.arg_name 'KEY'
|
|
98
|
-
c.flag [:tag_sort], must_match:
|
|
48
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
99
49
|
|
|
100
50
|
c.desc 'Tag sort direction (asc|desc)'
|
|
101
51
|
c.arg_name 'DIRECTION'
|
|
102
|
-
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value:
|
|
52
|
+
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
103
53
|
|
|
104
54
|
c.desc 'Only show items with recorded time intervals'
|
|
105
55
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
@@ -121,9 +71,17 @@ command :show do |c|
|
|
|
121
71
|
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
122
72
|
c.arg_name 'FORMAT'
|
|
123
73
|
c.flag %i[o output]
|
|
74
|
+
|
|
75
|
+
add_options(:search, c)
|
|
76
|
+
add_options(:tag_filter, c)
|
|
77
|
+
add_options(:date_filter, c)
|
|
78
|
+
|
|
124
79
|
c.action do |global_options, options, args|
|
|
125
80
|
options[:fuzzy] = false
|
|
126
|
-
|
|
81
|
+
if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
82
|
+
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}")
|
|
83
|
+
|
|
84
|
+
end
|
|
127
85
|
|
|
128
86
|
tag_filter = false
|
|
129
87
|
tags = []
|
|
@@ -142,7 +100,7 @@ command :show do |c|
|
|
|
142
100
|
else
|
|
143
101
|
begin
|
|
144
102
|
section = @wwid.guess_section(args[0])
|
|
145
|
-
rescue WrongCommand
|
|
103
|
+
rescue WrongCommand
|
|
146
104
|
cmd = commands[:view]
|
|
147
105
|
action = cmd.send(:get_action, nil)
|
|
148
106
|
return action.call(global_options, options, args)
|
|
@@ -155,8 +113,8 @@ command :show do |c|
|
|
|
155
113
|
if args.length.positive?
|
|
156
114
|
args.each do |arg|
|
|
157
115
|
arg.split(/,/).each do |tag|
|
|
158
|
-
|
|
159
|
-
|
|
116
|
+
tags.push(tag.strip.sub(/^@/, ''))
|
|
117
|
+
end
|
|
160
118
|
end
|
|
161
119
|
end
|
|
162
120
|
else
|
|
@@ -169,13 +127,11 @@ command :show do |c|
|
|
|
169
127
|
options[:times] = true if options[:totals]
|
|
170
128
|
|
|
171
129
|
template = @settings['templates'][options[:config_template]].deep_merge({
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
options[:case] = options[:case].normalize_case
|
|
130
|
+
'wrap_width' => @settings['wrap_width'] || 0,
|
|
131
|
+
'date_format' => @settings['default_date_format'],
|
|
132
|
+
'order' => @settings['order']&.normalize_order || :asc,
|
|
133
|
+
'tags_color' => @settings['tags_color']
|
|
134
|
+
})
|
|
179
135
|
|
|
180
136
|
if options[:search]
|
|
181
137
|
search = options[:search]
|
|
@@ -188,7 +144,7 @@ command :show do |c|
|
|
|
188
144
|
if tags.good?
|
|
189
145
|
tag_filter = {
|
|
190
146
|
'tags' => tags,
|
|
191
|
-
'bool' => options[:bool]
|
|
147
|
+
'bool' => options[:bool]
|
|
192
148
|
}
|
|
193
149
|
end
|
|
194
150
|
|
|
@@ -198,32 +154,30 @@ command :show do |c|
|
|
|
198
154
|
items = @wwid.filter_items([], opt: options)
|
|
199
155
|
|
|
200
156
|
if options[:menu]
|
|
157
|
+
Doing.logger.benchmark(:menu, :start)
|
|
201
158
|
tag = @wwid.choose_tag(section, items: items, include_all: true)
|
|
202
159
|
raise UserCancelled unless tag
|
|
203
160
|
|
|
204
|
-
# options[:bool] = :and unless tags.empty?
|
|
205
|
-
|
|
206
161
|
tags = tag.split(/ +/).map { |t| t.strip.sub(/^@?/, '') } if tag =~ /^@/
|
|
207
162
|
if tags.good?
|
|
208
163
|
tag_filter = {
|
|
209
164
|
'tags' => tags,
|
|
210
|
-
'bool' => options[:bool]
|
|
165
|
+
'bool' => options[:bool]
|
|
211
166
|
}
|
|
212
167
|
options[:tag_filter] = tag_filter
|
|
213
168
|
end
|
|
169
|
+
Doing.logger.benchmark(:menu, :finish)
|
|
214
170
|
end
|
|
215
171
|
|
|
216
172
|
options[:age] ||= :newest
|
|
217
173
|
|
|
218
174
|
opt = options.clone
|
|
219
|
-
opt[:
|
|
220
|
-
opt[:sort_tags] = options[:tag_sort] =~ /^n/i
|
|
175
|
+
opt[:sort_tags] = options[:tag_sort]
|
|
221
176
|
opt[:count] = options[:count].to_i
|
|
222
177
|
opt[:highlight] = true
|
|
223
178
|
opt[:hilite] = options[:hilite]
|
|
224
|
-
opt[:order] = options[:sort]
|
|
179
|
+
opt[:order] = options[:sort]
|
|
225
180
|
opt[:tag] = nil
|
|
226
|
-
opt[:tag_order] = options[:tag_order].normalize_order
|
|
227
181
|
opt[:tags_color] = template['tags_color']
|
|
228
182
|
|
|
229
183
|
Doing::Pager.page @wwid.list_section(opt, items: items)
|
data/bin/commands/since.rb
CHANGED
|
@@ -21,10 +21,9 @@ command :since do |c|
|
|
|
21
21
|
c.switch [:totals], default_value: false, negatable: false
|
|
22
22
|
|
|
23
23
|
c.desc 'Sort tags by (name|time)'
|
|
24
|
-
default = '
|
|
25
|
-
default = @settings['tag_sort'] || 'name'
|
|
24
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
26
25
|
c.arg_name 'KEY'
|
|
27
|
-
c.flag [:tag_sort], must_match:
|
|
26
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
28
27
|
|
|
29
28
|
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
30
29
|
c.arg_name 'FORMAT'
|
|
@@ -56,7 +55,7 @@ command :since do |c|
|
|
|
56
55
|
Doing.logger.debug('Interpreter:', "date interpreted as #{start} through the current time")
|
|
57
56
|
|
|
58
57
|
options[:times] = true if options[:totals]
|
|
59
|
-
options[:sort_tags] = options[:tag_sort]
|
|
58
|
+
options[:sort_tags] = options[:tag_sort]
|
|
60
59
|
|
|
61
60
|
Doing::Pager.page @wwid.list_date([start, finish], options[:section], options[:times], options[:output],
|
|
62
61
|
{ template: options[:template], config_template: options[:config_template], duration: options[:duration], totals: options[:totals], sort_tags: options[:sort_tags] }).chomp
|
data/bin/commands/tag.rb
CHANGED
|
@@ -55,39 +55,12 @@ command :tag do |c|
|
|
|
55
55
|
c.desc 'Autotag entries based on autotag configuration in ~/.config/doing/config.yml'
|
|
56
56
|
c.switch %i[a autotag], negatable: false, default_value: false
|
|
57
57
|
|
|
58
|
-
c.desc 'Tag the last X entries containing TAG.
|
|
59
|
-
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
|
60
|
-
c.arg_name 'TAG'
|
|
61
|
-
c.flag [:tag], type: TagArray
|
|
62
|
-
|
|
63
|
-
c.desc 'Tag entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
|
64
|
-
c.arg_name 'QUERY'
|
|
65
|
-
c.flag [:search]
|
|
66
|
-
|
|
67
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
68
|
-
c.arg_name 'QUERY'
|
|
69
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
70
|
-
|
|
71
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
72
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
73
|
-
|
|
74
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
75
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
76
|
-
|
|
77
|
-
c.desc 'Tag items that *don\'t* match search/tag filters'
|
|
78
|
-
c.switch [:not], default_value: false, negatable: false
|
|
79
|
-
|
|
80
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
81
|
-
c.arg_name 'TYPE'
|
|
82
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
83
|
-
|
|
84
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
|
85
|
-
c.arg_name 'BOOLEAN'
|
|
86
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
87
|
-
|
|
88
58
|
c.desc 'Select item(s) to tag from a menu of matching entries'
|
|
89
59
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
90
60
|
|
|
61
|
+
add_options(:search, c)
|
|
62
|
+
add_options(:tag_filter, c)
|
|
63
|
+
|
|
91
64
|
c.action do |_global_options, options, args|
|
|
92
65
|
options[:fuzzy] = false
|
|
93
66
|
# raise MissingArgument, 'You must specify at least one tag' if args.empty? && !options[:autotag]
|
|
@@ -130,9 +103,6 @@ command :tag do |c|
|
|
|
130
103
|
count = options[:count].to_i
|
|
131
104
|
end
|
|
132
105
|
|
|
133
|
-
options[:case] ||= :smart
|
|
134
|
-
options[:case] = options[:case].normalize_case
|
|
135
|
-
|
|
136
106
|
if options[:search]
|
|
137
107
|
search = options[:search]
|
|
138
108
|
search.sub!(/^'?/, "'") if options[:exact]
|
|
@@ -143,7 +113,7 @@ command :tag do |c|
|
|
|
143
113
|
options[:section] = section
|
|
144
114
|
options[:tag] = search_tags
|
|
145
115
|
options[:tags] = tags
|
|
146
|
-
options[:tag_bool] = options[:bool]
|
|
116
|
+
options[:tag_bool] = options[:bool]
|
|
147
117
|
|
|
148
118
|
if count.zero? && !options[:force]
|
|
149
119
|
matches = @wwid.filter_items([], opt: options).count
|
data/bin/commands/tags.rb
CHANGED
|
@@ -18,41 +18,14 @@ command :tags do |c|
|
|
|
18
18
|
|
|
19
19
|
c.desc 'Sort order (asc/desc)'
|
|
20
20
|
c.arg_name 'ORDER'
|
|
21
|
-
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value:
|
|
22
|
-
|
|
23
|
-
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
24
|
-
c.arg_name 'TAG'
|
|
25
|
-
c.flag [:tag]
|
|
26
|
-
|
|
27
|
-
c.desc 'Get tags for items matching search. Surround with
|
|
28
|
-
slashes for regex (e.g. "/query/"), start with a single quote for exact match ("\'query").'
|
|
29
|
-
c.arg_name 'QUERY'
|
|
30
|
-
c.flag [:search]
|
|
31
|
-
|
|
32
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
33
|
-
c.arg_name 'QUERY'
|
|
34
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
35
|
-
|
|
36
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
37
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
38
|
-
|
|
39
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
40
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
41
|
-
|
|
42
|
-
c.desc 'Get tags from items that *don\'t* match search/tag filters'
|
|
43
|
-
c.switch [:not], default_value: false, negatable: false
|
|
44
|
-
|
|
45
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
46
|
-
c.arg_name 'TYPE'
|
|
47
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
48
|
-
|
|
49
|
-
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
|
50
|
-
c.arg_name 'BOOLEAN'
|
|
51
|
-
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
21
|
+
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
52
22
|
|
|
53
23
|
c.desc 'Select items to scan from a menu of matching entries'
|
|
54
24
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
55
25
|
|
|
26
|
+
add_options(:search, c)
|
|
27
|
+
add_options(:tag_filter, c)
|
|
28
|
+
|
|
56
29
|
c.action do |_global, options, args|
|
|
57
30
|
section = @wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
58
31
|
options[:count] = args.count.positive? ? args[0].to_i : 0
|
|
@@ -78,7 +51,7 @@ command :tags do |c|
|
|
|
78
51
|
tags = tags.sort_by { |tag, count| count }
|
|
79
52
|
end
|
|
80
53
|
|
|
81
|
-
tags.reverse! if options[:order]
|
|
54
|
+
tags.reverse! if options[:order] == :desc
|
|
82
55
|
|
|
83
56
|
if options[:counts]
|
|
84
57
|
tags.each { |t, c| puts "#{t} (#{c})" }
|
data/bin/commands/today.rb
CHANGED
|
@@ -22,10 +22,9 @@ command :today do |c|
|
|
|
22
22
|
c.switch [:totals], default_value: false, negatable: false
|
|
23
23
|
|
|
24
24
|
c.desc 'Sort tags by (name|time)'
|
|
25
|
-
default = '
|
|
26
|
-
default = @settings['tag_sort'] || 'name'
|
|
25
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
27
26
|
c.arg_name 'KEY'
|
|
28
|
-
c.flag [:tag_sort], must_match:
|
|
27
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
29
28
|
|
|
30
29
|
c.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
|
|
31
30
|
c.arg_name 'FORMAT'
|
|
@@ -57,7 +56,7 @@ command :today do |c|
|
|
|
57
56
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
58
57
|
|
|
59
58
|
options[:times] = true if options[:totals]
|
|
60
|
-
options[:sort_tags] = options[:tag_sort]
|
|
59
|
+
options[:sort_tags] = options[:tag_sort]
|
|
61
60
|
filter_options = %i[after before duration from section sort_tags totals template config_template].each_with_object({}) { |k, hsh| hsh[k] = options[k] }
|
|
62
61
|
|
|
63
62
|
Doing::Pager.page @wwid.today(options[:times], options[:output], filter_options).chomp
|
data/bin/commands/view.rb
CHANGED
|
@@ -21,7 +21,7 @@ command :view do |c|
|
|
|
21
21
|
|
|
22
22
|
c.desc 'Age (oldest|newest)'
|
|
23
23
|
c.arg_name 'AGE'
|
|
24
|
-
c.flag %i[age], default_value:
|
|
24
|
+
c.flag %i[age], default_value: :newest, type: AgeSymbol
|
|
25
25
|
|
|
26
26
|
c.desc 'Show time intervals on @done tasks'
|
|
27
27
|
c.switch %i[t times], default_value: true, negatable: true
|
|
@@ -35,64 +35,16 @@ command :view do |c|
|
|
|
35
35
|
c.desc 'Include colors in output'
|
|
36
36
|
c.switch [:color], default_value: true, negatable: true
|
|
37
37
|
|
|
38
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
|
39
|
-
c.arg_name 'TAG'
|
|
40
|
-
c.flag [:tag]
|
|
41
|
-
|
|
42
|
-
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
|
43
|
-
c.arg_name 'QUERY'
|
|
44
|
-
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
|
45
|
-
|
|
46
|
-
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
|
47
|
-
c.arg_name 'BOOLEAN'
|
|
48
|
-
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
|
49
|
-
|
|
50
|
-
c.desc 'Search filter, surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
|
|
51
|
-
c.arg_name 'QUERY'
|
|
52
|
-
c.flag [:search]
|
|
53
|
-
|
|
54
38
|
c.desc "Highlight search matches in output. Only affects command line output"
|
|
55
39
|
c.switch %i[h hilite], default_value: @settings.dig('search', 'highlight')
|
|
56
40
|
|
|
57
|
-
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
|
58
|
-
# c.switch [:fuzzy], default_value: false, negatable: false
|
|
59
|
-
|
|
60
|
-
c.desc 'Force exact search string matching (case sensitive)'
|
|
61
|
-
c.switch %i[x exact], default_value: @config.exact_match?, negatable: @config.exact_match?
|
|
62
|
-
|
|
63
|
-
c.desc 'Show items that *don\'t* match search string'
|
|
64
|
-
c.switch [:not], default_value: false, negatable: false
|
|
65
|
-
|
|
66
|
-
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
67
|
-
c.arg_name 'TYPE'
|
|
68
|
-
c.flag [:case], must_match: /^[csi]/, default_value: @settings.dig('search', 'case')
|
|
69
|
-
|
|
70
41
|
c.desc 'Sort tags by (name|time)'
|
|
71
42
|
c.arg_name 'KEY'
|
|
72
|
-
c.flag [:tag_sort], must_match:
|
|
43
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, type: TagSortSymbol
|
|
73
44
|
|
|
74
45
|
c.desc 'Tag sort direction (asc|desc)'
|
|
75
46
|
c.arg_name 'DIRECTION'
|
|
76
|
-
c.flag [:tag_order], must_match: REGEX_SORT_ORDER
|
|
77
|
-
|
|
78
|
-
c.desc 'View entries older than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
79
|
-
c.arg_name 'DATE_STRING'
|
|
80
|
-
c.flag [:before], type: DateBeginString
|
|
81
|
-
|
|
82
|
-
c.desc 'View entries newer than date. If this is only a time (8am, 1:30pm, 15:00), all dates will be included, but entries will be filtered by time of day'
|
|
83
|
-
c.arg_name 'DATE_STRING'
|
|
84
|
-
c.flag [:after], type: DateEndString
|
|
85
|
-
|
|
86
|
-
c.desc %(
|
|
87
|
-
Date range to show, or a single day to filter date on.
|
|
88
|
-
Date range argument should be quoted. Date specifications can be natural language.
|
|
89
|
-
To specify a range, use "to" or "through": `doing view --from "monday 8am to friday 5pm" view_name`.
|
|
90
|
-
|
|
91
|
-
If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
|
|
92
|
-
by time of day.
|
|
93
|
-
)
|
|
94
|
-
c.arg_name 'DATE_OR_RANGE'
|
|
95
|
-
c.flag [:from], type: DateRangeString
|
|
47
|
+
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, type: OrderSymbol
|
|
96
48
|
|
|
97
49
|
c.desc 'Only show items with recorded time intervals (override view settings)'
|
|
98
50
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
@@ -100,9 +52,16 @@ command :view do |c|
|
|
|
100
52
|
c.desc 'Select from a menu of matching entries to perform additional operations'
|
|
101
53
|
c.switch %i[i interactive], negatable: false, default_value: false
|
|
102
54
|
|
|
55
|
+
add_options(:search, c)
|
|
56
|
+
add_options(:tag_filter, c)
|
|
57
|
+
add_options(:date_filter, c)
|
|
58
|
+
|
|
103
59
|
c.action do |global_options, options, args|
|
|
104
60
|
options[:fuzzy] = false
|
|
105
|
-
|
|
61
|
+
if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
62
|
+
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}")
|
|
63
|
+
|
|
64
|
+
end
|
|
106
65
|
|
|
107
66
|
raise InvalidArgument, '--tag and --search can not be used together' if options[:tag] && options[:search]
|
|
108
67
|
|
|
@@ -111,20 +70,20 @@ command :view do |c|
|
|
|
111
70
|
else
|
|
112
71
|
begin
|
|
113
72
|
@wwid.guess_view(args[0])
|
|
114
|
-
rescue WrongCommand
|
|
73
|
+
rescue WrongCommand
|
|
115
74
|
cmd = commands[:show]
|
|
116
|
-
options[:sort] =
|
|
117
|
-
options[:tag_order] =
|
|
75
|
+
options[:sort] = :asc
|
|
76
|
+
options[:tag_order] = :asc
|
|
118
77
|
action = cmd.send(:get_action, nil)
|
|
119
78
|
return action.call(global_options, options, args)
|
|
120
79
|
end
|
|
121
80
|
end
|
|
122
81
|
|
|
123
|
-
if options[:section]
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
82
|
+
section = if options[:section]
|
|
83
|
+
@wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
84
|
+
else
|
|
85
|
+
@settings['current_section']
|
|
86
|
+
end
|
|
128
87
|
|
|
129
88
|
view = @wwid.get_view(title)
|
|
130
89
|
|
|
@@ -143,7 +102,7 @@ command :view do |c|
|
|
|
143
102
|
tag_filter = false
|
|
144
103
|
if options[:tag]
|
|
145
104
|
tag_filter = { 'tags' => [], 'bool' => 'OR' }
|
|
146
|
-
bool = options[:bool]
|
|
105
|
+
bool = options[:bool]
|
|
147
106
|
tag_filter['bool'] = bool
|
|
148
107
|
tag_filter['tags'] = if bool == :pattern
|
|
149
108
|
options[:tag]
|
|
@@ -164,41 +123,45 @@ command :view do |c|
|
|
|
164
123
|
# If the -o/--output flag was specified, override any default in the view template
|
|
165
124
|
options[:output] ||= view.key?('output_format') ? view['output_format'] : 'template'
|
|
166
125
|
|
|
167
|
-
count =
|
|
126
|
+
count = if options[:count]
|
|
127
|
+
options[:count]
|
|
128
|
+
elsif view.key?('count')
|
|
129
|
+
view['count']
|
|
130
|
+
else
|
|
131
|
+
10
|
|
132
|
+
end
|
|
168
133
|
|
|
169
134
|
section = if options[:section]
|
|
170
135
|
section
|
|
171
136
|
else
|
|
172
137
|
view['section'] || @settings['current_section']
|
|
173
138
|
end
|
|
174
|
-
order = view
|
|
139
|
+
order = if view.key?('order')
|
|
140
|
+
view['order'].normalize_order
|
|
141
|
+
else
|
|
142
|
+
:asc
|
|
143
|
+
end
|
|
175
144
|
|
|
176
145
|
totals = if options[:totals]
|
|
177
146
|
true
|
|
178
147
|
else
|
|
179
148
|
view['totals'] || false
|
|
180
149
|
end
|
|
181
|
-
tag_order =
|
|
182
|
-
options[:tag_order].normalize_order
|
|
183
|
-
else
|
|
184
|
-
view['tag_order']&.normalize_order || 'asc'
|
|
185
|
-
end
|
|
150
|
+
tag_order = options[:tag_order] || view['tag_order']&.normalize_order || :asc
|
|
186
151
|
|
|
187
152
|
options[:times] = true if totals
|
|
188
153
|
output_format = options[:output]&.downcase || 'template'
|
|
189
154
|
|
|
190
155
|
options[:sort_tags] = if options[:tag_sort]
|
|
191
|
-
options[:tag_sort]
|
|
156
|
+
options[:tag_sort]
|
|
192
157
|
elsif view.key?('tag_sort')
|
|
193
|
-
view['tag_sort']
|
|
158
|
+
view['tag_sort'].normalize_tag_sort
|
|
194
159
|
else
|
|
195
160
|
false
|
|
196
161
|
end
|
|
197
162
|
|
|
198
163
|
%w[before after from duration].each { |k| options[k.to_sym] = view[k] if view.key?(k) && !options[k.to_sym] }
|
|
199
164
|
|
|
200
|
-
options[:case] = options[:case].normalize_case
|
|
201
|
-
|
|
202
165
|
search = nil
|
|
203
166
|
|
|
204
167
|
if options[:search]
|
|
@@ -209,7 +172,7 @@ command :view do |c|
|
|
|
209
172
|
options[:age] ||= :newest
|
|
210
173
|
|
|
211
174
|
opts = options.clone
|
|
212
|
-
opts[:age] = options[:age]
|
|
175
|
+
opts[:age] = options[:age]
|
|
213
176
|
opts[:count] = count
|
|
214
177
|
opts[:format] = date_format
|
|
215
178
|
opts[:highlight] = options[:color]
|
data/bin/commands/yesterday.rb
CHANGED
|
@@ -33,9 +33,9 @@ command :yesterday do |c|
|
|
|
33
33
|
c.switch [:totals], default_value: false, negatable: false
|
|
34
34
|
|
|
35
35
|
c.desc 'Sort tags by (name|time)'
|
|
36
|
-
default = @settings['tag_sort'] ||
|
|
36
|
+
default = @settings['tag_sort'].normalize_tag_sort || :name
|
|
37
37
|
c.arg_name 'KEY'
|
|
38
|
-
c.flag [:tag_sort], must_match:
|
|
38
|
+
c.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
|
|
39
39
|
|
|
40
40
|
c.desc 'View entries before specified time (e.g. 8am, 12:30pm, 15:00)'
|
|
41
41
|
c.arg_name 'TIME_STRING'
|
|
@@ -51,12 +51,12 @@ command :yesterday do |c|
|
|
|
51
51
|
|
|
52
52
|
c.desc 'Tag sort direction (asc|desc)'
|
|
53
53
|
c.arg_name 'DIRECTION'
|
|
54
|
-
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value:
|
|
54
|
+
c.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
|
|
55
55
|
|
|
56
56
|
c.action do |_global_options, options, _args|
|
|
57
57
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
|
58
58
|
|
|
59
|
-
options[:sort_tags] = options[:tag_sort]
|
|
59
|
+
options[:sort_tags] = options[:tag_sort]
|
|
60
60
|
|
|
61
61
|
if options[:from]
|
|
62
62
|
options[:from] = options[:from].split(/#{REGEX_RANGE_INDICATOR}/).map do |time|
|
|
@@ -65,7 +65,6 @@ command :yesterday do |c|
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
opt = options.clone
|
|
68
|
-
opt[:tag_order] = options[:tag_order].normalize_order
|
|
69
68
|
opt[:order] = @settings.dig('templates', options[:config_template], 'order')
|
|
70
69
|
|
|
71
70
|
Doing::Pager.page @wwid.yesterday(options[:section], options[:times], options[:output], opt).chomp
|