doing 2.1.12 → 2.1.16
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 +16 -14
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +67 -0
- data/Gemfile.lock +9 -2
- data/README.md +56 -19
- data/bin/doing +317 -113
- 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 +103 -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 +214 -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 +881 -138
- 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 +408 -256
- data/docs/doc/top-level-namespace.html +2 -2
- data/docs/index.md +56 -19
- data/doing.gemspec +2 -0
- data/doing.rdoc +257 -48
- 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 +37 -7
- 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 +54 -1
- data/lib/doing/string.rb +97 -33
- data/lib/doing/string_chronify.rb +112 -14
- data/lib/doing/template_string.rb +1 -1
- 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 +128 -103
- data/lib/doing.rb +36 -31
- 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.read_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.'
|
@@ -314,19 +338,26 @@ command %i[done did] do |c|
|
|
314
338
|
c.switch %i[a archive], negatable: false, default_value: false
|
315
339
|
|
316
340
|
c.desc %(Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm).
|
317
|
-
|
341
|
+
Used with --took, backdates start date)
|
318
342
|
c.arg_name 'DATE_STRING'
|
319
|
-
c.flag [
|
343
|
+
c.flag %i[at finished]
|
320
344
|
|
321
345
|
c.desc 'Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]'
|
322
346
|
c.arg_name 'DATE_STRING'
|
323
347
|
c.flag %i[b back started]
|
324
348
|
|
349
|
+
c.desc %(
|
350
|
+
Start and end times as a date/time range `doing done --from "1am to 8am"`.
|
351
|
+
Overrides other date flags.
|
352
|
+
)
|
353
|
+
c.arg_name 'TIME_RANGE'
|
354
|
+
c.flag [:from]
|
355
|
+
|
325
356
|
c.desc %(Set completion date to start date plus interval (XX[mhd] or HH:MM).
|
326
357
|
If used without the --back option, the start date will be moved back to allow
|
327
358
|
the completion date to be the current time.)
|
328
359
|
c.arg_name 'INTERVAL'
|
329
|
-
c.flag %i[t took]
|
360
|
+
c.flag %i[t took for]
|
330
361
|
|
331
362
|
c.desc 'Section'
|
332
363
|
c.arg_name 'NAME'
|
@@ -339,6 +370,9 @@ command %i[done did] do |c|
|
|
339
370
|
c.arg_name 'TEXT'
|
340
371
|
c.flag %i[n note]
|
341
372
|
|
373
|
+
c.desc 'Prompt for note via multi-line input'
|
374
|
+
c.switch %i[ask], negatable: false, default_value: false
|
375
|
+
|
342
376
|
c.desc 'Finish last entry not already marked @done'
|
343
377
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
344
378
|
|
@@ -350,30 +384,41 @@ command %i[done did] do |c|
|
|
350
384
|
took = 0
|
351
385
|
donedate = nil
|
352
386
|
|
353
|
-
if options[:
|
354
|
-
|
355
|
-
|
356
|
-
end
|
357
|
-
|
358
|
-
if options[:back]
|
359
|
-
date = options[:back].chronify(guess: :begin)
|
360
|
-
raise InvalidTimeExpression, 'Unable to parse date string for --back' if date.nil?
|
387
|
+
if options[:from]
|
388
|
+
date, finish_date = options[:from].split_date_range
|
389
|
+
finish_date ||= Time.now
|
361
390
|
else
|
362
|
-
|
363
|
-
|
391
|
+
if options[:took]
|
392
|
+
took = options[:took].chronify_qty
|
393
|
+
raise InvalidTimeExpression, 'Unable to parse date string for --took' if took.nil?
|
394
|
+
end
|
364
395
|
|
365
|
-
|
366
|
-
|
367
|
-
|
396
|
+
if options[:back]
|
397
|
+
date = options[:back].chronify(guess: :begin)
|
398
|
+
raise InvalidTimeExpression, 'Unable to parse date string for --back' if date.nil?
|
399
|
+
else
|
400
|
+
date = options[:took] ? Time.now - took : Time.now
|
401
|
+
end
|
368
402
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
403
|
+
if options[:at]
|
404
|
+
finish_date = options[:at].chronify(guess: :begin)
|
405
|
+
raise InvalidTimeExpression, 'Unable to parse date string for --at' if finish_date.nil?
|
406
|
+
|
407
|
+
if options[:took]
|
408
|
+
date = finish_date - took
|
409
|
+
else
|
410
|
+
date ||= finish_date
|
411
|
+
end
|
412
|
+
elsif options[:took]
|
413
|
+
finish_date = date + took
|
414
|
+
else
|
415
|
+
finish_date = Time.now
|
416
|
+
end
|
374
417
|
end
|
375
418
|
|
376
419
|
if options[:date]
|
420
|
+
finish_date = wwid.verify_duration(date, finish_date) unless options[:took] || options[:from]
|
421
|
+
|
377
422
|
donedate = finish_date.strftime('%F %R')
|
378
423
|
end
|
379
424
|
|
@@ -383,9 +428,14 @@ command %i[done did] do |c|
|
|
383
428
|
section = settings['current_section']
|
384
429
|
end
|
385
430
|
|
431
|
+
|
386
432
|
note = Doing::Note.new
|
387
433
|
note.add(options[:note]) if options[:note]
|
388
434
|
|
435
|
+
if options[:ask] && !options[:editor]
|
436
|
+
note.add(Doing::Prompt.read_lines(prompt: 'Add a note'))
|
437
|
+
end
|
438
|
+
|
389
439
|
if options[:editor]
|
390
440
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
391
441
|
is_new = false
|
@@ -410,6 +460,12 @@ command %i[done did] do |c|
|
|
410
460
|
raise EmptyInput, 'No content' unless input && !input.empty?
|
411
461
|
|
412
462
|
d, title, note = wwid.format_input(input)
|
463
|
+
|
464
|
+
if options[:ask]
|
465
|
+
ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
|
466
|
+
note.add(ask_note) unless ask_note.empty?
|
467
|
+
end
|
468
|
+
|
413
469
|
date = d.nil? ? date : d
|
414
470
|
new_entry = Doing::Item.new(date, title, section, note)
|
415
471
|
if new_entry.should_finish?
|
@@ -439,7 +495,6 @@ command %i[done did] do |c|
|
|
439
495
|
if options[:remove]
|
440
496
|
wwid.tag_last({ tags: ['done'], count: 1, section: section, remove: true })
|
441
497
|
else
|
442
|
-
note = options[:note] ? Doing::Note.new(options[:note]) : nil
|
443
498
|
opt = {
|
444
499
|
archive: options[:archive],
|
445
500
|
back: finish_date,
|
@@ -454,12 +509,13 @@ command %i[done did] do |c|
|
|
454
509
|
wwid.tag_last(opt)
|
455
510
|
end
|
456
511
|
elsif !args.empty?
|
457
|
-
note = Doing::Note.new(options[:note])
|
458
512
|
d, title, new_note = wwid.format_input([args.join(' '), note.strip_lines.join("\n")].join("\n"))
|
459
513
|
date = d.nil? ? date : d
|
514
|
+
new_note.add(options[:note])
|
460
515
|
title.chomp!
|
461
516
|
section = 'Archive' if options[:archive]
|
462
517
|
new_entry = Doing::Item.new(date, title, section, new_note)
|
518
|
+
|
463
519
|
if new_entry.should_finish?
|
464
520
|
if new_entry.should_time?
|
465
521
|
new_entry.tag('done', value: donedate)
|
@@ -467,12 +523,14 @@ command %i[done did] do |c|
|
|
467
523
|
new_entry.tag('done')
|
468
524
|
end
|
469
525
|
end
|
526
|
+
|
470
527
|
Doing::Hooks.trigger :pre_entry_add, wwid, new_entry
|
471
528
|
wwid.content.push(new_entry)
|
472
529
|
Doing::Hooks.trigger :post_entry_added, wwid, new_entry.dup
|
473
530
|
wwid.write(wwid.doing_file)
|
474
531
|
Doing.logger.info('Entry Added:', new_entry.title)
|
475
532
|
elsif $stdin.stat.size.positive?
|
533
|
+
note = Doing::Note.new(options[:note])
|
476
534
|
d, title, note = wwid.format_input($stdin.read.strip)
|
477
535
|
unless d.nil?
|
478
536
|
Doing.logger.debug('Parser:', 'Date detected in input, overriding command line values')
|
@@ -520,7 +578,7 @@ command :finish do |c|
|
|
520
578
|
|
521
579
|
c.desc 'Set the completed date to the start date plus XX[hmd]'
|
522
580
|
c.arg_name 'INTERVAL'
|
523
|
-
c.flag %i[t took]
|
581
|
+
c.flag %i[t took for]
|
524
582
|
|
525
583
|
c.desc %(Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm). If used, ignores --back.)
|
526
584
|
c.arg_name 'DATE_STRING'
|
@@ -529,12 +587,16 @@ command :finish do |c|
|
|
529
587
|
c.desc 'Finish the last X entries containing TAG.
|
530
588
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
531
589
|
c.arg_name 'TAG'
|
532
|
-
c.flag [:tag]
|
590
|
+
c.flag [:tag], type: TagArray
|
533
591
|
|
534
592
|
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
593
|
c.arg_name 'QUERY'
|
536
594
|
c.flag [:search]
|
537
595
|
|
596
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
597
|
+
c.arg_name 'QUERY'
|
598
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
599
|
+
|
538
600
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
539
601
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
540
602
|
|
@@ -548,7 +610,7 @@ command :finish do |c|
|
|
548
610
|
c.arg_name 'TYPE'
|
549
611
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
550
612
|
|
551
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
613
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
552
614
|
c.arg_name 'BOOLEAN'
|
553
615
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
554
616
|
|
@@ -604,7 +666,7 @@ command :finish do |c|
|
|
604
666
|
if options[:tag].nil?
|
605
667
|
tags = []
|
606
668
|
else
|
607
|
-
tags = options[:tag]
|
669
|
+
tags = options[:tag]
|
608
670
|
end
|
609
671
|
|
610
672
|
raise InvalidArgument, 'Only one argument allowed' if args.length > 1
|
@@ -641,7 +703,8 @@ command :finish do |c|
|
|
641
703
|
tag_bool: options[:bool].normalize_bool,
|
642
704
|
tags: ['done'],
|
643
705
|
took: options[:took],
|
644
|
-
unfinished: options[:unfinished]
|
706
|
+
unfinished: options[:unfinished],
|
707
|
+
val: options[:val]
|
645
708
|
}
|
646
709
|
|
647
710
|
wwid.tag_last(opts)
|
@@ -666,6 +729,9 @@ command :later do |c|
|
|
666
729
|
c.arg_name 'TEXT'
|
667
730
|
c.flag %i[n note]
|
668
731
|
|
732
|
+
c.desc 'Prompt for note via multi-line input'
|
733
|
+
c.switch %i[ask], negatable: false, default_value: false
|
734
|
+
|
669
735
|
c.action do |_global_options, options, args|
|
670
736
|
if options[:back]
|
671
737
|
date = options[:back].chronify(guess: :begin)
|
@@ -674,23 +740,36 @@ command :later do |c|
|
|
674
740
|
date = Time.now
|
675
741
|
end
|
676
742
|
|
677
|
-
|
743
|
+
ask_note = options[:ask] && !options[:editor] && args.count.positive? ? Doing::Prompt.read_lines(prompt: 'Add a note') : ''
|
744
|
+
|
745
|
+
if options[:editor]
|
678
746
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
679
747
|
|
748
|
+
input = ''
|
680
749
|
input += date.strftime('%F %R | ')
|
681
750
|
input += args.empty? ? '' : args.join(' ')
|
751
|
+
input += "\n#{options[:note]}" if options[:note]
|
752
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
753
|
+
|
682
754
|
input = wwid.fork_editor(input).strip
|
683
|
-
raise EmptyInput, 'No content' unless input && !input.empty?
|
684
755
|
|
685
756
|
d, title, note = wwid.format_input(input)
|
686
|
-
|
757
|
+
raise EmptyInput, 'No content' if title.empty?
|
758
|
+
|
687
759
|
note.add(options[:note]) if options[:note]
|
760
|
+
if ask_note.empty? && options[:ask]
|
761
|
+
ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
|
762
|
+
note.add(ask_note) unless ask_note.empty?
|
763
|
+
end
|
764
|
+
|
765
|
+
date = d.nil? ? date : d
|
688
766
|
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
689
767
|
wwid.write(wwid.doing_file)
|
690
768
|
elsif !args.empty?
|
691
769
|
d, title, note = wwid.format_input(args.join(' '))
|
692
770
|
date = d.nil? ? date : d
|
693
771
|
note.add(options[:note]) if options[:note]
|
772
|
+
note.add(ask_note) unless ask_note.empty?
|
694
773
|
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
695
774
|
wwid.write(wwid.doing_file)
|
696
775
|
elsif $stdin.stat.size.positive?
|
@@ -700,10 +779,20 @@ command :later do |c|
|
|
700
779
|
date = d
|
701
780
|
end
|
702
781
|
note.add(options[:note]) if options[:note]
|
782
|
+
note.add(ask_note) unless ask_note.empty?
|
703
783
|
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
704
784
|
wwid.write(wwid.doing_file)
|
705
785
|
else
|
706
|
-
|
786
|
+
title = Doing::Prompt.read_line(prompt: 'Entry content')
|
787
|
+
raise EmptyInput, 'You must provide content when creating a new entry' if title.strip.empty?
|
788
|
+
|
789
|
+
note = Doing::Note.new
|
790
|
+
res = Doing::Prompt.yn('Add a note', default_response: false)
|
791
|
+
ask_note = res ? Doing::Prompt.read_lines(prompt: 'Enter note') : []
|
792
|
+
note.add(ask_note)
|
793
|
+
|
794
|
+
wwid.add_item(title.cap_first, 'Later', { note: note, back: date })
|
795
|
+
wwid.write(wwid.doing_file)
|
707
796
|
end
|
708
797
|
end
|
709
798
|
end
|
@@ -739,12 +828,16 @@ command %i[mark flag] do |c|
|
|
739
828
|
c.desc 'Flag the last entry containing TAG.
|
740
829
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
741
830
|
c.arg_name 'TAG'
|
742
|
-
c.flag [:tag]
|
831
|
+
c.flag [:tag], type: TagArray
|
743
832
|
|
744
833
|
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
834
|
c.arg_name 'QUERY'
|
746
835
|
c.flag [:search]
|
747
836
|
|
837
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
838
|
+
c.arg_name 'QUERY'
|
839
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
840
|
+
|
748
841
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
749
842
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
750
843
|
|
@@ -758,7 +851,7 @@ command %i[mark flag] do |c|
|
|
758
851
|
c.arg_name 'TYPE'
|
759
852
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
760
853
|
|
761
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
854
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
762
855
|
c.arg_name 'BOOLEAN'
|
763
856
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
764
857
|
|
@@ -780,7 +873,7 @@ command %i[mark flag] do |c|
|
|
780
873
|
if options[:tag].nil?
|
781
874
|
search_tags = []
|
782
875
|
else
|
783
|
-
search_tags = options[:tag]
|
876
|
+
search_tags = options[:tag]
|
784
877
|
end
|
785
878
|
|
786
879
|
if options[:interactive]
|
@@ -862,6 +955,9 @@ command :meanwhile do |c|
|
|
862
955
|
c.arg_name 'TEXT'
|
863
956
|
c.flag %i[n note]
|
864
957
|
|
958
|
+
c.desc 'Prompt for note via multi-line input'
|
959
|
+
c.switch %i[ask], negatable: false, default_value: false
|
960
|
+
|
865
961
|
c.action do |_global_options, options, args|
|
866
962
|
if options[:back]
|
867
963
|
date = options[:back].chronify(guess: :begin)
|
@@ -878,10 +974,15 @@ command :meanwhile do |c|
|
|
878
974
|
end
|
879
975
|
input = ''
|
880
976
|
|
977
|
+
ask_note = options[:ask] ? Doing::Prompt.read_lines(prompt: 'Add a note') : []
|
978
|
+
|
881
979
|
if options[:editor]
|
882
980
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
883
981
|
input += date.strftime('%F %R | ')
|
884
982
|
input += args.join(' ') unless args.empty?
|
983
|
+
input += "\n#{options[:note]}" if options[:note]
|
984
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
985
|
+
|
885
986
|
input = wwid.fork_editor(input).strip
|
886
987
|
elsif !args.empty?
|
887
988
|
input = args.join(' ')
|
@@ -900,10 +1001,9 @@ command :meanwhile do |c|
|
|
900
1001
|
note = []
|
901
1002
|
end
|
902
1003
|
|
903
|
-
|
904
|
-
note.
|
905
|
-
|
906
|
-
note = nil
|
1004
|
+
unless options[:editor]
|
1005
|
+
note.add(options[:note]) if options[:note]
|
1006
|
+
note.add(ask_note) unless ask_note.empty?
|
907
1007
|
end
|
908
1008
|
|
909
1009
|
wwid.stop_start('meanwhile', { new_item: input, back: date, section: section, archive: options[:archive], note: note })
|
@@ -937,14 +1037,18 @@ command :note do |c|
|
|
937
1037
|
c.desc "Replace/Remove last entry's note (default append)"
|
938
1038
|
c.switch %i[r remove], negatable: false, default_value: false
|
939
1039
|
|
940
|
-
c.desc 'Add/remove note from last entry matching tag. Wildcards allowed (*, ?)
|
1040
|
+
c.desc 'Add/remove note from last entry matching tag. Wildcards allowed (*, ?)'
|
941
1041
|
c.arg_name 'TAG'
|
942
|
-
c.flag [:tag]
|
1042
|
+
c.flag [:tag], type: TagArray
|
943
1043
|
|
944
1044
|
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
1045
|
c.arg_name 'QUERY'
|
946
1046
|
c.flag [:search]
|
947
1047
|
|
1048
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1049
|
+
c.arg_name 'QUERY'
|
1050
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1051
|
+
|
948
1052
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
949
1053
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
950
1054
|
|
@@ -958,13 +1062,16 @@ command :note do |c|
|
|
958
1062
|
c.arg_name 'TYPE'
|
959
1063
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
960
1064
|
|
961
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
1065
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
962
1066
|
c.arg_name 'BOOLEAN'
|
963
1067
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
964
1068
|
|
965
1069
|
c.desc 'Select item for new note from a menu of matching entries'
|
966
1070
|
c.switch %i[i interactive], negatable: false, default_value: false
|
967
1071
|
|
1072
|
+
c.desc 'Prompt for note via multi-line input'
|
1073
|
+
c.switch %i[ask], negatable: false, default_value: false
|
1074
|
+
|
968
1075
|
c.action do |_global_options, options, args|
|
969
1076
|
options[:fuzzy] = false
|
970
1077
|
if options[:section]
|
@@ -991,8 +1098,9 @@ command :note do |c|
|
|
991
1098
|
|
992
1099
|
last_note = last_entry.note || Doing::Note.new
|
993
1100
|
new_note = Doing::Note.new
|
1101
|
+
ask_note = options[:ask] ? Doing::Prompt.read_lines(prompt: 'Add a note') : ''
|
994
1102
|
|
995
|
-
if options[:editor] || (args.empty? && $stdin.stat.size.zero? && !options[:remove])
|
1103
|
+
if options[:editor] || (args.empty? && $stdin.stat.size.zero? && !options[:remove] && !options[:ask])
|
996
1104
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
997
1105
|
|
998
1106
|
input = !args.empty? ? args.join(' ') : ''
|
@@ -1003,7 +1111,9 @@ command :note do |c|
|
|
1003
1111
|
prev_input = last_entry.note || Doing::Note.new
|
1004
1112
|
end
|
1005
1113
|
|
1114
|
+
|
1006
1115
|
input = prev_input.add(input)
|
1116
|
+
input.add(ask_note) unless ask_note.empty?
|
1007
1117
|
|
1008
1118
|
input = wwid.fork_editor(prev_input.strip_lines.join("\n"), message: nil).strip
|
1009
1119
|
note = input
|
@@ -1014,9 +1124,12 @@ command :note do |c|
|
|
1014
1124
|
elsif $stdin.stat.size.positive?
|
1015
1125
|
new_note.add($stdin.read.strip)
|
1016
1126
|
else
|
1017
|
-
raise EmptyInput, 'You must provide content when adding a note' unless options[:remove]
|
1127
|
+
raise EmptyInput, 'You must provide content when adding a note' unless options[:remove] || !ask_note.empty?
|
1128
|
+
|
1018
1129
|
end
|
1019
1130
|
|
1131
|
+
new_note.add(ask_note) unless ask_note.empty?
|
1132
|
+
|
1020
1133
|
if last_note.equal?(new_note)
|
1021
1134
|
Doing.logger.debug('Skipped:', 'No note change')
|
1022
1135
|
else
|
@@ -1035,10 +1148,13 @@ long_desc %(Record what you're starting now, or backdate the start time using na
|
|
1035
1148
|
|
1036
1149
|
A parenthetical at the end of the entry will be converted to a note.
|
1037
1150
|
|
1038
|
-
Run
|
1151
|
+
Run without arguments to create a new entry interactively.
|
1152
|
+
|
1153
|
+
Run with --editor to create a new entry using #{Doing::Util.default_editor}.)
|
1039
1154
|
arg_name 'ENTRY'
|
1040
1155
|
command %i[now next] do |c|
|
1041
|
-
c.example 'doing now', desc:
|
1156
|
+
c.example 'doing now', desc: 'Create a new entry with interactive prompts'
|
1157
|
+
c.example 'doing now -e', desc: "Open #{Doing::Util.default_editor} to input an entry and optional note"
|
1042
1158
|
c.example 'doing now working on a new project', desc: 'Add a new entry at the current time'
|
1043
1159
|
c.example 'doing now debugging @project2', desc: 'Add an entry with a tag'
|
1044
1160
|
c.example 'doing now adding an entry (with a note)', desc: 'Parenthetical at end is converted to note'
|
@@ -1062,6 +1178,9 @@ command %i[now next] do |c|
|
|
1062
1178
|
c.arg_name 'TEXT'
|
1063
1179
|
c.flag %i[n note]
|
1064
1180
|
|
1181
|
+
c.desc 'Prompt for note via multi-line input'
|
1182
|
+
c.switch %i[ask], negatable: false, default_value: false
|
1183
|
+
|
1065
1184
|
# c.desc "Edit entry with specified app"
|
1066
1185
|
# c.arg_name 'editor_app'
|
1067
1186
|
# # c.flag [:a, :app]
|
@@ -1081,23 +1200,32 @@ command %i[now next] do |c|
|
|
1081
1200
|
options[:section] = settings['current_section']
|
1082
1201
|
end
|
1083
1202
|
|
1084
|
-
|
1203
|
+
ask_note = options[:ask] && !options[:editor] && args.count.positive? ? Doing::Prompt.read_lines(prompt: 'Add a note') : ''
|
1204
|
+
|
1205
|
+
if options[:editor]
|
1085
1206
|
raise MissingEditor, 'No EDITOR variable defined in environment' if Doing::Util.default_editor.nil?
|
1086
1207
|
|
1087
1208
|
input = date.strftime('%F %R | ')
|
1088
1209
|
input += args.join(' ') unless args.empty?
|
1210
|
+
input += "\n#{options[:note]}" if options[:note]
|
1211
|
+
input += "\n#{ask_note}" unless ask_note.empty?
|
1089
1212
|
input = wwid.fork_editor(input).strip
|
1090
1213
|
|
1091
|
-
raise EmptyInput, 'No content' if input.empty?
|
1092
|
-
|
1093
1214
|
date, title, note = wwid.format_input(input)
|
1094
|
-
|
1215
|
+
raise EmptyInput, 'No content' if title.strip.empty?
|
1216
|
+
|
1217
|
+
if ask_note.empty? && options[:ask]
|
1218
|
+
ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
|
1219
|
+
note.add(ask_note) unless ask_note.empty?
|
1220
|
+
end
|
1221
|
+
|
1095
1222
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1096
1223
|
wwid.write(wwid.doing_file)
|
1097
1224
|
elsif args.length.positive?
|
1098
1225
|
d, title, note = wwid.format_input(args.join(' '))
|
1099
1226
|
date = d.nil? ? date : d
|
1100
1227
|
note.add(options[:note]) if options[:note]
|
1228
|
+
note.add(ask_note) unless ask_note.empty?
|
1101
1229
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1102
1230
|
wwid.write(wwid.doing_file)
|
1103
1231
|
elsif $stdin.stat.size.positive?
|
@@ -1108,10 +1236,20 @@ command %i[now next] do |c|
|
|
1108
1236
|
date = d
|
1109
1237
|
end
|
1110
1238
|
note.add(options[:note]) if options[:note]
|
1239
|
+
note.add(ask_note) unless ask_note.empty?
|
1111
1240
|
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1112
1241
|
wwid.write(wwid.doing_file)
|
1113
1242
|
else
|
1114
|
-
|
1243
|
+
title = Doing::Prompt.read_line(prompt: 'Entry content')
|
1244
|
+
raise EmptyInput, 'You must provide content when creating a new entry' if title.strip.empty?
|
1245
|
+
|
1246
|
+
note = Doing::Note.new
|
1247
|
+
res = Doing::Prompt.yn('Add a note', default_response: false)
|
1248
|
+
ask_note = res ? Doing::Prompt.read_lines(prompt: 'Enter note') : []
|
1249
|
+
note.add(ask_note)
|
1250
|
+
|
1251
|
+
wwid.add_item(title.cap_first, section, { note: note, back: date, timed: options[:finish_last] })
|
1252
|
+
wwid.write(wwid.doing_file)
|
1115
1253
|
end
|
1116
1254
|
end
|
1117
1255
|
end
|
@@ -1135,7 +1273,7 @@ command %i[reset begin] do |c|
|
|
1135
1273
|
c.desc 'Resume entry (remove @done)'
|
1136
1274
|
c.switch %i[r resume], default_value: true
|
1137
1275
|
|
1138
|
-
c.desc 'Reset last entry matching tag. Wildcards allowed (*, ?)
|
1276
|
+
c.desc 'Reset last entry matching tag. Wildcards allowed (*, ?)'
|
1139
1277
|
c.arg_name 'TAG'
|
1140
1278
|
c.flag [:tag]
|
1141
1279
|
|
@@ -1143,6 +1281,10 @@ command %i[reset begin] do |c|
|
|
1143
1281
|
c.arg_name 'QUERY'
|
1144
1282
|
c.flag [:search]
|
1145
1283
|
|
1284
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1285
|
+
c.arg_name 'QUERY'
|
1286
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1287
|
+
|
1146
1288
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
1147
1289
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
1148
1290
|
|
@@ -1156,7 +1298,7 @@ command %i[reset begin] do |c|
|
|
1156
1298
|
c.arg_name 'TYPE'
|
1157
1299
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1158
1300
|
|
1159
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
1301
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
1160
1302
|
c.arg_name 'BOOLEAN'
|
1161
1303
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1162
1304
|
|
@@ -1256,13 +1398,21 @@ command :select do |c|
|
|
1256
1398
|
|
1257
1399
|
c.desc 'Initial search query for filtering. Matching is fuzzy. For exact matching, start query with a single quote, e.g. `--query "\'search"'
|
1258
1400
|
c.arg_name 'QUERY'
|
1259
|
-
c.flag %i[q query
|
1401
|
+
c.flag %i[q query]
|
1402
|
+
|
1403
|
+
c.desc 'Select from entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
1404
|
+
c.arg_name 'QUERY'
|
1405
|
+
c.flag [:search]
|
1406
|
+
|
1407
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1408
|
+
c.arg_name 'QUERY'
|
1409
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1260
1410
|
|
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
|
1411
|
+
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
1412
|
c.arg_name 'DATE_STRING'
|
1263
1413
|
c.flag [:before]
|
1264
1414
|
|
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
|
1415
|
+
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
1416
|
c.arg_name 'DATE_STRING'
|
1267
1417
|
c.flag [:after]
|
1268
1418
|
|
@@ -1287,7 +1437,7 @@ command :select do |c|
|
|
1287
1437
|
c.arg_name 'TYPE'
|
1288
1438
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1289
1439
|
|
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
|
1440
|
+
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
1441
|
c.switch %i[menu], negatable: true, default_value: true
|
1292
1442
|
|
1293
1443
|
c.desc 'Cancel selected items (add @done without timestamp)'
|
@@ -1305,7 +1455,7 @@ command :select do |c|
|
|
1305
1455
|
c.desc 'Add flag to selected item(s)'
|
1306
1456
|
c.switch %i[flag], negatable: false, default_value: false
|
1307
1457
|
|
1308
|
-
c.desc 'Perform action without confirmation
|
1458
|
+
c.desc 'Perform action without confirmation'
|
1309
1459
|
c.switch %i[force], negatable: false, default_value: false
|
1310
1460
|
|
1311
1461
|
c.desc 'Save selected entries to file using --output format'
|
@@ -1365,6 +1515,10 @@ command :tag do |c|
|
|
1365
1515
|
c.arg_name 'ORIG_TAG'
|
1366
1516
|
c.flag %i[rename]
|
1367
1517
|
|
1518
|
+
c.desc 'Include a value, e.g. @tag(value)'
|
1519
|
+
c.arg_name 'VALUE'
|
1520
|
+
c.flag %i[v value]
|
1521
|
+
|
1368
1522
|
c.desc 'Don\'t ask permission to tag all entries when count is 0'
|
1369
1523
|
c.switch %i[force], negatable: false, default_value: false
|
1370
1524
|
|
@@ -1386,12 +1540,16 @@ command :tag do |c|
|
|
1386
1540
|
c.desc 'Tag the last X entries containing TAG.
|
1387
1541
|
Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool. Wildcards allowed (*, ?).'
|
1388
1542
|
c.arg_name 'TAG'
|
1389
|
-
c.flag [:tag]
|
1543
|
+
c.flag [:tag], type: TagArray
|
1390
1544
|
|
1391
1545
|
c.desc 'Tag entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
1392
1546
|
c.arg_name 'QUERY'
|
1393
1547
|
c.flag [:search]
|
1394
1548
|
|
1549
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1550
|
+
c.arg_name 'QUERY'
|
1551
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1552
|
+
|
1395
1553
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
1396
1554
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
1397
1555
|
|
@@ -1405,7 +1563,7 @@ command :tag do |c|
|
|
1405
1563
|
c.arg_name 'TYPE'
|
1406
1564
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
1407
1565
|
|
1408
|
-
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans
|
1566
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters. Use PATTERN to parse + and - as booleans'
|
1409
1567
|
c.arg_name 'BOOLEAN'
|
1410
1568
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1411
1569
|
|
@@ -1414,7 +1572,7 @@ command :tag do |c|
|
|
1414
1572
|
|
1415
1573
|
c.action do |_global_options, options, args|
|
1416
1574
|
options[:fuzzy] = false
|
1417
|
-
raise MissingArgument, 'You must specify at least one tag' if args.empty? && !options[:autotag]
|
1575
|
+
# raise MissingArgument, 'You must specify at least one tag' if args.empty? && !options[:autotag]
|
1418
1576
|
|
1419
1577
|
raise InvalidArgument, '--search and --tag can not be used together' if options[:search] && options[:tag]
|
1420
1578
|
|
@@ -1428,17 +1586,21 @@ command :tag do |c|
|
|
1428
1586
|
if options[:tag].nil?
|
1429
1587
|
search_tags = []
|
1430
1588
|
else
|
1431
|
-
search_tags = options[:tag]
|
1589
|
+
search_tags = options[:tag]
|
1432
1590
|
end
|
1433
1591
|
|
1434
1592
|
if options[:autotag]
|
1435
1593
|
tags = []
|
1436
1594
|
else
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1595
|
+
if args.empty?
|
1596
|
+
tags = []
|
1597
|
+
else
|
1598
|
+
tags = if args.join('') =~ /,/
|
1599
|
+
args.join('').split(/ *, */)
|
1600
|
+
else
|
1601
|
+
args.join(' ').split(' ') # in case tags are quoted as one arg
|
1602
|
+
end
|
1603
|
+
end
|
1442
1604
|
|
1443
1605
|
tags.map! { |tag| tag.sub(/^@/, '').strip }
|
1444
1606
|
end
|
@@ -1528,11 +1690,11 @@ command %i[grep search] do |c|
|
|
1528
1690
|
c.arg_name 'NAME'
|
1529
1691
|
c.flag %i[s section], default_value: 'All'
|
1530
1692
|
|
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
|
1693
|
+
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
1694
|
c.arg_name 'DATE_STRING'
|
1533
1695
|
c.flag [:before]
|
1534
1696
|
|
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
|
1697
|
+
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
1698
|
c.arg_name 'DATE_STRING'
|
1537
1699
|
c.flag [:after]
|
1538
1700
|
|
@@ -1591,6 +1753,13 @@ command %i[grep search] do |c|
|
|
1591
1753
|
c.desc 'Display an interactive menu of results to perform further operations'
|
1592
1754
|
c.switch %i[i interactive], default_value: false, negatable: false
|
1593
1755
|
|
1756
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1757
|
+
c.arg_name 'QUERY'
|
1758
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1759
|
+
|
1760
|
+
c.desc 'Combine multiple tags or value queries using AND, OR, or NOT'
|
1761
|
+
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
1762
|
+
|
1594
1763
|
c.action do |_global_options, options, args|
|
1595
1764
|
options[:fuzzy] = false
|
1596
1765
|
raise DoingRuntimeError, %(Invalid output type "#{options[:output]}") if options[:output] && options[:output] !~ Doing::Plugins.plugin_regex(type: :export)
|
@@ -1601,6 +1770,7 @@ command %i[grep search] do |c|
|
|
1601
1770
|
section = wwid.guess_section(options[:section]) if options[:section]
|
1602
1771
|
|
1603
1772
|
options[:case] = options[:case].normalize_case
|
1773
|
+
options[:bool] = options[:bool].normalize_bool
|
1604
1774
|
|
1605
1775
|
search = args.join(' ')
|
1606
1776
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1639,11 +1809,11 @@ command :last do |c|
|
|
1639
1809
|
c.desc "Delete the last entry"
|
1640
1810
|
c.switch %i[d delete], negatable: false, default_value: false
|
1641
1811
|
|
1642
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)
|
1812
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
1643
1813
|
c.arg_name 'TAG'
|
1644
|
-
c.flag [:tag]
|
1814
|
+
c.flag [:tag], type: TagArray
|
1645
1815
|
|
1646
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
1816
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
1647
1817
|
c.arg_name 'BOOLEAN'
|
1648
1818
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1649
1819
|
|
@@ -1651,6 +1821,10 @@ command :last do |c|
|
|
1651
1821
|
c.arg_name 'QUERY'
|
1652
1822
|
c.flag [:search]
|
1653
1823
|
|
1824
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1825
|
+
c.arg_name 'QUERY'
|
1826
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1827
|
+
|
1654
1828
|
c.desc 'Show elapsed time if entry is not tagged @done'
|
1655
1829
|
c.switch [:duration]
|
1656
1830
|
|
@@ -1674,7 +1848,7 @@ command :last do |c|
|
|
1674
1848
|
if options[:tag].nil?
|
1675
1849
|
options[:tag] = []
|
1676
1850
|
else
|
1677
|
-
options[:tag] = options[:tag]
|
1851
|
+
options[:tag] = options[:tag]
|
1678
1852
|
options[:bool] = options[:bool].normalize_bool
|
1679
1853
|
end
|
1680
1854
|
|
@@ -1685,12 +1859,14 @@ command :last do |c|
|
|
1685
1859
|
if options[:editor]
|
1686
1860
|
wwid.edit_last(section: options[:section],
|
1687
1861
|
options: {
|
1688
|
-
search: search,
|
1862
|
+
search: options[:search],
|
1689
1863
|
fuzzy: options[:fuzzy],
|
1690
1864
|
case: options[:case],
|
1691
|
-
tag:
|
1865
|
+
tag: options[:tag],
|
1692
1866
|
tag_bool: options[:bool],
|
1693
|
-
not: options[:not]
|
1867
|
+
not: options[:not],
|
1868
|
+
val: options[:val],
|
1869
|
+
bool: options[:bool]
|
1694
1870
|
})
|
1695
1871
|
else
|
1696
1872
|
last = wwid.last(times: true, section: options[:section],
|
@@ -1702,7 +1878,9 @@ command :last do |c|
|
|
1702
1878
|
negate: options[:not],
|
1703
1879
|
tag: options[:tag],
|
1704
1880
|
tag_bool: options[:bool],
|
1705
|
-
delete: options[:delete]
|
1881
|
+
delete: options[:delete],
|
1882
|
+
bool: options[:bool],
|
1883
|
+
val: options[:val]
|
1706
1884
|
})
|
1707
1885
|
Doing::Pager::page last.strip if last
|
1708
1886
|
end
|
@@ -1798,11 +1976,15 @@ command :show do |c|
|
|
1798
1976
|
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
1977
|
c.example 'doing show --interactive Later @doing', desc: 'Create a menu from entries from the Later section tagged @doing to perform batch actions'
|
1800
1978
|
|
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
|
1979
|
+
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
1980
|
c.arg_name 'TAG'
|
1803
|
-
c.flag [:tag]
|
1981
|
+
c.flag [:tag], type: TagArray
|
1982
|
+
|
1983
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
1984
|
+
c.arg_name 'QUERY'
|
1985
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
1804
1986
|
|
1805
|
-
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans
|
1987
|
+
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
1806
1988
|
c.arg_name 'BOOLEAN'
|
1807
1989
|
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
1808
1990
|
|
@@ -1814,11 +1996,11 @@ command :show do |c|
|
|
1814
1996
|
c.arg_name 'AGE'
|
1815
1997
|
c.flag %i[a age], default_value: 'newest'
|
1816
1998
|
|
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
|
1999
|
+
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
2000
|
c.arg_name 'DATE_STRING'
|
1819
2001
|
c.flag [:before]
|
1820
2002
|
|
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
|
2003
|
+
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
2004
|
c.arg_name 'DATE_STRING'
|
1823
2005
|
c.flag [:after]
|
1824
2006
|
|
@@ -1929,7 +2111,7 @@ command :show do |c|
|
|
1929
2111
|
section ||= 'All'
|
1930
2112
|
end
|
1931
2113
|
|
1932
|
-
tags.concat(options[:tag]
|
2114
|
+
tags.concat(options[:tag]) if options[:tag]
|
1933
2115
|
|
1934
2116
|
options[:times] = true if options[:totals]
|
1935
2117
|
|
@@ -2012,7 +2194,7 @@ command :tags do |c|
|
|
2012
2194
|
c.arg_name 'ORDER'
|
2013
2195
|
c.flag %i[o order], must_match: REGEX_SORT_ORDER, default_value: 'asc'
|
2014
2196
|
|
2015
|
-
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)
|
2197
|
+
c.desc 'Get tags for entries matching tags. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
2016
2198
|
c.arg_name 'TAG'
|
2017
2199
|
c.flag [:tag]
|
2018
2200
|
|
@@ -2021,6 +2203,10 @@ command :tags do |c|
|
|
2021
2203
|
c.arg_name 'QUERY'
|
2022
2204
|
c.flag [:search]
|
2023
2205
|
|
2206
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
2207
|
+
c.arg_name 'QUERY'
|
2208
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
2209
|
+
|
2024
2210
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
2025
2211
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
2026
2212
|
|
@@ -2034,7 +2220,7 @@ command :tags do |c|
|
|
2034
2220
|
c.arg_name 'TYPE'
|
2035
2221
|
c.flag [:case], must_match: /^[csi]/, default_value: settings.dig('search', 'case')
|
2036
2222
|
|
2037
|
-
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans
|
2223
|
+
c.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
|
2038
2224
|
c.arg_name 'BOOLEAN'
|
2039
2225
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2040
2226
|
|
@@ -2291,11 +2477,15 @@ command :view do |c|
|
|
2291
2477
|
c.desc 'Include colors in output'
|
2292
2478
|
c.switch [:color], default_value: true, negatable: true
|
2293
2479
|
|
2294
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)
|
2480
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?)'
|
2295
2481
|
c.arg_name 'TAG'
|
2296
2482
|
c.flag [:tag]
|
2297
2483
|
|
2298
|
-
c.desc '
|
2484
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
2485
|
+
c.arg_name 'QUERY'
|
2486
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
2487
|
+
|
2488
|
+
c.desc 'Tag boolean (AND,OR,NOT). Use PATTERN to parse + and - as booleans'
|
2299
2489
|
c.arg_name 'BOOLEAN'
|
2300
2490
|
c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2301
2491
|
|
@@ -2324,11 +2514,11 @@ command :view do |c|
|
|
2324
2514
|
c.arg_name 'DIRECTION'
|
2325
2515
|
c.flag [:tag_order], must_match: REGEX_SORT_ORDER
|
2326
2516
|
|
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
|
2517
|
+
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
2518
|
c.arg_name 'DATE_STRING'
|
2329
2519
|
c.flag [:before]
|
2330
2520
|
|
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
|
2521
|
+
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
2522
|
c.arg_name 'DATE_STRING'
|
2333
2523
|
c.flag [:after]
|
2334
2524
|
|
@@ -2935,11 +3125,11 @@ command %i[archive move] do |c|
|
|
2935
3125
|
c.desc 'Label moved items with @from(SECTION_NAME)'
|
2936
3126
|
c.switch [:label], default_value: true, negatable: true
|
2937
3127
|
|
2938
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands
|
3128
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands'
|
2939
3129
|
c.arg_name 'TAG'
|
2940
|
-
c.flag [:tag]
|
3130
|
+
c.flag [:tag], type: TagArray
|
2941
3131
|
|
2942
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
3132
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
2943
3133
|
c.arg_name 'BOOLEAN'
|
2944
3134
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
2945
3135
|
|
@@ -2947,6 +3137,10 @@ command %i[archive move] do |c|
|
|
2947
3137
|
c.arg_name 'QUERY'
|
2948
3138
|
c.flag [:search]
|
2949
3139
|
|
3140
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
3141
|
+
c.arg_name 'QUERY'
|
3142
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
3143
|
+
|
2950
3144
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
2951
3145
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
2952
3146
|
|
@@ -2982,7 +3176,7 @@ command %i[archive move] do |c|
|
|
2982
3176
|
|
2983
3177
|
raise InvalidArgument, '--keep and --count can not be used together' if options[:keep] && options[:count]
|
2984
3178
|
|
2985
|
-
tags.concat(options[:tag]
|
3179
|
+
tags.concat(options[:tag]) if options[:tag]
|
2986
3180
|
|
2987
3181
|
search = nil
|
2988
3182
|
|
@@ -3042,7 +3236,7 @@ command :import do |c|
|
|
3042
3236
|
|
3043
3237
|
c.desc 'Tag all imported entries'
|
3044
3238
|
c.arg_name 'TAGS'
|
3045
|
-
c.flag
|
3239
|
+
c.flag %i[t tag]
|
3046
3240
|
|
3047
3241
|
c.desc 'Autotag entries'
|
3048
3242
|
c.switch :autotag, negatable: true, default_value: true
|
@@ -3077,6 +3271,12 @@ command :import do |c|
|
|
3077
3271
|
options[:section] = wwid.guess_section(options[:section]) || options[:section].cap_first
|
3078
3272
|
end
|
3079
3273
|
|
3274
|
+
if options[:search]
|
3275
|
+
search = options[:search]
|
3276
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
3277
|
+
options[:search] = search
|
3278
|
+
end
|
3279
|
+
|
3080
3280
|
if options[:from]
|
3081
3281
|
date_string = options[:from]
|
3082
3282
|
if date_string =~ / (to|through|thru|(un)?til|-+) /
|
@@ -3085,7 +3285,7 @@ command :import do |c|
|
|
3085
3285
|
finish = dates[2].chronify(guess: :end)
|
3086
3286
|
else
|
3087
3287
|
start = date_string.chronify(guess: :begin)
|
3088
|
-
finish =
|
3288
|
+
finish = date_string.chronify(guess: :end)
|
3089
3289
|
end
|
3090
3290
|
raise InvalidTimeExpression, 'Unrecognized date string' unless start
|
3091
3291
|
dates = [start, finish]
|
@@ -3122,11 +3322,11 @@ command :rotate do |c|
|
|
3122
3322
|
c.arg_name 'SECTION_NAME'
|
3123
3323
|
c.flag %i[s section], default_value: 'All'
|
3124
3324
|
|
3125
|
-
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands
|
3325
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Wildcards allowed (*, ?). Added for compatibility with other commands'
|
3126
3326
|
c.arg_name 'TAG'
|
3127
3327
|
c.flag [:tag]
|
3128
3328
|
|
3129
|
-
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans
|
3329
|
+
c.desc 'Tag boolean (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
|
3130
3330
|
c.arg_name 'BOOLEAN'
|
3131
3331
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'PATTERN'
|
3132
3332
|
|
@@ -3134,6 +3334,10 @@ command :rotate do |c|
|
|
3134
3334
|
c.arg_name 'QUERY'
|
3135
3335
|
c.flag [:search]
|
3136
3336
|
|
3337
|
+
c.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50"). May be used multiple times, combined with --bool'
|
3338
|
+
c.arg_name 'QUERY'
|
3339
|
+
c.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
|
3340
|
+
|
3137
3341
|
# c.desc '[DEPRECATED] Use alternative fuzzy matching for search string'
|
3138
3342
|
# c.switch [:fuzzy], default_value: false, negatable: false
|
3139
3343
|
|
@@ -3357,7 +3561,7 @@ command :undo do |c|
|
|
3357
3561
|
c.arg_name 'COUNT'
|
3358
3562
|
c.flag %i[p prune], type: Integer
|
3359
3563
|
|
3360
|
-
c.desc 'Redo last undo. Note: you cannot undo a redo
|
3564
|
+
c.desc 'Redo last undo. Note: you cannot undo a redo'
|
3361
3565
|
c.switch %i[r redo]
|
3362
3566
|
|
3363
3567
|
c.action do |_global_options, options, args|
|
@@ -3384,7 +3588,7 @@ command :undo do |c|
|
|
3384
3588
|
end
|
3385
3589
|
|
3386
3590
|
# @@redo
|
3387
|
-
long_desc 'Shortcut for `doing undo -r`, reverses the last undo command. You cannot undo a redo
|
3591
|
+
long_desc 'Shortcut for `doing undo -r`, reverses the last undo command. You cannot undo a redo'
|
3388
3592
|
arg_name 'COUNT'
|
3389
3593
|
command :redo do |c|
|
3390
3594
|
c.desc 'Specify alternate doing file'
|