doing 2.1.11 → 2.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.irbrc +1 -0
- data/.yardoc/checksums +15 -13
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +44 -1
- data/Gemfile.lock +9 -2
- data/README.md +56 -19
- data/bin/doing +215 -76
- data/docs/doc/Array.html +117 -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/Color.html +1 -1
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +7 -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/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 +337 -14
- data/docs/doc/Doing/Items.html +66 -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 +35 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/Util/Backup.html +84 -1
- data/docs/doc/Doing/Util.html +1 -1
- data/docs/doc/Doing/WWID.html +180 -35
- data/docs/doc/Doing.html +3 -3
- 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/Numeric.html +279 -0
- 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 +767 -115
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/_index.html +14 -9
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +41 -15
- data/docs/doc/index.html +41 -15
- data/docs/doc/method_list.html +407 -279
- data/docs/doc/top-level-namespace.html +2 -2
- data/docs/index.md +56 -19
- data/doing.gemspec +2 -0
- data/doing.rdoc +244 -45
- data/example_plugin.rb +2 -4
- data/lib/completion/_doing.zsh +31 -27
- data/lib/completion/doing.bash +50 -39
- data/lib/completion/doing.fish +35 -6
- data/lib/doing/array_chronify.rb +57 -0
- data/lib/doing/configuration.rb +4 -1
- data/lib/doing/item.rb +176 -0
- data/lib/doing/log_adapter.rb +1 -1
- data/lib/doing/numeric_chronify.rb +40 -0
- data/lib/doing/plugins/export/dayone_export.rb +1 -1
- data/lib/doing/plugins/export/json_export.rb +2 -2
- data/lib/doing/plugins/export/template_export.rb +47 -90
- data/lib/doing/plugins/import/calendar_import.rb +13 -1
- data/lib/doing/plugins/import/doing_import.rb +12 -1
- data/lib/doing/plugins/import/timing_import.rb +13 -1
- data/lib/doing/prompt.rb +13 -1
- data/lib/doing/string.rb +97 -33
- data/lib/doing/string_chronify.rb +83 -13
- data/lib/doing/time.rb +6 -6
- data/lib/doing/util_backup.rb +1 -1
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +88 -93
- data/lib/doing.rb +31 -27
- data/lib/examples/plugins/say_export.rb +1 -4
- metadata +46 -2
data/bin/doing
CHANGED
@@ -27,6 +27,7 @@ autocomplete_commands true
|
|
27
27
|
|
28
28
|
REGEX_BOOL = /^(?:and|all|any|or|not|none|p(?:at(?:tern)?)?)$/i
|
29
29
|
REGEX_SORT_ORDER = /^(?:a(?:sc)?|d(?:esc)?)$/i
|
30
|
+
REGEX_VALUE_QUERY = /^(?:!)?@?(?:\S+) +(?:!?[<>=][=*]?|[$*^]=) +(?:.*?)$/
|
30
31
|
|
31
32
|
InvalidExportType = Class.new(RuntimeError)
|
32
33
|
MissingConfigFile = Class.new(RuntimeError)
|
@@ -69,6 +70,12 @@ if settings.dig('plugins', 'command_path')
|
|
69
70
|
commands_from File.expand_path(settings.dig('plugins', 'command_path'))
|
70
71
|
end
|
71
72
|
|
73
|
+
class TagArray < Array; end
|
74
|
+
|
75
|
+
accept TagArray do |value|
|
76
|
+
value.gsub(/[, ]+/, ' ').split(' ').map { |tag| tag.sub(/^@/, '')}.map(&:strip)
|
77
|
+
end
|
78
|
+
|
72
79
|
program_desc 'A CLI for a What Was I Doing system'
|
73
80
|
program_long_desc %(Doing uses a TaskPaper-like formatting to keep a plain text
|
74
81
|
record of what you've been doing, complete with tag-based time tracking. The
|
@@ -110,7 +117,7 @@ switch %i[q quiet], default_value: false, negatable: false
|
|
110
117
|
desc 'Verbose output'
|
111
118
|
switch %i[debug], default_value: false, negatable: false
|
112
119
|
|
113
|
-
desc 'Use a specific configuration file. Deprecated, set $DOING_CONFIG instead
|
120
|
+
desc 'Use a specific configuration file. Deprecated, set $DOING_CONFIG instead'
|
114
121
|
flag [:config_file], default_value: config.config_file
|
115
122
|
|
116
123
|
desc 'Specify a different doing_file'
|
@@ -120,7 +127,7 @@ flag %i[f doing_file]
|
|
120
127
|
|
121
128
|
# @@again @@resume
|
122
129
|
desc 'Repeat last entry as new entry'
|
123
|
-
long_desc 'This command is designed to allow multiple time intervals to be created for an entry by duplicating it with a new start (and end, eventually) time
|
130
|
+
long_desc 'This command is designed to allow multiple time intervals to be created for an entry by duplicating it with a new start (and end, eventually) time'
|
124
131
|
command %i[again resume] do |c|
|
125
132
|
c.example 'doing resume', desc: 'Duplicate the most recent entry with a new start time, removing any @done tag'
|
126
133
|
c.example 'doing again', desc: 'again is an alias for resume'
|
@@ -136,15 +143,19 @@ command %i[again resume] do |c|
|
|
136
143
|
c.arg_name 'SECTION_NAME'
|
137
144
|
c.flag [:in]
|
138
145
|
|
139
|
-
c.desc 'Repeat last entry matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)
|
146
|
+
c.desc 'Repeat last entry matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
140
147
|
c.arg_name 'TAG'
|
141
|
-
c.flag [:tag]
|
148
|
+
c.flag [:tag], type: TagArray
|
142
149
|
|
143
150
|
c.desc 'Repeat last entry matching search. Surround with
|
144
151
|
slashes for regex (e.g. "/query/"), start with a single quote for exact match ("\'query").'
|
145
152
|
c.arg_name 'QUERY'
|
146
153
|
c.flag [:search]
|
147
154
|
|
155
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
156
|
+
c.arg_name 'QUERY'
|
157
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
158
|
+
|
148
159
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
149
160
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
150
161
|
|
@@ -158,23 +169,26 @@ command %i[again resume] do |c|
|
|
158
169
|
c.arg_name 'TYPE'
|
159
170
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
160
171
|
|
161
|
-
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans
|
172
|
+
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
162
173
|
c.arg_name 'BOOLEAN'
|
163
174
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
164
175
|
|
165
176
|
c.desc "Edit duplicated entry with #{Doing::Util.default_editor} before adding"
|
166
177
|
c.switch %i[e editor], negatable: false, default_value: false
|
167
178
|
|
168
|
-
c.desc '
|
179
|
+
c.desc 'Add a note'
|
169
180
|
c.arg_name 'TEXT'
|
170
181
|
c.flag %i[n note]
|
171
182
|
|
183
|
+
c.desc 'Prompt for note via multi-line input'
|
184
|
+
c.switch %i[ask], negatable: false, default_value: false
|
185
|
+
|
172
186
|
c.desc 'Select item to resume from a menu of matching entries'
|
173
187
|
c.switch %i[i interactive], negatable: false, default_value: false
|
174
188
|
|
175
189
|
c.action do |_global_options, options, _args|
|
176
190
|
options[:fuzzy] = false
|
177
|
-
tags = options[:tag].nil? ? [] : options[:tag]
|
191
|
+
tags = options[:tag].nil? ? [] : options[:tag]
|
178
192
|
|
179
193
|
options[:case] = options[:case].normalize_case
|
180
194
|
|
@@ -184,6 +198,11 @@ command %i[again resume] do |c|
|
|
184
198
|
options[:search] = search
|
185
199
|
end
|
186
200
|
|
201
|
+
note = Doing::Note.new(options[:note])
|
202
|
+
note.add(Doing::Prompt.request_lines(prompt: 'Add a note')) if options[:ask]
|
203
|
+
|
204
|
+
options[:note] = note
|
205
|
+
|
187
206
|
opts = options.dup
|
188
207
|
|
189
208
|
opts[:tag] = tags
|
@@ -196,7 +215,7 @@ end
|
|
196
215
|
|
197
216
|
# @@cancel
|
198
217
|
desc 'End last X entries with no time tracked'
|
199
|
-
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date
|
218
|
+
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`'
|
200
219
|
arg_name 'COUNT'
|
201
220
|
command :cancel do |c|
|
202
221
|
c.example 'doing cancel', desc: 'Cancel the last entry'
|
@@ -209,11 +228,11 @@ command :cancel do |c|
|
|
209
228
|
c.arg_name 'NAME'
|
210
229
|
c.flag %i[s section]
|
211
230
|
|
212
|
-
c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2). Wildcards allowed (*, ?)
|
231
|
+
c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2). Wildcards allowed (*, ?)'
|
213
232
|
c.arg_name 'TAG'
|
214
|
-
c.flag [:tag]
|
233
|
+
c.flag [:tag], type: TagArray
|
215
234
|
|
216
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
235
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
217
236
|
c.arg_name 'BOOLEAN'
|
218
237
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
219
238
|
|
@@ -221,6 +240,10 @@ command :cancel do |c|
|
|
221
240
|
c.arg_name 'QUERY'
|
222
241
|
c.flag [:search]
|
223
242
|
|
243
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
244
|
+
c.arg_name 'QUERY'
|
245
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
246
|
+
|
224
247
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
225
248
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
226
249
|
|
@@ -251,7 +274,7 @@ command :cancel do |c|
|
|
251
274
|
if options[:tag].nil?
|
252
275
|
tags = []
|
253
276
|
else
|
254
|
-
tags = options[:tag]
|
277
|
+
tags = options[:tag]
|
255
278
|
end
|
256
279
|
|
257
280
|
raise InvalidArgument, 'Only one argument allowed' if args.length > 1
|
@@ -285,7 +308,8 @@ command :cancel do |c|
|
|
285
308
|
tag: tags,
|
286
309
|
tag_bool: options[:bool].normalize_bool,
|
287
310
|
tags: ['done'],
|
288
|
-
unfinished: options[:unfinished]
|
311
|
+
unfinished: options[:unfinished],
|
312
|
+
val: options[:val]
|
289
313
|
}
|
290
314
|
|
291
315
|
wwid.tag_last(opts)
|
@@ -293,7 +317,7 @@ command :cancel do |c|
|
|
293
317
|
end
|
294
318
|
|
295
319
|
# @@done @@did
|
296
|
-
desc 'Add a completed item with @done(date). No argument finishes last entry
|
320
|
+
desc 'Add a completed item with @done(date). No argument finishes last entry'
|
297
321
|
long_desc 'Use this command to add an entry after you\'ve already finished it. It will be immediately marked as @done.
|
298
322
|
You can modify the start and end times of the entry using the --back, --took, and --at flags, making it an easy
|
299
323
|
way to add entries in post and maintain accurate (albeit manual) time tracking.'
|
@@ -326,7 +350,7 @@ command %i[done did] do |c|
|
|
326
350
|
If used without the --back option, the start date will be moved back to allow
|
327
351
|
the completion date to be the current time.)
|
328
352
|
c.arg_name 'INTERVAL'
|
329
|
-
c.flag %i[t took]
|
353
|
+
c.flag %i[t took for]
|
330
354
|
|
331
355
|
c.desc 'Section'
|
332
356
|
c.arg_name 'NAME'
|
@@ -339,6 +363,9 @@ command %i[done did] do |c|
|
|
339
363
|
c.arg_name 'TEXT'
|
340
364
|
c.flag %i[n note]
|
341
365
|
|
366
|
+
c.desc 'Prompt for note via multi-line input'
|
367
|
+
c.switch %i[ask], negatable: false, default_value: false
|
368
|
+
|
342
369
|
c.desc 'Finish last entry not already marked @done'
|
343
370
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
344
371
|
|
@@ -374,6 +401,8 @@ command %i[done did] do |c|
|
|
374
401
|
end
|
375
402
|
|
376
403
|
if options[:date]
|
404
|
+
finish_date = wwid.verify_duration(date, finish_date) unless options[:took]
|
405
|
+
|
377
406
|
donedate = finish_date.strftime('%F %R')
|
378
407
|
end
|
379
408
|
|
@@ -385,6 +414,7 @@ command %i[done did] do |c|
|
|
385
414
|
|
386
415
|
note = Doing::Note.new
|
387
416
|
note.add(options[:note]) if options[:note]
|
417
|
+
note.add(Doing::Prompt.request_lines(prompt: 'Add a note')) if options[:ask]
|
388
418
|
|
389
419
|
if options[:editor]
|
390
420
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
@@ -439,7 +469,6 @@ command %i[done did] do |c|
|
|
439
469
|
if options[:remove]
|
440
470
|
wwid.tag_last({ tags: ['done'], count: 1, section: section, remove: true })
|
441
471
|
else
|
442
|
-
note = options[:note] ? Doing::Note.new(options[:note]) : nil
|
443
472
|
opt = {
|
444
473
|
archive: options[:archive],
|
445
474
|
back: finish_date,
|
@@ -520,7 +549,7 @@ command :finish do |c|
|
|
520
549
|
|
521
550
|
c.desc 'Set the completed date to the start date plus XX[hmd]'
|
522
551
|
c.arg_name 'INTERVAL'
|
523
|
-
c.flag %i[t took]
|
552
|
+
c.flag %i[t took for]
|
524
553
|
|
525
554
|
c.desc %(Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm). If used, ignores --back.)
|
526
555
|
c.arg_name 'DATE_STRING'
|
@@ -529,12 +558,16 @@ command :finish do |c|
|
|
529
558
|
c.desc 'Finish the last X entries containing TAG.
|
530
559
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
531
560
|
c.arg_name 'TAG'
|
532
|
-
c.flag [:tag]
|
561
|
+
c.flag [:tag], type: TagArray
|
533
562
|
|
534
563
|
c.desc 'Finish the last X entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
535
564
|
c.arg_name 'QUERY'
|
536
565
|
c.flag [:search]
|
537
566
|
|
567
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
568
|
+
c.arg_name 'QUERY'
|
569
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
570
|
+
|
538
571
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
539
572
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
540
573
|
|
@@ -548,7 +581,7 @@ command :finish do |c|
|
|
548
581
|
c.arg_name 'TYPE'
|
549
582
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
550
583
|
|
551
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
584
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
552
585
|
c.arg_name 'BOOLEAN'
|
553
586
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
554
587
|
|
@@ -604,7 +637,7 @@ command :finish do |c|
|
|
604
637
|
if options[:tag].nil?
|
605
638
|
tags = []
|
606
639
|
else
|
607
|
-
tags = options[:tag]
|
640
|
+
tags = options[:tag]
|
608
641
|
end
|
609
642
|
|
610
643
|
raise InvalidArgument, 'Only one argument allowed' if args.length > 1
|
@@ -641,7 +674,8 @@ command :finish do |c|
|
|
641
674
|
tag_bool: options[:bool].normalize_bool,
|
642
675
|
tags: ['done'],
|
643
676
|
took: options[:took],
|
644
|
-
unfinished: options[:unfinished]
|
677
|
+
unfinished: options[:unfinished],
|
678
|
+
val: options[:val]
|
645
679
|
}
|
646
680
|
|
647
681
|
wwid.tag_last(opts)
|
@@ -666,6 +700,9 @@ command :later do |c|
|
|
666
700
|
c.arg_name 'TEXT'
|
667
701
|
c.flag %i[n note]
|
668
702
|
|
703
|
+
c.desc 'Prompt for note via multi-line input'
|
704
|
+
c.switch %i[ask], negatable: false, default_value: false
|
705
|
+
|
669
706
|
c.action do |_global_options, options, args|
|
670
707
|
if options[:back]
|
671
708
|
date = options[:back].chronify(guess: :begin)
|
@@ -674,11 +711,16 @@ command :later do |c|
|
|
674
711
|
date = Time.now
|
675
712
|
end
|
676
713
|
|
714
|
+
ask_note = options[:ask] ? Doing::Prompt.request_lines(prompt: 'Add a note') : ''
|
715
|
+
|
677
716
|
if options[:editor] || (args.empty? && $stdin.stat.size.zero?)
|
678
717
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
679
718
|
|
680
719
|
input += date.strftime('%F %R | ')
|
681
720
|
input += args.empty? ? '' : args.join(' ')
|
721
|
+
input += "\n#{options[:note]}" if options[:note]
|
722
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
723
|
+
|
682
724
|
input = wwid.fork_editor(input).strip
|
683
725
|
raise EmptyInput, 'No content' unless input && !input.empty?
|
684
726
|
|
@@ -691,6 +733,7 @@ command :later do |c|
|
|
691
733
|
d, title, note = wwid.format_input(args.join(' '))
|
692
734
|
date = d.nil? ? date : d
|
693
735
|
note.add(options[:note]) if options[:note]
|
736
|
+
note.add(ask_note) unless ask_note.empty?
|
694
737
|
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
695
738
|
wwid.write(wwid.doing_file)
|
696
739
|
elsif $stdin.stat.size.positive?
|
@@ -700,6 +743,7 @@ command :later do |c|
|
|
700
743
|
date = d
|
701
744
|
end
|
702
745
|
note.add(options[:note]) if options[:note]
|
746
|
+
note.add(ask_note) unless ask_note.empty?
|
703
747
|
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
704
748
|
wwid.write(wwid.doing_file)
|
705
749
|
else
|
@@ -739,12 +783,16 @@ command %i[mark flag] do |c|
|
|
739
783
|
c.desc 'Flag the last entry containing TAG.
|
740
784
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
741
785
|
c.arg_name 'TAG'
|
742
|
-
c.flag [:tag]
|
786
|
+
c.flag [:tag], type: TagArray
|
743
787
|
|
744
788
|
c.desc 'Flag the last entry matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
745
789
|
c.arg_name 'QUERY'
|
746
790
|
c.flag [:search]
|
747
791
|
|
792
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
793
|
+
c.arg_name 'QUERY'
|
794
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
795
|
+
|
748
796
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
749
797
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
750
798
|
|
@@ -758,7 +806,7 @@ command %i[mark flag] do |c|
|
|
758
806
|
c.arg_name 'TYPE'
|
759
807
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
760
808
|
|
761
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
809
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
762
810
|
c.arg_name 'BOOLEAN'
|
763
811
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
764
812
|
|
@@ -780,7 +828,7 @@ command %i[mark flag] do |c|
|
|
780
828
|
if options[:tag].nil?
|
781
829
|
search_tags = []
|
782
830
|
else
|
783
|
-
search_tags = options[:tag]
|
831
|
+
search_tags = options[:tag]
|
784
832
|
end
|
785
833
|
|
786
834
|
if options[:interactive]
|
@@ -862,6 +910,9 @@ command :meanwhile do |c|
|
|
862
910
|
c.arg_name 'TEXT'
|
863
911
|
c.flag %i[n note]
|
864
912
|
|
913
|
+
c.desc 'Prompt for note via multi-line input'
|
914
|
+
c.switch %i[ask], negatable: false, default_value: false
|
915
|
+
|
865
916
|
c.action do |_global_options, options, args|
|
866
917
|
if options[:back]
|
867
918
|
date = options[:back].chronify(guess: :begin)
|
@@ -878,10 +929,15 @@ command :meanwhile do |c|
|
|
878
929
|
end
|
879
930
|
input = ''
|
880
931
|
|
932
|
+
ask_note = options[:ask] ? Doing::Prompt.request_lines(prompt: 'Add a note') : []
|
933
|
+
|
881
934
|
if options[:editor]
|
882
935
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
883
936
|
input += date.strftime('%F %R | ')
|
884
937
|
input += args.join(' ') unless args.empty?
|
938
|
+
input += "\n#{options[:note]}" if options[:note]
|
939
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
940
|
+
|
885
941
|
input = wwid.fork_editor(input).strip
|
886
942
|
elsif !args.empty?
|
887
943
|
input = args.join(' ')
|
@@ -900,10 +956,9 @@ command :meanwhile do |c|
|
|
900
956
|
note = []
|
901
957
|
end
|
902
958
|
|
903
|
-
|
904
|
-
note.
|
905
|
-
|
906
|
-
note = nil
|
959
|
+
unless options[:editor]
|
960
|
+
note.add(options[:note]) if options[:note]
|
961
|
+
note.add(ask_note) unless ask_note.empty?
|
907
962
|
end
|
908
963
|
|
909
964
|
wwid.stop_start('meanwhile', { new_item: input, back: date, section: section, archive: options[:archive], note: note })
|
@@ -937,14 +992,18 @@ command :note do |c|
|
|
937
992
|
c.desc "Replace/Remove last entry's note (default append)"
|
938
993
|
c.switch %i[r remove], negatable: false, default_value: false
|
939
994
|
|
940
|
-
c.desc 'Add/remove note from last entry matching tag. Wildcards allowed (*, ?)
|
995
|
+
c.desc 'Add/remove note from last entry matching tag. Wildcards allowed (*, ?)'
|
941
996
|
c.arg_name 'TAG'
|
942
|
-
c.flag [:tag]
|
997
|
+
c.flag [:tag], type: TagArray
|
943
998
|
|
944
999
|
c.desc 'Add/remove note from last entry matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
945
1000
|
c.arg_name 'QUERY'
|
946
1001
|
c.flag [:search]
|
947
1002
|
|
1003
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1004
|
+
c.arg_name 'QUERY'
|
1005
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1006
|
+
|
948
1007
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
949
1008
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
950
1009
|
|
@@ -958,13 +1017,16 @@ command :note do |c|
|
|
958
1017
|
c.arg_name 'TYPE'
|
959
1018
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
960
1019
|
|
961
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
1020
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
962
1021
|
c.arg_name 'BOOLEAN'
|
963
1022
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
964
1023
|
|
965
1024
|
c.desc 'Select item for new note from a menu of matching entries'
|
966
1025
|
c.switch %i[i interactive], negatable: false, default_value: false
|
967
1026
|
|
1027
|
+
c.desc 'Prompt for note via multi-line input'
|
1028
|
+
c.switch %i[ask], negatable: false, default_value: false
|
1029
|
+
|
968
1030
|
c.action do |_global_options, options, args|
|
969
1031
|
options[:fuzzy] = false
|
970
1032
|
if options[:section]
|
@@ -991,8 +1053,9 @@ command :note do |c|
|
|
991
1053
|
|
992
1054
|
last_note = last_entry.note || Doing::Note.new
|
993
1055
|
new_note = Doing::Note.new
|
1056
|
+
ask_note = options[:ask] ? Doing::Prompt.request_lines(prompt: 'Add a note') : ''
|
994
1057
|
|
995
|
-
if options[:editor] || (args.empty? && $stdin.stat.size.zero? && !options[:remove])
|
1058
|
+
if options[:editor] || (args.empty? && $stdin.stat.size.zero? && !options[:remove] && !options[:ask])
|
996
1059
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
997
1060
|
|
998
1061
|
input = !args.empty? ? args.join(' ') : ''
|
@@ -1003,7 +1066,9 @@ command :note do |c|
|
|
1003
1066
|
prev_input = last_entry.note || Doing::Note.new
|
1004
1067
|
end
|
1005
1068
|
|
1069
|
+
|
1006
1070
|
input = prev_input.add(input)
|
1071
|
+
input.add(ask_note) unless ask_note.empty?
|
1007
1072
|
|
1008
1073
|
input = wwid.fork_editor(prev_input.strip_lines.join("\n"), message: nil).strip
|
1009
1074
|
note = input
|
@@ -1014,9 +1079,12 @@ command :note do |c|
|
|
1014
1079
|
elsif $stdin.stat.size.positive?
|
1015
1080
|
new_note.add($stdin.read.strip)
|
1016
1081
|
else
|
1017
|
-
raise EmptyInput, 'You must provide content when adding a note' unless options[:remove]
|
1082
|
+
raise EmptyInput, 'You must provide content when adding a note' unless options[:remove] || !ask_note.empty?
|
1083
|
+
|
1018
1084
|
end
|
1019
1085
|
|
1086
|
+
new_note.add(ask_note) unless ask_note.empty?
|
1087
|
+
|
1020
1088
|
if last_note.equal?(new_note)
|
1021
1089
|
Doing.logger.debug('Skipped:', 'No note change')
|
1022
1090
|
else
|
@@ -1062,6 +1130,9 @@ command %i[now next] do |c|
|
|
1062
1130
|
c.arg_name 'TEXT'
|
1063
1131
|
c.flag %i[n note]
|
1064
1132
|
|
1133
|
+
c.desc 'Prompt for note via multi-line input'
|
1134
|
+
c.switch %i[ask], negatable: false, default_value: false
|
1135
|
+
|
1065
1136
|
# c.desc "Edit entry with specified app"
|
1066
1137
|
# c.arg_name 'editor_app'
|
1067
1138
|
# # c.flag [:a, :app]
|
@@ -1081,23 +1152,28 @@ command %i[now next] do |c|
|
|
1081
1152
|
options[:section] = settings['current_section']
|
1082
1153
|
end
|
1083
1154
|
|
1155
|
+
ask_note = options[:ask] ? Doing::Prompt.request_lines(prompt: 'Add a note') : ''
|
1156
|
+
|
1084
1157
|
if options[:editor] || (args.empty? && $stdin.stat.size.zero?)
|
1085
1158
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
1086
1159
|
|
1087
1160
|
input = date.strftime('%F %R | ')
|
1088
1161
|
input += args.join(' ') unless args.empty?
|
1162
|
+
input += "\n#{options[:note]}" if options[:note]
|
1163
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
1089
1164
|
input = wwid.fork_editor(input).strip
|
1090
1165
|
|
1091
1166
|
raise EmptyInput, 'No content' if input.empty?
|
1092
1167
|
|
1093
1168
|
date, title, note = wwid.format_input(input)
|
1094
|
-
|
1169
|
+
|
1095
1170
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1096
1171
|
wwid.write(wwid.doing_file)
|
1097
1172
|
elsif args.length.positive?
|
1098
1173
|
d, title, note = wwid.format_input(args.join(' '))
|
1099
1174
|
date = d.nil? ? date : d
|
1100
1175
|
note.add(options[:note]) if options[:note]
|
1176
|
+
note.add(ask_note) unless ask_note.empty?
|
1101
1177
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1102
1178
|
wwid.write(wwid.doing_file)
|
1103
1179
|
elsif $stdin.stat.size.positive?
|
@@ -1108,6 +1184,7 @@ command %i[now next] do |c|
|
|
1108
1184
|
date = d
|
1109
1185
|
end
|
1110
1186
|
note.add(options[:note]) if options[:note]
|
1187
|
+
note.add(ask_note) unless ask_note.empty?
|
1111
1188
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1112
1189
|
wwid.write(wwid.doing_file)
|
1113
1190
|
else
|
@@ -1135,7 +1212,7 @@ command %i[reset begin] do |c|
|
|
1135
1212
|
c.desc 'Resume entry (remove @done)'
|
1136
1213
|
c.switch %i[r resume], default_value: true
|
1137
1214
|
|
1138
|
-
c.desc 'Reset last entry matching tag. Wildcards allowed (*, ?)
|
1215
|
+
c.desc 'Reset last entry matching tag. Wildcards allowed (*, ?)'
|
1139
1216
|
c.arg_name 'TAG'
|
1140
1217
|
c.flag [:tag]
|
1141
1218
|
|
@@ -1143,6 +1220,10 @@ command %i[reset begin] do |c|
|
|
1143
1220
|
c.arg_name 'QUERY'
|
1144
1221
|
c.flag [:search]
|
1145
1222
|
|
1223
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1224
|
+
c.arg_name 'QUERY'
|
1225
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1226
|
+
|
1146
1227
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
1147
1228
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
1148
1229
|
|
@@ -1156,7 +1237,7 @@ command %i[reset begin] do |c|
|
|
1156
1237
|
c.arg_name 'TYPE'
|
1157
1238
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1158
1239
|
|
1159
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
1240
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
1160
1241
|
c.arg_name 'BOOLEAN'
|
1161
1242
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1162
1243
|
|
@@ -1256,13 +1337,21 @@ command :select do |c|
|
|
1256
1337
|
|
1257
1338
|
c.desc 'Initial search query for filtering. Matching is fuzzy. For exact matching, start query with a single quote, e.g. `--query "\'search"'
|
1258
1339
|
c.arg_name 'QUERY'
|
1259
|
-
c.flag %i[q query
|
1340
|
+
c.flag %i[q query]
|
1341
|
+
|
1342
|
+
c.desc 'Select from entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
1343
|
+
c.arg_name 'QUERY'
|
1344
|
+
c.flag [:search]
|
1345
|
+
|
1346
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1347
|
+
c.arg_name 'QUERY'
|
1348
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1260
1349
|
|
1261
|
-
c.desc 'Select from 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
|
1350
|
+
c.desc 'Select from 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'
|
1262
1351
|
c.arg_name 'DATE_STRING'
|
1263
1352
|
c.flag [:before]
|
1264
1353
|
|
1265
|
-
c.desc 'Select from 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
|
1354
|
+
c.desc 'Select from 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'
|
1266
1355
|
c.arg_name 'DATE_STRING'
|
1267
1356
|
c.flag [:after]
|
1268
1357
|
|
@@ -1287,7 +1376,7 @@ command :select do |c|
|
|
1287
1376
|
c.arg_name 'TYPE'
|
1288
1377
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1289
1378
|
|
1290
|
-
c.desc 'Use --no-menu to skip the interactive menu. Use with --query to filter items and act on results automatically. Test with `--output doing` to preview matches
|
1379
|
+
c.desc 'Use --no-menu to skip the interactive menu. Use with --query to filter items and act on results automatically. Test with `--output doing` to preview matches'
|
1291
1380
|
c.switch %i[menu], negatable: true, default_value: true
|
1292
1381
|
|
1293
1382
|
c.desc 'Cancel selected items (add @done without timestamp)'
|
@@ -1305,7 +1394,7 @@ command :select do |c|
|
|
1305
1394
|
c.desc 'Add flag to selected item(s)'
|
1306
1395
|
c.switch %i[flag], negatable: false, default_value: false
|
1307
1396
|
|
1308
|
-
c.desc 'Perform action without confirmation
|
1397
|
+
c.desc 'Perform action without confirmation'
|
1309
1398
|
c.switch %i[force], negatable: false, default_value: false
|
1310
1399
|
|
1311
1400
|
c.desc 'Save selected entries to file using --output format'
|
@@ -1365,6 +1454,10 @@ command :tag do |c|
|
|
1365
1454
|
c.arg_name 'ORIG_TAG'
|
1366
1455
|
c.flag %i[rename]
|
1367
1456
|
|
1457
|
+
c.desc 'Include a value, e.g. @tag(value)'
|
1458
|
+
c.arg_name 'VALUE'
|
1459
|
+
c.flag %i[v value]
|
1460
|
+
|
1368
1461
|
c.desc 'Don\'t ask permission to tag all entries when count is 0'
|
1369
1462
|
c.switch %i[force], negatable: false, default_value: false
|
1370
1463
|
|
@@ -1386,12 +1479,16 @@ command :tag do |c|
|
|
1386
1479
|
c.desc 'Tag the last X entries containing TAG.
|
1387
1480
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
1388
1481
|
c.arg_name 'TAG'
|
1389
|
-
c.flag [:tag]
|
1482
|
+
c.flag [:tag], type: TagArray
|
1390
1483
|
|
1391
1484
|
c.desc 'Tag entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
1392
1485
|
c.arg_name 'QUERY'
|
1393
1486
|
c.flag [:search]
|
1394
1487
|
|
1488
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1489
|
+
c.arg_name 'QUERY'
|
1490
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1491
|
+
|
1395
1492
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
1396
1493
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
1397
1494
|
|
@@ -1405,7 +1502,7 @@ command :tag do |c|
|
|
1405
1502
|
c.arg_name 'TYPE'
|
1406
1503
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1407
1504
|
|
1408
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
1505
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
1409
1506
|
c.arg_name 'BOOLEAN'
|
1410
1507
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1411
1508
|
|
@@ -1428,7 +1525,7 @@ command :tag do |c|
|
|
1428
1525
|
if options[:tag].nil?
|
1429
1526
|
search_tags = []
|
1430
1527
|
else
|
1431
|
-
search_tags = options[:tag]
|
1528
|
+
search_tags = options[:tag]
|
1432
1529
|
end
|
1433
1530
|
|
1434
1531
|
if options[:autotag]
|
@@ -1528,11 +1625,11 @@ command %i[grep search] do |c|
|
|
1528
1625
|
c.arg_name 'NAME'
|
1529
1626
|
c.flag %i[s section], default_value: 'All'
|
1530
1627
|
|
1531
|
-
c.desc 'Search 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
|
1628
|
+
c.desc 'Search 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'
|
1532
1629
|
c.arg_name 'DATE_STRING'
|
1533
1630
|
c.flag [:before]
|
1534
1631
|
|
1535
|
-
c.desc 'Search 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
|
1632
|
+
c.desc 'Search 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'
|
1536
1633
|
c.arg_name 'DATE_STRING'
|
1537
1634
|
c.flag [:after]
|
1538
1635
|
|
@@ -1591,6 +1688,13 @@ command %i[grep search] do |c|
|
|
1591
1688
|
c.desc 'Display an interactive menu of results to perform further operations'
|
1592
1689
|
c.switch %i[i interactive], default_value: false, negatable: false
|
1593
1690
|
|
1691
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1692
|
+
c.arg_name 'QUERY'
|
1693
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1694
|
+
|
1695
|
+
c.desc 'Combine multiple tags or value queries using AND, OR, or NOT'
|
1696
|
+
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
1697
|
+
|
1594
1698
|
c.action do |_global_options, options, args|
|
1595
1699
|
options[:fuzzy] = false
|
1596
1700
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
@@ -1601,6 +1705,7 @@ command %i[grep search] do |c|
|
|
1601
1705
|
section = wwid.guess_section(options[:section]) if options[:section]
|
1602
1706
|
|
1603
1707
|
options[:case] = options[:case].normalize_case
|
1708
|
+
options[:bool] = options[:bool].normalize_bool
|
1604
1709
|
|
1605
1710
|
search = args.join(' ')
|
1606
1711
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1639,11 +1744,11 @@ command :last do |c|
|
|
1639
1744
|
c.desc "Delete the last entry"
|
1640
1745
|
c.switch %i[d delete], negatable: false, default_value: false
|
1641
1746
|
|
1642
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)
|
1747
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
1643
1748
|
c.arg_name 'TAG'
|
1644
|
-
c.flag [:tag]
|
1749
|
+
c.flag [:tag], type: TagArray
|
1645
1750
|
|
1646
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
1751
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
1647
1752
|
c.arg_name 'BOOLEAN'
|
1648
1753
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1649
1754
|
|
@@ -1651,6 +1756,10 @@ command :last do |c|
|
|
1651
1756
|
c.arg_name 'QUERY'
|
1652
1757
|
c.flag [:search]
|
1653
1758
|
|
1759
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1760
|
+
c.arg_name 'QUERY'
|
1761
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1762
|
+
|
1654
1763
|
c.desc 'Show elapsed time if entry is not tagged @done'
|
1655
1764
|
c.switch [:duration]
|
1656
1765
|
|
@@ -1674,7 +1783,7 @@ command :last do |c|
|
|
1674
1783
|
if options[:tag].nil?
|
1675
1784
|
options[:tag] = []
|
1676
1785
|
else
|
1677
|
-
options[:tag] = options[:tag]
|
1786
|
+
options[:tag] = options[:tag]
|
1678
1787
|
options[:bool] = options[:bool].normalize_bool
|
1679
1788
|
end
|
1680
1789
|
|
@@ -1685,12 +1794,14 @@ command :last do |c|
|
|
1685
1794
|
if options[:editor]
|
1686
1795
|
wwid.edit_last(section: options[:section],
|
1687
1796
|
options: {
|
1688
|
-
search: search,
|
1797
|
+
search: options[:search],
|
1689
1798
|
fuzzy: options[:fuzzy],
|
1690
1799
|
case: options[:case],
|
1691
|
-
tag:
|
1800
|
+
tag: options[:tag],
|
1692
1801
|
tag_bool: options[:bool],
|
1693
|
-
not: options[:not]
|
1802
|
+
not: options[:not],
|
1803
|
+
val: options[:val],
|
1804
|
+
bool: options[:bool]
|
1694
1805
|
})
|
1695
1806
|
else
|
1696
1807
|
last = wwid.last(times: true, section: options[:section],
|
@@ -1702,7 +1813,9 @@ command :last do |c|
|
|
1702
1813
|
negate: options[:not],
|
1703
1814
|
tag: options[:tag],
|
1704
1815
|
tag_bool: options[:bool],
|
1705
|
-
delete: options[:delete]
|
1816
|
+
delete: options[:delete],
|
1817
|
+
bool: options[:bool],
|
1818
|
+
val: options[:val]
|
1706
1819
|
})
|
1707
1820
|
Doing::Pager::page last.strip if last
|
1708
1821
|
end
|
@@ -1798,11 +1911,15 @@ command :show do |c|
|
|
1798
1911
|
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.'
|
1799
1912
|
c.example 'doing show --interactive Later @doing', desc: 'Create a menu from entries from the Later section tagged @doing to perform batch actions'
|
1800
1913
|
|
1801
|
-
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
|
1914
|
+
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'
|
1802
1915
|
c.arg_name 'TAG'
|
1803
|
-
c.flag [:tag]
|
1916
|
+
c.flag [:tag], type: TagArray
|
1917
|
+
|
1918
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1919
|
+
c.arg_name 'QUERY'
|
1920
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1804
1921
|
|
1805
|
-
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans
|
1922
|
+
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
1806
1923
|
c.arg_name 'BOOLEAN'
|
1807
1924
|
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1808
1925
|
|
@@ -1814,11 +1931,11 @@ command :show do |c|
|
|
1814
1931
|
c.arg_name 'AGE'
|
1815
1932
|
c.flag %i[a age], default_value: 'newest'
|
1816
1933
|
|
1817
|
-
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
|
1934
|
+
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'
|
1818
1935
|
c.arg_name 'DATE_STRING'
|
1819
1936
|
c.flag [:before]
|
1820
1937
|
|
1821
|
-
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
|
1938
|
+
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'
|
1822
1939
|
c.arg_name 'DATE_STRING'
|
1823
1940
|
c.flag [:after]
|
1824
1941
|
|
@@ -1929,7 +2046,7 @@ command :show do |c|
|
|
1929
2046
|
section ||= 'All'
|
1930
2047
|
end
|
1931
2048
|
|
1932
|
-
tags.concat(options[:tag]
|
2049
|
+
tags.concat(options[:tag]) if options[:tag]
|
1933
2050
|
|
1934
2051
|
options[:times] = true if options[:totals]
|
1935
2052
|
|
@@ -2012,7 +2129,7 @@ command :tags do |c|
|
|
2012
2129
|
c.arg_name 'ORDER'
|
2013
2130
|
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value: 'asc'
|
2014
2131
|
|
2015
|
-
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)
|
2132
|
+
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
2016
2133
|
c.arg_name 'TAG'
|
2017
2134
|
c.flag [:tag]
|
2018
2135
|
|
@@ -2021,6 +2138,10 @@ command :tags do |c|
|
|
2021
2138
|
c.arg_name 'QUERY'
|
2022
2139
|
c.flag [:search]
|
2023
2140
|
|
2141
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
2142
|
+
c.arg_name 'QUERY'
|
2143
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
2144
|
+
|
2024
2145
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
2025
2146
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
2026
2147
|
|
@@ -2034,7 +2155,7 @@ command :tags do |c|
|
|
2034
2155
|
c.arg_name 'TYPE'
|
2035
2156
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
2036
2157
|
|
2037
|
-
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans
|
2158
|
+
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
2038
2159
|
c.arg_name 'BOOLEAN'
|
2039
2160
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2040
2161
|
|
@@ -2291,11 +2412,15 @@ command :view do |c|
|
|
2291
2412
|
c.desc 'Include colors in output'
|
2292
2413
|
c.switch [:color], default_value: true, negatable: true
|
2293
2414
|
|
2294
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)
|
2415
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
2295
2416
|
c.arg_name 'TAG'
|
2296
2417
|
c.flag [:tag]
|
2297
2418
|
|
2298
|
-
c.desc '
|
2419
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
2420
|
+
c.arg_name 'QUERY'
|
2421
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
2422
|
+
|
2423
|
+
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
2299
2424
|
c.arg_name 'BOOLEAN'
|
2300
2425
|
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2301
2426
|
|
@@ -2324,11 +2449,11 @@ command :view do |c|
|
|
2324
2449
|
c.arg_name 'DIRECTION'
|
2325
2450
|
c.flag [:tag_order], must_match: REGEX_SORT_ORDER
|
2326
2451
|
|
2327
|
-
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
|
2452
|
+
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'
|
2328
2453
|
c.arg_name 'DATE_STRING'
|
2329
2454
|
c.flag [:before]
|
2330
2455
|
|
2331
|
-
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
|
2456
|
+
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'
|
2332
2457
|
c.arg_name 'DATE_STRING'
|
2333
2458
|
c.flag [:after]
|
2334
2459
|
|
@@ -2935,11 +3060,11 @@ command %i[archive move] do |c|
|
|
2935
3060
|
c.desc 'Label moved items with @from(SECTION_NAME)'
|
2936
3061
|
c.switch [:label], default_value: true, negatable: true
|
2937
3062
|
|
2938
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands
|
3063
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands'
|
2939
3064
|
c.arg_name 'TAG'
|
2940
|
-
c.flag [:tag]
|
3065
|
+
c.flag [:tag], type: TagArray
|
2941
3066
|
|
2942
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
3067
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
2943
3068
|
c.arg_name 'BOOLEAN'
|
2944
3069
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2945
3070
|
|
@@ -2947,6 +3072,10 @@ command %i[archive move] do |c|
|
|
2947
3072
|
c.arg_name 'QUERY'
|
2948
3073
|
c.flag [:search]
|
2949
3074
|
|
3075
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
3076
|
+
c.arg_name 'QUERY'
|
3077
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
3078
|
+
|
2950
3079
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
2951
3080
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
2952
3081
|
|
@@ -2982,7 +3111,7 @@ command %i[archive move] do |c|
|
|
2982
3111
|
|
2983
3112
|
raise InvalidArgument, '--keep and --count can not be used together' if options[:keep] && options[:count]
|
2984
3113
|
|
2985
|
-
tags.concat(options[:tag]
|
3114
|
+
tags.concat(options[:tag]) if options[:tag]
|
2986
3115
|
|
2987
3116
|
search = nil
|
2988
3117
|
|
@@ -3042,7 +3171,7 @@ command :import do |c|
|
|
3042
3171
|
|
3043
3172
|
c.desc 'Tag all imported entries'
|
3044
3173
|
c.arg_name 'TAGS'
|
3045
|
-
c.flag
|
3174
|
+
c.flag %i[t tag]
|
3046
3175
|
|
3047
3176
|
c.desc 'Autotag entries'
|
3048
3177
|
c.switch :autotag, negatable: true, default_value: true
|
@@ -3077,6 +3206,12 @@ command :import do |c|
|
|
3077
3206
|
options[:section] = wwid.guess_section(options[:section]) || options[:section].cap_first
|
3078
3207
|
end
|
3079
3208
|
|
3209
|
+
if options[:search]
|
3210
|
+
search = options[:search]
|
3211
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
3212
|
+
options[:search] = search
|
3213
|
+
end
|
3214
|
+
|
3080
3215
|
if options[:from]
|
3081
3216
|
date_string = options[:from]
|
3082
3217
|
if date_string =~ / (to|through|thru|(un)?til|-+) /
|
@@ -3085,7 +3220,7 @@ command :import do |c|
|
|
3085
3220
|
finish = dates[2].chronify(guess: :end)
|
3086
3221
|
else
|
3087
3222
|
start = date_string.chronify(guess: :begin)
|
3088
|
-
finish =
|
3223
|
+
finish = date_string.chronify(guess: :end)
|
3089
3224
|
end
|
3090
3225
|
raise InvalidTimeExpression, 'Unrecognized date string' unless start
|
3091
3226
|
dates = [start, finish]
|
@@ -3122,11 +3257,11 @@ command :rotate do |c|
|
|
3122
3257
|
c.arg_name 'SECTION_NAME'
|
3123
3258
|
c.flag %i[s section], default_value: 'All'
|
3124
3259
|
|
3125
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands
|
3260
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands'
|
3126
3261
|
c.arg_name 'TAG'
|
3127
3262
|
c.flag [:tag]
|
3128
3263
|
|
3129
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
3264
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
3130
3265
|
c.arg_name 'BOOLEAN'
|
3131
3266
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
3132
3267
|
|
@@ -3134,6 +3269,10 @@ command :rotate do |c|
|
|
3134
3269
|
c.arg_name 'QUERY'
|
3135
3270
|
c.flag [:search]
|
3136
3271
|
|
3272
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
3273
|
+
c.arg_name 'QUERY'
|
3274
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
3275
|
+
|
3137
3276
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
3138
3277
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
3139
3278
|
|
@@ -3357,7 +3496,7 @@ command :undo do |c|
|
|
3357
3496
|
c.arg_name 'COUNT'
|
3358
3497
|
c.flag %i[p prune], type: Integer
|
3359
3498
|
|
3360
|
-
c.desc 'Redo last undo. Note: you cannot undo a redo
|
3499
|
+
c.desc 'Redo last undo. Note: you cannot undo a redo'
|
3361
3500
|
c.switch %i[r redo]
|
3362
3501
|
|
3363
3502
|
c.action do |_global_options, options, args|
|
@@ -3384,7 +3523,7 @@ command :undo do |c|
|
|
3384
3523
|
end
|
3385
3524
|
|
3386
3525
|
# @@redo
|
3387
|
-
long_desc 'Shortcut for `doing undo -r`, reverses the last undo command. You cannot undo a redo
|
3526
|
+
long_desc 'Shortcut for `doing undo -r`, reverses the last undo command. You cannot undo a redo'
|
3388
3527
|
arg_name 'COUNT'
|
3389
3528
|
command :redo do |c|
|
3390
3529
|
c.desc 'Specify alternate doing file'
|