doing 2.1.12 → 2.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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'
|