doing 2.0.6.pre → 2.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardoc/checksums +20 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +7 -7
- data/Gemfile.lock +30 -10
- data/README.md +1 -1
- data/Rakefile +8 -1
- data/bin/doing +367 -21
- data/doc/Array.html +135 -0
- data/doc/Doing/Color.html +506 -0
- data/doc/Doing/Configuration.html +680 -0
- data/doc/Doing/Errors/DoingNoTraceError.html +186 -0
- data/doc/Doing/Errors/DoingRuntimeError.html +186 -0
- data/doc/Doing/Errors/DoingStandardError.html +186 -0
- data/doc/Doing/Errors/EmptyInput.html +186 -0
- data/doc/Doing/Errors/NoResults.html +186 -0
- data/doc/Doing/Errors/PluginException.html +248 -0
- data/doc/Doing/Errors/UserCancelled.html +186 -0
- data/doc/Doing/Errors/WrongCommand.html +186 -0
- data/doc/Doing/Errors.html +191 -0
- data/doc/Doing/Hooks.html +364 -0
- data/doc/Doing/Item.html +1385 -0
- data/doc/Doing/Items.html +393 -0
- data/doc/Doing/LogAdapter.html +1650 -0
- data/doc/Doing/Note.html +535 -0
- data/doc/Doing/Pager.html +268 -0
- data/doc/Doing/Plugins.html +849 -0
- data/doc/Doing/Util.html +870 -0
- data/doc/Doing/WWID.html +4827 -0
- data/doc/Doing.html +145 -0
- data/doc/GLI/Commands/MarkdownDocumentListener.html +763 -0
- data/doc/GLI/Commands.html +115 -0
- data/doc/GLI.html +115 -0
- data/doc/Hash.html +332 -0
- data/doc/Status.html +292 -0
- data/doc/String.html +1714 -0
- data/doc/Symbol.html +250 -0
- data/doc/Time.html +182 -0
- data/doc/_index.html +411 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +497 -0
- data/doc/file.README.html +123 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +123 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +1867 -0
- data/doc/top-level-namespace.html +112 -0
- data/doing.gemspec +5 -1
- data/doing.rdoc +354 -6
- data/example_plugin.rb +6 -6
- data/lib/doing/array.rb +1 -1
- data/lib/doing/configuration.rb +14 -12
- data/lib/doing/errors.rb +1 -1
- data/lib/doing/hash.rb +1 -1
- data/lib/doing/item.rb +113 -23
- data/lib/doing/log_adapter.rb +123 -113
- data/lib/doing/note.rb +1 -1
- data/lib/doing/plugin_manager.rb +5 -5
- data/lib/doing/plugins/export/csv_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +5 -7
- data/lib/doing/plugins/import/calendar_import.rb +8 -2
- data/lib/doing/plugins/import/doing_import.rb +10 -10
- data/lib/doing/plugins/import/timing_import.rb +12 -4
- data/lib/doing/string.rb +94 -19
- data/lib/doing/symbol.rb +9 -5
- data/lib/doing/time.rb +1 -1
- data/lib/doing/util.rb +18 -11
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +455 -335
- data/lib/doing/wwidfile.rb +5 -5
- data/lib/doing.rb +2 -1
- data/lib/examples/plugins/say_export.rb +6 -6
- data/lib/examples/plugins/{templates → wiki_export/templates}/wiki.css +0 -0
- data/lib/examples/plugins/{templates → wiki_export/templates}/wiki.haml +0 -0
- data/lib/examples/plugins/{templates → wiki_export/templates}/wiki_index.haml +0 -0
- data/lib/examples/plugins/{wiki_export.rb → wiki_export/wiki_export.rb} +0 -0
- data/rdocfixer.rb +1 -1
- data/scripts/generate_zsh_completions.rb +3 -2
- data/yard_templates/default/method_details/setup.rb +3 -0
- metadata +121 -8
data/bin/doing
CHANGED
|
@@ -62,7 +62,10 @@ if settings.dig('plugins', 'command_path')
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
program_desc 'A CLI for a What Was I Doing system'
|
|
65
|
-
program_long_desc %(Doing uses a TaskPaper-like formatting to keep a plain text
|
|
65
|
+
program_long_desc %(Doing uses a TaskPaper-like formatting to keep a plain text
|
|
66
|
+
record of what you've been doing, complete with tag-based time tracking. The
|
|
67
|
+
command line tool allows you to add entries, annotate with tags and notes, and
|
|
68
|
+
view your entries with myriad options, with a focus on a "natural" language syntax.)
|
|
66
69
|
|
|
67
70
|
default_command :recent
|
|
68
71
|
# sort_help :manually
|
|
@@ -180,7 +183,7 @@ end
|
|
|
180
183
|
|
|
181
184
|
desc 'Reset the start time of an entry'
|
|
182
185
|
command %i[reset begin] do |c|
|
|
183
|
-
c.desc '
|
|
186
|
+
c.desc 'Limit search to section'
|
|
184
187
|
c.arg_name 'NAME'
|
|
185
188
|
c.flag %i[s section], default_value: 'All'
|
|
186
189
|
|
|
@@ -195,6 +198,19 @@ command %i[reset begin] do |c|
|
|
|
195
198
|
c.arg_name 'QUERY'
|
|
196
199
|
c.flag [:search]
|
|
197
200
|
|
|
201
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
202
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
203
|
+
|
|
204
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
205
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
206
|
+
|
|
207
|
+
c.desc 'Reset items that *don\'t* match search/tag filters'
|
|
208
|
+
c.switch [:not], default_value: false, negatable: false
|
|
209
|
+
|
|
210
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
211
|
+
c.arg_name 'TYPE'
|
|
212
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
213
|
+
|
|
198
214
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
|
199
215
|
c.arg_name 'BOOLEAN'
|
|
200
216
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -207,7 +223,16 @@ command %i[reset begin] do |c|
|
|
|
207
223
|
options[:section] = wwid.guess_section(options[:section]) || options[:section].cap_first
|
|
208
224
|
end
|
|
209
225
|
|
|
210
|
-
options[:
|
|
226
|
+
options[:bool] = options[:bool].normalize_bool
|
|
227
|
+
|
|
228
|
+
options[:case] = options[:case].normalize_case
|
|
229
|
+
|
|
230
|
+
if options[:search]
|
|
231
|
+
search = options[:search]
|
|
232
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
233
|
+
options[:search] = search
|
|
234
|
+
end
|
|
235
|
+
|
|
211
236
|
|
|
212
237
|
items = wwid.filter_items([], opt: options)
|
|
213
238
|
|
|
@@ -248,6 +273,11 @@ long_desc %(
|
|
|
248
273
|
)
|
|
249
274
|
arg_name 'NOTE_TEXT'
|
|
250
275
|
command :note do |c|
|
|
276
|
+
c.example 'doing note', desc: 'Open the last entry in $EDITOR to append a note'
|
|
277
|
+
c.example 'doing note "Just a quick annotation"', desc: 'Add a quick note to the last entry'
|
|
278
|
+
c.example 'doing note --tag done "Keeping it real or something"', desc: 'Add a note to the last item tagged @done'
|
|
279
|
+
c.example 'doing note --search "late night" -e', desc: 'Open $EDITOR to add a note to the last item containing "late night" (fuzzy matched)'
|
|
280
|
+
|
|
251
281
|
c.desc 'Section'
|
|
252
282
|
c.arg_name 'NAME'
|
|
253
283
|
c.flag %i[s section], default_value: 'All'
|
|
@@ -266,6 +296,19 @@ command :note do |c|
|
|
|
266
296
|
c.arg_name 'QUERY'
|
|
267
297
|
c.flag [:search]
|
|
268
298
|
|
|
299
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
300
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
301
|
+
|
|
302
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
303
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
304
|
+
|
|
305
|
+
c.desc 'Add note to item that *doesn\'t* match search/tag filters'
|
|
306
|
+
c.switch [:not], default_value: false, negatable: false
|
|
307
|
+
|
|
308
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
309
|
+
c.arg_name 'TYPE'
|
|
310
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
311
|
+
|
|
269
312
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
|
270
313
|
c.arg_name 'BOOLEAN'
|
|
271
314
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -280,6 +323,15 @@ command :note do |c|
|
|
|
280
323
|
|
|
281
324
|
options[:tag_bool] = options[:bool].normalize_bool
|
|
282
325
|
|
|
326
|
+
options[:case] = options[:case].normalize_case
|
|
327
|
+
|
|
328
|
+
if options[:search]
|
|
329
|
+
search = options[:search]
|
|
330
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
331
|
+
options[:search] = search
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
|
|
283
335
|
last_entry = wwid.last_entry(options)
|
|
284
336
|
|
|
285
337
|
unless last_entry
|
|
@@ -330,6 +382,11 @@ end
|
|
|
330
382
|
desc 'Finish any running @meanwhile tasks and optionally create a new one'
|
|
331
383
|
arg_name 'ENTRY'
|
|
332
384
|
command :meanwhile do |c|
|
|
385
|
+
c.example 'doing meanwhile "Long task that will have others after it before it\'s done"', desc: 'Add a new long-running entry, completing any current @meanwhile entry'
|
|
386
|
+
c.example 'doing meanwhile', desc: 'Finish any open @meanwhile entry'
|
|
387
|
+
c.example 'doing meanwhile --archive', desc: 'Finish any open @meanwhile entry and archive it'
|
|
388
|
+
c.example 'doing meanwhile --back 2h "Something I\'ve been working on for a while', desc: 'Add a @meanwhile entry with a start date 2 hours ago'
|
|
389
|
+
|
|
333
390
|
c.desc 'Section'
|
|
334
391
|
c.arg_name 'NAME'
|
|
335
392
|
c.flag %i[s section]
|
|
@@ -396,12 +453,12 @@ end
|
|
|
396
453
|
desc 'Output HTML, CSS, and Markdown (ERB) templates for customization'
|
|
397
454
|
long_desc %(
|
|
398
455
|
Templates are printed to STDOUT for piping to a file.
|
|
399
|
-
Save them and use them in the configuration file under
|
|
400
|
-
|
|
401
|
-
Example `doing template haml > ~/styles/my_doing.haml`
|
|
456
|
+
Save them and use them in the configuration file under export_templates.
|
|
402
457
|
)
|
|
403
458
|
arg_name 'TYPE', must_match: Doing::Plugins.template_regex
|
|
404
459
|
command :template do |c|
|
|
460
|
+
c.example 'doing template haml > ~/styles/my_doing.haml', desc: 'Output the haml template and save it to a file'
|
|
461
|
+
|
|
405
462
|
c.desc 'List all available templates'
|
|
406
463
|
c.switch %i[l list], negatable: false
|
|
407
464
|
|
|
@@ -473,6 +530,16 @@ command :select do |c|
|
|
|
473
530
|
c.arg_name 'QUERY'
|
|
474
531
|
c.flag %i[q query search]
|
|
475
532
|
|
|
533
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
534
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
535
|
+
|
|
536
|
+
c.desc 'Select items that *don\'t* match search/tag filters'
|
|
537
|
+
c.switch [:not], default_value: false, negatable: false
|
|
538
|
+
|
|
539
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
540
|
+
c.arg_name 'TYPE'
|
|
541
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
542
|
+
|
|
476
543
|
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.'
|
|
477
544
|
c.switch %i[menu], negatable: true, default_value: true
|
|
478
545
|
|
|
@@ -510,6 +577,8 @@ command :select do |c|
|
|
|
510
577
|
|
|
511
578
|
raise InvalidArgument, '--no-menu requires --query' if !options[:menu] && !options[:query]
|
|
512
579
|
|
|
580
|
+
options[:case] = options[:case].normalize_case
|
|
581
|
+
|
|
513
582
|
wwid.interactive(options)
|
|
514
583
|
end
|
|
515
584
|
end
|
|
@@ -517,6 +586,9 @@ end
|
|
|
517
586
|
desc 'Add an item to the Later section'
|
|
518
587
|
arg_name 'ENTRY'
|
|
519
588
|
command :later do |c|
|
|
589
|
+
c.example 'doing later "Something I\'ll think about tomorrow"', desc: 'Add an entry to the Later section'
|
|
590
|
+
c.example 'doing later -e', desc: 'Open $EDITOR to create an entry and optional note'
|
|
591
|
+
|
|
520
592
|
c.desc "Edit entry with #{Doing::Util.default_editor}"
|
|
521
593
|
c.switch %i[e editor], negatable: false, default_value: false
|
|
522
594
|
|
|
@@ -566,6 +638,11 @@ end
|
|
|
566
638
|
desc 'Add a completed item with @done(date). No argument finishes last entry.'
|
|
567
639
|
arg_name 'ENTRY'
|
|
568
640
|
command %i[done did] do |c|
|
|
641
|
+
c.example 'doing done', desc: 'Tag the last entry @done'
|
|
642
|
+
c.example 'doing done I already finished this', desc: 'Add a new entry and immediately mark it @done'
|
|
643
|
+
c.example 'doing done --back 30m This took me half an hour', desc: 'Add an entry with a start date 30 minutes ago and a @done date of right now'
|
|
644
|
+
c.example 'doing done --at 3pm --took 1h Started and finished this afternoon', desc: 'Add an entry with a @done date of 3pm and a start date of 2pm (3pm - 1h)'
|
|
645
|
+
|
|
569
646
|
c.desc 'Remove @done tag'
|
|
570
647
|
c.switch %i[r remove], negatable: false, default_value: false
|
|
571
648
|
|
|
@@ -755,6 +832,9 @@ desc 'End last X entries with no time tracked'
|
|
|
755
832
|
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`.'
|
|
756
833
|
arg_name 'COUNT'
|
|
757
834
|
command :cancel do |c|
|
|
835
|
+
c.example 'doing cancel', desc: 'Cancel the last entry'
|
|
836
|
+
c.example 'doing cancel --tag project1 -u 5', desc: 'Cancel the last 5 unfinished entries containing @project1'
|
|
837
|
+
|
|
758
838
|
c.desc 'Archive entries'
|
|
759
839
|
c.switch %i[a archive], negatable: false, default_value: false
|
|
760
840
|
|
|
@@ -770,6 +850,23 @@ command :cancel do |c|
|
|
|
770
850
|
c.arg_name 'BOOLEAN'
|
|
771
851
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
772
852
|
|
|
853
|
+
c.desc 'Cancel the last X entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("\'query")'
|
|
854
|
+
c.arg_name 'QUERY'
|
|
855
|
+
c.flag [:search]
|
|
856
|
+
|
|
857
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
858
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
859
|
+
|
|
860
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
861
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
862
|
+
|
|
863
|
+
c.desc 'Finish items that *don\'t* match search/tag filters'
|
|
864
|
+
c.switch [:not], default_value: false, negatable: false
|
|
865
|
+
|
|
866
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
867
|
+
c.arg_name 'TYPE'
|
|
868
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
869
|
+
|
|
773
870
|
c.desc 'Cancel last entry (or entries) not already marked @done'
|
|
774
871
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
|
775
872
|
|
|
@@ -799,17 +896,28 @@ command :cancel do |c|
|
|
|
799
896
|
count = args[0] ? args[0].to_i : 1
|
|
800
897
|
end
|
|
801
898
|
|
|
899
|
+
search = nil
|
|
900
|
+
|
|
901
|
+
if options[:search]
|
|
902
|
+
search = options[:search]
|
|
903
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
904
|
+
end
|
|
905
|
+
|
|
802
906
|
opts = {
|
|
803
907
|
archive: options[:a],
|
|
908
|
+
case: options[:case].normalize_case,
|
|
804
909
|
count: count,
|
|
805
910
|
date: false,
|
|
911
|
+
fuzzy: options[:fuzzy],
|
|
912
|
+
interactive: options[:interactive],
|
|
913
|
+
not: options[:not],
|
|
914
|
+
search: search,
|
|
806
915
|
section: section,
|
|
807
916
|
sequential: false,
|
|
808
917
|
tag: tags,
|
|
809
918
|
tag_bool: options[:bool].normalize_bool,
|
|
810
919
|
tags: ['done'],
|
|
811
|
-
unfinished: options[:unfinished]
|
|
812
|
-
interactive: options[:interactive]
|
|
920
|
+
unfinished: options[:unfinished]
|
|
813
921
|
}
|
|
814
922
|
|
|
815
923
|
wwid.tag_last(opts)
|
|
@@ -820,6 +928,10 @@ desc 'Mark last X entries as @done'
|
|
|
820
928
|
long_desc 'Marks the last X entries with a @done tag and current date. Does not alter already completed entries.'
|
|
821
929
|
arg_name 'COUNT'
|
|
822
930
|
command :finish do |c|
|
|
931
|
+
c.example 'doing finish', desc: 'Mark the last entry @done'
|
|
932
|
+
c.example 'doing finish --auto --section Later 10', desc: 'Add @done to any unfinished entries in the last 10 in Later, setting the finish time based on the start time of the task after it'
|
|
933
|
+
c.example 'doing finish --search "a specific entry" --at "yesterday 3pm"', desc: 'Search for an entry containing string and set its @done time to yesterday at 3pm'
|
|
934
|
+
|
|
823
935
|
c.desc 'Include date'
|
|
824
936
|
c.switch [:date], negatable: true, default_value: true
|
|
825
937
|
|
|
@@ -844,6 +956,19 @@ command :finish do |c|
|
|
|
844
956
|
c.arg_name 'QUERY'
|
|
845
957
|
c.flag [:search]
|
|
846
958
|
|
|
959
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
960
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
961
|
+
|
|
962
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
963
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
964
|
+
|
|
965
|
+
c.desc 'Finish items that *don\'t* match search/tag filters'
|
|
966
|
+
c.switch [:not], default_value: false, negatable: false
|
|
967
|
+
|
|
968
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
969
|
+
c.arg_name 'TYPE'
|
|
970
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
971
|
+
|
|
847
972
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
|
848
973
|
c.arg_name 'BOOLEAN'
|
|
849
974
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -912,20 +1037,30 @@ command :finish do |c|
|
|
|
912
1037
|
count = args[0] ? args[0].to_i : 1
|
|
913
1038
|
end
|
|
914
1039
|
|
|
1040
|
+
search = nil
|
|
1041
|
+
|
|
1042
|
+
if options[:search]
|
|
1043
|
+
search = options[:search]
|
|
1044
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1045
|
+
end
|
|
1046
|
+
|
|
915
1047
|
opts = {
|
|
916
1048
|
archive: options[:archive],
|
|
917
1049
|
back: date,
|
|
1050
|
+
case: options[:case].normalize_case,
|
|
918
1051
|
count: count,
|
|
919
1052
|
date: options[:date],
|
|
920
|
-
|
|
1053
|
+
fuzzy: options[:fuzzy],
|
|
1054
|
+
interactive: options[:interactive],
|
|
1055
|
+
not: options[:not],
|
|
1056
|
+
remove: options[:remove],
|
|
1057
|
+
search: search,
|
|
921
1058
|
section: options[:section],
|
|
922
1059
|
sequential: options[:auto],
|
|
923
1060
|
tag: tags,
|
|
924
1061
|
tag_bool: options[:bool].normalize_bool,
|
|
925
1062
|
tags: ['done'],
|
|
926
|
-
unfinished: options[:unfinished]
|
|
927
|
-
remove: options[:remove],
|
|
928
|
-
interactive: options[:interactive]
|
|
1063
|
+
unfinished: options[:unfinished]
|
|
929
1064
|
}
|
|
930
1065
|
|
|
931
1066
|
wwid.tag_last(opts)
|
|
@@ -951,6 +1086,19 @@ command %i[again resume] do |c|
|
|
|
951
1086
|
c.arg_name 'QUERY'
|
|
952
1087
|
c.flag [:search]
|
|
953
1088
|
|
|
1089
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1090
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1091
|
+
|
|
1092
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
1093
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
1094
|
+
|
|
1095
|
+
c.desc 'Resume items that *don\'t* match search/tag filters'
|
|
1096
|
+
c.switch [:not], default_value: false, negatable: false
|
|
1097
|
+
|
|
1098
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
1099
|
+
c.arg_name 'TYPE'
|
|
1100
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
1101
|
+
|
|
954
1102
|
c.desc 'Boolean used to combine multiple tags'
|
|
955
1103
|
c.arg_name 'BOOLEAN'
|
|
956
1104
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -967,7 +1115,17 @@ command %i[again resume] do |c|
|
|
|
967
1115
|
|
|
968
1116
|
c.action do |_global_options, options, _args|
|
|
969
1117
|
tags = options[:tag].nil? ? [] : options[:tag].to_tags
|
|
970
|
-
|
|
1118
|
+
|
|
1119
|
+
options[:case] = options[:case].normalize_case
|
|
1120
|
+
|
|
1121
|
+
if options[:search]
|
|
1122
|
+
search = options[:search]
|
|
1123
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1124
|
+
options[:search] = search
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1127
|
+
opts = options.dup
|
|
1128
|
+
|
|
971
1129
|
opts[:tag] = tags
|
|
972
1130
|
opts[:tag_bool] = options[:bool].normalize_bool
|
|
973
1131
|
opts[:interactive] = options[:interactive]
|
|
@@ -1037,6 +1195,19 @@ command :tag do |c|
|
|
|
1037
1195
|
c.arg_name 'QUERY'
|
|
1038
1196
|
c.flag [:search]
|
|
1039
1197
|
|
|
1198
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1199
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1200
|
+
|
|
1201
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
1202
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
1203
|
+
|
|
1204
|
+
c.desc 'Tag items that *don\'t* match search/tag filters'
|
|
1205
|
+
c.switch [:not], default_value: false, negatable: false
|
|
1206
|
+
|
|
1207
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
1208
|
+
c.arg_name 'TYPE'
|
|
1209
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
1210
|
+
|
|
1040
1211
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
|
1041
1212
|
c.arg_name 'BOOLEAN'
|
|
1042
1213
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -1081,6 +1252,13 @@ command :tag do |c|
|
|
|
1081
1252
|
count = options[:count].to_i
|
|
1082
1253
|
end
|
|
1083
1254
|
|
|
1255
|
+
options[:case] = options[:case].normalize_case
|
|
1256
|
+
|
|
1257
|
+
if options[:search]
|
|
1258
|
+
search = options[:search]
|
|
1259
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1260
|
+
options[:search] = search
|
|
1261
|
+
end
|
|
1084
1262
|
|
|
1085
1263
|
if count.zero? && !options[:force]
|
|
1086
1264
|
if options[:search]
|
|
@@ -1104,7 +1282,7 @@ command :tag do |c|
|
|
|
1104
1282
|
|
|
1105
1283
|
res = wwid.yn(question, default_response: false)
|
|
1106
1284
|
|
|
1107
|
-
|
|
1285
|
+
raise UserCancelled unless res
|
|
1108
1286
|
end
|
|
1109
1287
|
|
|
1110
1288
|
options[:count] = count
|
|
@@ -1152,6 +1330,19 @@ command [:mark, :flag] do |c|
|
|
|
1152
1330
|
c.arg_name 'QUERY'
|
|
1153
1331
|
c.flag [:search]
|
|
1154
1332
|
|
|
1333
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1334
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1335
|
+
|
|
1336
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
1337
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
1338
|
+
|
|
1339
|
+
c.desc 'Flag items that *don\'t* match search/tag/date filters'
|
|
1340
|
+
c.switch [:not], default_value: false, negatable: false
|
|
1341
|
+
|
|
1342
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
1343
|
+
c.arg_name 'TYPE'
|
|
1344
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
1345
|
+
|
|
1155
1346
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
|
1156
1347
|
c.arg_name 'BOOLEAN'
|
|
1157
1348
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
|
@@ -1183,6 +1374,14 @@ command [:mark, :flag] do |c|
|
|
|
1183
1374
|
count = options[:count].to_i
|
|
1184
1375
|
end
|
|
1185
1376
|
|
|
1377
|
+
options[:case] = options[:case].normalize_case
|
|
1378
|
+
|
|
1379
|
+
if options[:search]
|
|
1380
|
+
search = options[:search]
|
|
1381
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1382
|
+
options[:search] = search
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1186
1385
|
if count.zero? && !options[:force]
|
|
1187
1386
|
if options[:search]
|
|
1188
1387
|
section_q = ' matching your search terms'
|
|
@@ -1226,7 +1425,9 @@ command :show do |c|
|
|
|
1226
1425
|
c.example 'doing show Currently', desc: 'Show entries in the Currently section'
|
|
1227
1426
|
c.example 'doing show @project1', desc: 'Show entries tagged @project1'
|
|
1228
1427
|
c.example 'doing show Later @doing', desc: 'Show entries from the Later section tagged @doing'
|
|
1229
|
-
c.example 'doing show
|
|
1428
|
+
c.example 'doing show @oracle @writing --bool and', desc: 'Show entries tagged both @oracle and @writing'
|
|
1429
|
+
c.example 'doing show Currently @devo --bool not', desc: 'Show entries in Currently NOT tagged @devo'
|
|
1430
|
+
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.'
|
|
1230
1431
|
c.example 'doing show --interactive Later @doing', desc: 'Create a menu from entries from the Later section tagged @doing to perform batch actions'
|
|
1231
1432
|
|
|
1232
1433
|
c.desc 'Tag filter, combine multiple tags with a comma. Added for compatibility with other commands.'
|
|
@@ -1257,6 +1458,19 @@ command :show do |c|
|
|
|
1257
1458
|
c.arg_name 'QUERY'
|
|
1258
1459
|
c.flag [:search]
|
|
1259
1460
|
|
|
1461
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1462
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1463
|
+
|
|
1464
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
1465
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
1466
|
+
|
|
1467
|
+
c.desc 'Show items that *don\'t* match search/tag/date filters'
|
|
1468
|
+
c.switch [:not], default_value: false, negatable: false
|
|
1469
|
+
|
|
1470
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
1471
|
+
c.arg_name 'TYPE'
|
|
1472
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
1473
|
+
|
|
1260
1474
|
c.desc 'Sort order (asc/desc)'
|
|
1261
1475
|
c.arg_name 'ORDER'
|
|
1262
1476
|
c.flag %i[s sort], must_match: REGEX_SORT_ORDER, default_value: 'asc'
|
|
@@ -1361,6 +1575,14 @@ command :show do |c|
|
|
|
1361
1575
|
|
|
1362
1576
|
tags_color = settings.key?('tags_color') ? settings['tags_color'] : nil
|
|
1363
1577
|
|
|
1578
|
+
options[:case] = options[:case].normalize_case
|
|
1579
|
+
|
|
1580
|
+
if options[:search]
|
|
1581
|
+
search = options[:search]
|
|
1582
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1583
|
+
options[:search] = search
|
|
1584
|
+
end
|
|
1585
|
+
|
|
1364
1586
|
opt = options.dup
|
|
1365
1587
|
|
|
1366
1588
|
opt[:sort_tags] = options[:tag_sort] =~ /^n/i
|
|
@@ -1423,6 +1645,19 @@ command %i[grep search] do |c|
|
|
|
1423
1645
|
c.desc 'Only show items with recorded time intervals'
|
|
1424
1646
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
1425
1647
|
|
|
1648
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1649
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1650
|
+
|
|
1651
|
+
c.desc 'Force exact string matching (case sensitive)'
|
|
1652
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
1653
|
+
|
|
1654
|
+
c.desc 'Show items that *don\'t* match search string'
|
|
1655
|
+
c.switch [:not], default_value: false, negatable: false
|
|
1656
|
+
|
|
1657
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
1658
|
+
c.arg_name 'TYPE'
|
|
1659
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
1660
|
+
|
|
1426
1661
|
c.desc 'Display an interactive menu of results to perform further operations'
|
|
1427
1662
|
c.switch %i[i interactive], default_value: false, negatable: false
|
|
1428
1663
|
|
|
@@ -1433,10 +1668,15 @@ command %i[grep search] do |c|
|
|
|
1433
1668
|
|
|
1434
1669
|
section = wwid.guess_section(options[:section]) if options[:section]
|
|
1435
1670
|
|
|
1671
|
+
options[:case] = options[:case].normalize_case
|
|
1672
|
+
|
|
1673
|
+
search = args.join(' ')
|
|
1674
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
1675
|
+
|
|
1436
1676
|
options[:times] = true if options[:totals]
|
|
1437
1677
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
|
1438
1678
|
options[:highlight] = true
|
|
1439
|
-
options[:search] =
|
|
1679
|
+
options[:search] = search
|
|
1440
1680
|
options[:section] = section
|
|
1441
1681
|
options[:tags_color] = tags_color
|
|
1442
1682
|
|
|
@@ -1754,6 +1994,19 @@ command :last do |c|
|
|
|
1754
1994
|
c.arg_name 'QUERY'
|
|
1755
1995
|
c.flag [:search]
|
|
1756
1996
|
|
|
1997
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
1998
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
1999
|
+
|
|
2000
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
2001
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
2002
|
+
|
|
2003
|
+
c.desc 'Show items that *don\'t* match search string or tag filter'
|
|
2004
|
+
c.switch [:not], default_value: false, negatable: false
|
|
2005
|
+
|
|
2006
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
2007
|
+
c.arg_name 'TYPE'
|
|
2008
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
2009
|
+
|
|
1757
2010
|
c.action do |global_options, options, _args|
|
|
1758
2011
|
raise InvalidArgument, '--tag and --search can not be used together' if options[:tag] && options[:search]
|
|
1759
2012
|
|
|
@@ -1772,11 +2025,20 @@ command :last do |c|
|
|
|
1772
2025
|
|
|
1773
2026
|
end
|
|
1774
2027
|
|
|
2028
|
+
options[:case] = options[:case].normalize_case
|
|
2029
|
+
|
|
2030
|
+
search = nil
|
|
2031
|
+
|
|
2032
|
+
if options[:search]
|
|
2033
|
+
search = options[:search]
|
|
2034
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
2035
|
+
end
|
|
2036
|
+
|
|
1775
2037
|
if options[:editor]
|
|
1776
|
-
wwid.edit_last(section: options[:s], options: { search: options[:
|
|
2038
|
+
wwid.edit_last(section: options[:s], options: { search: search, fuzzy: options[:fuzzy], case: options[:case], tag: tags, tag_bool: options[:bool], not: options[:not] })
|
|
1777
2039
|
else
|
|
1778
2040
|
Doing::Pager::page wwid.last(times: true, section: options[:s],
|
|
1779
|
-
options: { search: options[:
|
|
2041
|
+
options: { search: search, fuzzy: options[:fuzzy], case: options[:case], negate: options[:not], tag: tags, tag_bool: options[:bool] }).strip
|
|
1780
2042
|
end
|
|
1781
2043
|
end
|
|
1782
2044
|
end
|
|
@@ -1934,6 +2196,19 @@ command :view do |c|
|
|
|
1934
2196
|
c.arg_name 'QUERY'
|
|
1935
2197
|
c.flag [:search]
|
|
1936
2198
|
|
|
2199
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
2200
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
2201
|
+
|
|
2202
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
2203
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
2204
|
+
|
|
2205
|
+
c.desc 'Show items that *don\'t* match search string'
|
|
2206
|
+
c.switch [:not], default_value: false, negatable: false
|
|
2207
|
+
|
|
2208
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
2209
|
+
c.arg_name 'TYPE'
|
|
2210
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
2211
|
+
|
|
1937
2212
|
c.desc 'Sort tags by (name|time)'
|
|
1938
2213
|
c.arg_name 'KEY'
|
|
1939
2214
|
c.flag [:tag_sort], must_match: /^(?:name|time)$/i
|
|
@@ -2065,7 +2340,17 @@ command :view do |c|
|
|
|
2065
2340
|
dates = [start, finish]
|
|
2066
2341
|
end
|
|
2067
2342
|
|
|
2068
|
-
|
|
2343
|
+
options[:case] = options[:case].normalize_case
|
|
2344
|
+
|
|
2345
|
+
search = nil
|
|
2346
|
+
|
|
2347
|
+
if options[:search]
|
|
2348
|
+
search = options[:search]
|
|
2349
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
2350
|
+
end
|
|
2351
|
+
|
|
2352
|
+
opts = options.dup
|
|
2353
|
+
opts[:search] = search
|
|
2069
2354
|
opts[:output] = output_format
|
|
2070
2355
|
opts[:count] = count
|
|
2071
2356
|
opts[:format] = date_format
|
|
@@ -2138,6 +2423,19 @@ command %i[archive move] do |c|
|
|
|
2138
2423
|
c.arg_name 'QUERY'
|
|
2139
2424
|
c.flag [:search]
|
|
2140
2425
|
|
|
2426
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
2427
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
2428
|
+
|
|
2429
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
2430
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
2431
|
+
|
|
2432
|
+
c.desc 'Show items that *don\'t* match search string'
|
|
2433
|
+
c.switch [:not], default_value: false, negatable: false
|
|
2434
|
+
|
|
2435
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
2436
|
+
c.arg_name 'TYPE'
|
|
2437
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
2438
|
+
|
|
2141
2439
|
c.desc 'Archive entries older than date
|
|
2142
2440
|
(Flexible date format, e.g. 1/27/2021, 2020-07-19, or Monday 3pm)'
|
|
2143
2441
|
c.arg_name 'DATE_STRING'
|
|
@@ -2161,7 +2459,17 @@ command %i[archive move] do |c|
|
|
|
2161
2459
|
|
|
2162
2460
|
tags.concat(options[:tag].to_tags) if options[:tag]
|
|
2163
2461
|
|
|
2164
|
-
|
|
2462
|
+
search = nil
|
|
2463
|
+
|
|
2464
|
+
options[:case] = options[:case].normalize_case
|
|
2465
|
+
|
|
2466
|
+
if options[:search]
|
|
2467
|
+
search = options[:search]
|
|
2468
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
2469
|
+
end
|
|
2470
|
+
|
|
2471
|
+
opts = options.dup
|
|
2472
|
+
opts[:search] = search
|
|
2165
2473
|
opts[:bool] = options[:bool].normalize_bool
|
|
2166
2474
|
opts[:destination] = options[:to]
|
|
2167
2475
|
opts[:tags] = tags
|
|
@@ -2196,6 +2504,19 @@ command :rotate do |c|
|
|
|
2196
2504
|
c.arg_name 'QUERY'
|
|
2197
2505
|
c.flag [:search]
|
|
2198
2506
|
|
|
2507
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
2508
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
2509
|
+
|
|
2510
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
2511
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
2512
|
+
|
|
2513
|
+
c.desc 'Rotate items that *don\'t* match search string or tag filter'
|
|
2514
|
+
c.switch [:not], default_value: false, negatable: false
|
|
2515
|
+
|
|
2516
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
2517
|
+
c.arg_name 'TYPE'
|
|
2518
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
2519
|
+
|
|
2199
2520
|
c.desc 'Rotate entries older than date
|
|
2200
2521
|
(Flexible date format, e.g. 1/27/2021, 2020-07-19, or Monday 3pm)'
|
|
2201
2522
|
c.arg_name 'DATE_STRING'
|
|
@@ -2208,6 +2529,16 @@ command :rotate do |c|
|
|
|
2208
2529
|
|
|
2209
2530
|
options[:bool] = options[:bool].normalize_bool
|
|
2210
2531
|
|
|
2532
|
+
options[:case] = options[:case].normalize_case
|
|
2533
|
+
|
|
2534
|
+
search = nil
|
|
2535
|
+
|
|
2536
|
+
if options[:search]
|
|
2537
|
+
search = options[:search]
|
|
2538
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
|
2539
|
+
options[:search] = search
|
|
2540
|
+
end
|
|
2541
|
+
|
|
2211
2542
|
wwid.rotate(options)
|
|
2212
2543
|
end
|
|
2213
2544
|
end
|
|
@@ -2311,7 +2642,7 @@ command :config do |c|
|
|
|
2311
2642
|
when /^j/
|
|
2312
2643
|
JSON.pretty_generate(cfg)
|
|
2313
2644
|
when /^r/
|
|
2314
|
-
cfg
|
|
2645
|
+
cfg.map {|k, v| v.to_s }
|
|
2315
2646
|
else
|
|
2316
2647
|
YAML.dump(cfg)
|
|
2317
2648
|
end
|
|
@@ -2396,6 +2727,19 @@ command :import do |c|
|
|
|
2396
2727
|
c.arg_name 'QUERY'
|
|
2397
2728
|
c.flag [:search]
|
|
2398
2729
|
|
|
2730
|
+
c.desc 'Use alternative fuzzy matching for search string'
|
|
2731
|
+
c.switch [:fuzzy], default_value: false, negatable: false
|
|
2732
|
+
|
|
2733
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
|
2734
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
|
2735
|
+
|
|
2736
|
+
c.desc 'Import items that *don\'t* match search/tag/date filters'
|
|
2737
|
+
c.switch [:not], default_value: false, negatable: false
|
|
2738
|
+
|
|
2739
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
|
|
2740
|
+
c.arg_name 'TYPE'
|
|
2741
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
|
2742
|
+
|
|
2399
2743
|
c.desc 'Only import items with recorded time intervals'
|
|
2400
2744
|
c.switch [:only_timed], default_value: false, negatable: false
|
|
2401
2745
|
|
|
@@ -2453,6 +2797,8 @@ command :import do |c|
|
|
|
2453
2797
|
dates = [start, finish]
|
|
2454
2798
|
end
|
|
2455
2799
|
|
|
2800
|
+
options[:case] = options[:case].normalize_case
|
|
2801
|
+
|
|
2456
2802
|
if options[:type] =~ Doing::Plugins.plugin_regex(type: :import)
|
|
2457
2803
|
options[:no_overlap] = !options[:overlap]
|
|
2458
2804
|
options[:date_filter] = dates
|