doing 2.0.8.pre → 2.0.9.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -20
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/bin/doing +145 -12
- data/doing.rdoc +143 -10
- data/lib/doing/item.rb +7 -2
- data/lib/doing/string.rb +22 -0
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +14 -9
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f63df319758e6575ab75de3305ed9e44ac272d54b026e6873397970780115cca
|
4
|
+
data.tar.gz: e770a9679824aae9582ca1cedb23e783d0bb1070b1c740d7ce662d912124006d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10bcf3f91db5636bb4133323b09a22f0978d3955e0e564931edef9cf8b9416aa4f7fa0480588dd85b95eab7cdb1f8952a843dce755bed6fc5dfd108ee60ea8ce
|
7
|
+
data.tar.gz: 23a73fa1f03cb28afaca764296a52140a6f7eb772add3db3220b255c51831cb5c2eb97a9f103000788fd06998bf8389dcac62618880a84fadfa5b209e1c718da
|
data/CHANGELOG.md
CHANGED
@@ -1,22 +1,14 @@
|
|
1
|
-
### 2.0.
|
2
|
-
|
3
|
-
#### NEW
|
4
|
-
|
5
|
-
- Add `--exact` flag to all commands with `--search` flag to force exact matching without requiring single quote prefix
|
6
|
-
- Add `--not` flag to all commands with filters (--tag, --search, --before, etc.) to negate the filter and return entries NOT matched
|
7
|
-
|
8
|
-
### 2.0.7.pre
|
9
|
-
|
10
|
-
#### FIXED
|
11
|
-
|
12
|
-
- Zsh completion not outputting results
|
13
|
-
|
14
|
-
### 2.0.6.pre
|
1
|
+
### 2.0.9.pre
|
15
2
|
|
16
3
|
#### NEW
|
17
4
|
|
5
|
+
- Add 'timer_format' config with 'human' option for tag totals
|
18
6
|
- If `doing view` and `doing show` are confused, offer option to run the other command
|
19
7
|
- `doing completion` to generate shell completion scripts for zsh, bash, and fish
|
8
|
+
- --search and --not for cancel command
|
9
|
+
- --case flag for commands with --search. Can be (c)ase-sensitive, (i)nsensitive, or (s)mart (default smart, case insensitive unless search string contains uppercase letters)
|
10
|
+
- Add `--exact` flag to all commands with `--search` flag to force exact matching without requiring single quote prefix
|
11
|
+
- Add `--not` flag to all commands with filters (--tag, --search, --before, etc.) to negate the filter and return entries NOT matched
|
20
12
|
|
21
13
|
#### IMPROVED
|
22
14
|
|
@@ -27,16 +19,11 @@
|
|
27
19
|
|
28
20
|
#### FIXED
|
29
21
|
|
22
|
+
- Zsh completion not outputting results
|
30
23
|
- Remove `--[no]` from non-negatable options
|
31
24
|
- `doing plugins -t export -c` not outputting columns
|
32
25
|
- View config not respecting tag_order setting
|
33
26
|
|
34
|
-
### 2.0.5.pre
|
35
|
-
|
36
|
-
#### NEW
|
37
|
-
|
38
|
-
- Add 'timer_format' config with 'human' option for tag totals
|
39
|
-
|
40
27
|
### 2.0.3.pre
|
41
28
|
|
42
29
|
#### NEW
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ _If you're one of the rare people like me who find this useful, feel free to [bu
|
|
6
6
|
|
7
7
|
<!--README-->
|
8
8
|
|
9
|
-
The current version of `doing` is <!--VER-->2.0.
|
9
|
+
The current version of `doing` is <!--VER-->2.0.8<!--END VER-->.
|
10
10
|
|
11
11
|
Find all of the documentation in the [doing wiki](https://github.com/ttscoff/doing/wiki).
|
12
12
|
|
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
|
@@ -201,6 +204,10 @@ command %i[reset begin] do |c|
|
|
201
204
|
c.desc 'Reset items that *don\'t* match search/tag filters'
|
202
205
|
c.switch [:not], default_value: false, negatable: false
|
203
206
|
|
207
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
208
|
+
c.arg_name 'TYPE'
|
209
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
210
|
+
|
204
211
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
205
212
|
c.arg_name 'BOOLEAN'
|
206
213
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -213,7 +220,9 @@ command %i[reset begin] do |c|
|
|
213
220
|
options[:section] = wwid.guess_section(options[:section]) || options[:section].cap_first
|
214
221
|
end
|
215
222
|
|
216
|
-
options[:
|
223
|
+
options[:bool] = options[:bool].normalize_bool
|
224
|
+
|
225
|
+
options[:case] = options[:case].normalize_case
|
217
226
|
|
218
227
|
if options[:search]
|
219
228
|
search = options[:search]
|
@@ -261,6 +270,11 @@ long_desc %(
|
|
261
270
|
)
|
262
271
|
arg_name 'NOTE_TEXT'
|
263
272
|
command :note do |c|
|
273
|
+
c.example 'doing note', desc: 'Open the last entry in $EDITOR to append a note'
|
274
|
+
c.example 'doing note "Just a quick annotation"', desc: 'Add a quick note to the last entry'
|
275
|
+
c.example 'doing note --tag done "Keeping it real or something"', desc: 'Add a note to the last item tagged @done'
|
276
|
+
c.example 'doing note --search "late night" -e', desc: 'Open $EDITOR to add a note to the last item containing "late night" (fuzzy matched)'
|
277
|
+
|
264
278
|
c.desc 'Section'
|
265
279
|
c.arg_name 'NAME'
|
266
280
|
c.flag %i[s section], default_value: 'All'
|
@@ -285,6 +299,10 @@ command :note do |c|
|
|
285
299
|
c.desc 'Add note to item that *doesn\'t* match search/tag filters'
|
286
300
|
c.switch [:not], default_value: false, negatable: false
|
287
301
|
|
302
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
303
|
+
c.arg_name 'TYPE'
|
304
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
305
|
+
|
288
306
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
289
307
|
c.arg_name 'BOOLEAN'
|
290
308
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -299,6 +317,8 @@ command :note do |c|
|
|
299
317
|
|
300
318
|
options[:tag_bool] = options[:bool].normalize_bool
|
301
319
|
|
320
|
+
options[:case] = options[:case].normalize_case
|
321
|
+
|
302
322
|
if options[:search]
|
303
323
|
search = options[:search]
|
304
324
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -356,6 +376,11 @@ end
|
|
356
376
|
desc 'Finish any running @meanwhile tasks and optionally create a new one'
|
357
377
|
arg_name 'ENTRY'
|
358
378
|
command :meanwhile do |c|
|
379
|
+
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'
|
380
|
+
c.example 'doing meanwhile', desc: 'Finish any open @meanwhile entry'
|
381
|
+
c.example 'doing meanwhile --archive', desc: 'Finish any open @meanwhile entry and archive it'
|
382
|
+
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'
|
383
|
+
|
359
384
|
c.desc 'Section'
|
360
385
|
c.arg_name 'NAME'
|
361
386
|
c.flag %i[s section]
|
@@ -422,12 +447,12 @@ end
|
|
422
447
|
desc 'Output HTML, CSS, and Markdown (ERB) templates for customization'
|
423
448
|
long_desc %(
|
424
449
|
Templates are printed to STDOUT for piping to a file.
|
425
|
-
Save them and use them in the configuration file under
|
426
|
-
|
427
|
-
Example `doing template haml > ~/styles/my_doing.haml`
|
450
|
+
Save them and use them in the configuration file under export_templates.
|
428
451
|
)
|
429
452
|
arg_name 'TYPE', must_match: Doing::Plugins.template_regex
|
430
453
|
command :template do |c|
|
454
|
+
c.example 'doing template haml > ~/styles/my_doing.haml', desc: 'Output the haml template and save it to a file'
|
455
|
+
|
431
456
|
c.desc 'List all available templates'
|
432
457
|
c.switch %i[l list], negatable: false
|
433
458
|
|
@@ -505,6 +530,10 @@ command :select do |c|
|
|
505
530
|
c.desc 'Select items that *don\'t* match search/tag filters'
|
506
531
|
c.switch [:not], default_value: false, negatable: false
|
507
532
|
|
533
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
534
|
+
c.arg_name 'TYPE'
|
535
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
536
|
+
|
508
537
|
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.'
|
509
538
|
c.switch %i[menu], negatable: true, default_value: true
|
510
539
|
|
@@ -542,6 +571,8 @@ command :select do |c|
|
|
542
571
|
|
543
572
|
raise InvalidArgument, '--no-menu requires --query' if !options[:menu] && !options[:query]
|
544
573
|
|
574
|
+
options[:case] = options[:case].normalize_case
|
575
|
+
|
545
576
|
wwid.interactive(options)
|
546
577
|
end
|
547
578
|
end
|
@@ -549,6 +580,9 @@ end
|
|
549
580
|
desc 'Add an item to the Later section'
|
550
581
|
arg_name 'ENTRY'
|
551
582
|
command :later do |c|
|
583
|
+
c.example 'doing later "Something I\'ll think about tomorrow"', desc: 'Add an entry to the Later section'
|
584
|
+
c.example 'doing later -e', desc: 'Open $EDITOR to create an entry and optional note'
|
585
|
+
|
552
586
|
c.desc "Edit entry with #{Doing::Util.default_editor}"
|
553
587
|
c.switch %i[e editor], negatable: false, default_value: false
|
554
588
|
|
@@ -598,6 +632,11 @@ end
|
|
598
632
|
desc 'Add a completed item with @done(date). No argument finishes last entry.'
|
599
633
|
arg_name 'ENTRY'
|
600
634
|
command %i[done did] do |c|
|
635
|
+
c.example 'doing done', desc: 'Tag the last entry @done'
|
636
|
+
c.example 'doing done I already finished this', desc: 'Add a new entry and immediately mark it @done'
|
637
|
+
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'
|
638
|
+
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)'
|
639
|
+
|
601
640
|
c.desc 'Remove @done tag'
|
602
641
|
c.switch %i[r remove], negatable: false, default_value: false
|
603
642
|
|
@@ -787,6 +826,9 @@ desc 'End last X entries with no time tracked'
|
|
787
826
|
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`.'
|
788
827
|
arg_name 'COUNT'
|
789
828
|
command :cancel do |c|
|
829
|
+
c.example 'doing cancel', desc: 'Cancel the last entry'
|
830
|
+
c.example 'doing cancel --tag project1 -u 5', desc: 'Cancel the last 5 unfinished entries containing @project1'
|
831
|
+
|
790
832
|
c.desc 'Archive entries'
|
791
833
|
c.switch %i[a archive], negatable: false, default_value: false
|
792
834
|
|
@@ -802,6 +844,20 @@ command :cancel do |c|
|
|
802
844
|
c.arg_name 'BOOLEAN'
|
803
845
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
804
846
|
|
847
|
+
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")'
|
848
|
+
c.arg_name 'QUERY'
|
849
|
+
c.flag [:search]
|
850
|
+
|
851
|
+
c.desc 'Force exact search string matching (case sensitive)'
|
852
|
+
c.switch %i[x exact], default_value: false, negatable: false
|
853
|
+
|
854
|
+
c.desc 'Finish items that *don\'t* match search/tag filters'
|
855
|
+
c.switch [:not], default_value: false, negatable: false
|
856
|
+
|
857
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
858
|
+
c.arg_name 'TYPE'
|
859
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
860
|
+
|
805
861
|
c.desc 'Cancel last entry (or entries) not already marked @done'
|
806
862
|
c.switch %i[u unfinished], negatable: false, default_value: false
|
807
863
|
|
@@ -831,7 +887,17 @@ command :cancel do |c|
|
|
831
887
|
count = args[0] ? args[0].to_i : 1
|
832
888
|
end
|
833
889
|
|
890
|
+
search = nil
|
891
|
+
|
892
|
+
if options[:search]
|
893
|
+
search = options[:search]
|
894
|
+
search.sub!(/^'?/, "'") if options[:exact]
|
895
|
+
end
|
896
|
+
|
834
897
|
opts = {
|
898
|
+
search: search,
|
899
|
+
case: options[:case].normalize_case,
|
900
|
+
not: options[:not],
|
835
901
|
archive: options[:a],
|
836
902
|
count: count,
|
837
903
|
date: false,
|
@@ -852,6 +918,10 @@ desc 'Mark last X entries as @done'
|
|
852
918
|
long_desc 'Marks the last X entries with a @done tag and current date. Does not alter already completed entries.'
|
853
919
|
arg_name 'COUNT'
|
854
920
|
command :finish do |c|
|
921
|
+
c.example 'doing finish', desc: 'Mark the last entry @done'
|
922
|
+
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'
|
923
|
+
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'
|
924
|
+
|
855
925
|
c.desc 'Include date'
|
856
926
|
c.switch [:date], negatable: true, default_value: true
|
857
927
|
|
@@ -882,6 +952,10 @@ command :finish do |c|
|
|
882
952
|
c.desc 'Finish items that *don\'t* match search/tag filters'
|
883
953
|
c.switch [:not], default_value: false, negatable: false
|
884
954
|
|
955
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
956
|
+
c.arg_name 'TYPE'
|
957
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
958
|
+
|
885
959
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
886
960
|
c.arg_name 'BOOLEAN'
|
887
961
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -963,6 +1037,7 @@ command :finish do |c|
|
|
963
1037
|
count: count,
|
964
1038
|
date: options[:date],
|
965
1039
|
search: search,
|
1040
|
+
case: options[:case].normalize_case,
|
966
1041
|
not: options[:not],
|
967
1042
|
section: options[:section],
|
968
1043
|
sequential: options[:auto],
|
@@ -1003,6 +1078,10 @@ command %i[again resume] do |c|
|
|
1003
1078
|
c.desc 'Resume items that *don\'t* match search/tag filters'
|
1004
1079
|
c.switch [:not], default_value: false, negatable: false
|
1005
1080
|
|
1081
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1082
|
+
c.arg_name 'TYPE'
|
1083
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1084
|
+
|
1006
1085
|
c.desc 'Boolean used to combine multiple tags'
|
1007
1086
|
c.arg_name 'BOOLEAN'
|
1008
1087
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -1020,6 +1099,8 @@ command %i[again resume] do |c|
|
|
1020
1099
|
c.action do |_global_options, options, _args|
|
1021
1100
|
tags = options[:tag].nil? ? [] : options[:tag].to_tags
|
1022
1101
|
|
1102
|
+
options[:case] = options[:case].normalize_case
|
1103
|
+
|
1023
1104
|
if options[:search]
|
1024
1105
|
search = options[:search]
|
1025
1106
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1103,6 +1184,10 @@ command :tag do |c|
|
|
1103
1184
|
c.desc 'Tag items that *don\'t* match search/tag filters'
|
1104
1185
|
c.switch [:not], default_value: false, negatable: false
|
1105
1186
|
|
1187
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1188
|
+
c.arg_name 'TYPE'
|
1189
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1190
|
+
|
1106
1191
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
1107
1192
|
c.arg_name 'BOOLEAN'
|
1108
1193
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -1147,6 +1232,8 @@ command :tag do |c|
|
|
1147
1232
|
count = options[:count].to_i
|
1148
1233
|
end
|
1149
1234
|
|
1235
|
+
options[:case] = options[:case].normalize_case
|
1236
|
+
|
1150
1237
|
if options[:search]
|
1151
1238
|
search = options[:search]
|
1152
1239
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1229,6 +1316,10 @@ command [:mark, :flag] do |c|
|
|
1229
1316
|
c.desc 'Flag items that *don\'t* match search/tag/date filters'
|
1230
1317
|
c.switch [:not], default_value: false, negatable: false
|
1231
1318
|
|
1319
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1320
|
+
c.arg_name 'TYPE'
|
1321
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1322
|
+
|
1232
1323
|
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
1233
1324
|
c.arg_name 'BOOLEAN'
|
1234
1325
|
c.flag [:bool], must_match: REGEX_BOOL, default_value: 'AND'
|
@@ -1260,6 +1351,8 @@ command [:mark, :flag] do |c|
|
|
1260
1351
|
count = options[:count].to_i
|
1261
1352
|
end
|
1262
1353
|
|
1354
|
+
options[:case] = options[:case].normalize_case
|
1355
|
+
|
1263
1356
|
if options[:search]
|
1264
1357
|
search = options[:search]
|
1265
1358
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1346,6 +1439,10 @@ command :show do |c|
|
|
1346
1439
|
c.desc 'Show items that *don\'t* match search/tag/date filters'
|
1347
1440
|
c.switch [:not], default_value: false, negatable: false
|
1348
1441
|
|
1442
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1443
|
+
c.arg_name 'TYPE'
|
1444
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1445
|
+
|
1349
1446
|
c.desc 'Sort order (asc/desc)'
|
1350
1447
|
c.arg_name 'ORDER'
|
1351
1448
|
c.flag %i[s sort], must_match: REGEX_SORT_ORDER, default_value: 'asc'
|
@@ -1450,6 +1547,8 @@ command :show do |c|
|
|
1450
1547
|
|
1451
1548
|
tags_color = settings.key?('tags_color') ? settings['tags_color'] : nil
|
1452
1549
|
|
1550
|
+
options[:case] = options[:case].normalize_case
|
1551
|
+
|
1453
1552
|
if options[:search]
|
1454
1553
|
search = options[:search]
|
1455
1554
|
search.sub!(/^'?/, "'") if options[:exact]
|
@@ -1521,12 +1620,13 @@ command %i[grep search] do |c|
|
|
1521
1620
|
c.desc 'Force exact string matching (case sensitive)'
|
1522
1621
|
c.switch %i[x exact], default_value: false, negatable: false
|
1523
1622
|
|
1524
|
-
c.desc 'Force case sensitive matching'
|
1525
|
-
c.switch %i[case]
|
1526
|
-
|
1527
1623
|
c.desc 'Show items that *don\'t* match search string'
|
1528
1624
|
c.switch [:not], default_value: false, negatable: false
|
1529
1625
|
|
1626
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1627
|
+
c.arg_name 'TYPE'
|
1628
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1629
|
+
|
1530
1630
|
c.desc 'Display an interactive menu of results to perform further operations'
|
1531
1631
|
c.switch %i[i interactive], default_value: false, negatable: false
|
1532
1632
|
|
@@ -1536,6 +1636,9 @@ command %i[grep search] do |c|
|
|
1536
1636
|
tags_color = settings.key?('tags_color') ? settings['tags_color'] : nil
|
1537
1637
|
|
1538
1638
|
section = wwid.guess_section(options[:section]) if options[:section]
|
1639
|
+
|
1640
|
+
options[:case] = options[:case].normalize_case
|
1641
|
+
|
1539
1642
|
search = args.join(' ')
|
1540
1643
|
search.sub!(/^'?/, "'") if options[:exact]
|
1541
1644
|
|
@@ -1866,6 +1969,10 @@ command :last do |c|
|
|
1866
1969
|
c.desc 'Show items that *don\'t* match search string or tag filter'
|
1867
1970
|
c.switch [:not], default_value: false, negatable: false
|
1868
1971
|
|
1972
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
1973
|
+
c.arg_name 'TYPE'
|
1974
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
1975
|
+
|
1869
1976
|
c.action do |global_options, options, _args|
|
1870
1977
|
raise InvalidArgument, '--tag and --search can not be used together' if options[:tag] && options[:search]
|
1871
1978
|
|
@@ -1884,6 +1991,8 @@ command :last do |c|
|
|
1884
1991
|
|
1885
1992
|
end
|
1886
1993
|
|
1994
|
+
options[:case] = options[:case].normalize_case
|
1995
|
+
|
1887
1996
|
search = nil
|
1888
1997
|
|
1889
1998
|
if options[:search]
|
@@ -1892,10 +2001,10 @@ command :last do |c|
|
|
1892
2001
|
end
|
1893
2002
|
|
1894
2003
|
if options[:editor]
|
1895
|
-
wwid.edit_last(section: options[:s], options: { search: search, tag: tags, tag_bool: options[:bool], not: options[:not] })
|
2004
|
+
wwid.edit_last(section: options[:s], options: { search: search, case: options[:case], tag: tags, tag_bool: options[:bool], not: options[:not] })
|
1896
2005
|
else
|
1897
2006
|
Doing::Pager::page wwid.last(times: true, section: options[:s],
|
1898
|
-
options: { search: search, negate: options[:not], tag: tags, tag_bool: options[:bool] }).strip
|
2007
|
+
options: { search: search, case: options[:case], negate: options[:not], tag: tags, tag_bool: options[:bool] }).strip
|
1899
2008
|
end
|
1900
2009
|
end
|
1901
2010
|
end
|
@@ -2059,6 +2168,10 @@ command :view do |c|
|
|
2059
2168
|
c.desc 'Show items that *don\'t* match search string'
|
2060
2169
|
c.switch [:not], default_value: false, negatable: false
|
2061
2170
|
|
2171
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
2172
|
+
c.arg_name 'TYPE'
|
2173
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
2174
|
+
|
2062
2175
|
c.desc 'Sort tags by (name|time)'
|
2063
2176
|
c.arg_name 'KEY'
|
2064
2177
|
c.flag [:tag_sort], must_match: /^(?:name|time)$/i
|
@@ -2190,6 +2303,8 @@ command :view do |c|
|
|
2190
2303
|
dates = [start, finish]
|
2191
2304
|
end
|
2192
2305
|
|
2306
|
+
options[:case] = options[:case].normalize_case
|
2307
|
+
|
2193
2308
|
search = nil
|
2194
2309
|
|
2195
2310
|
if options[:search]
|
@@ -2197,7 +2312,7 @@ command :view do |c|
|
|
2197
2312
|
search.sub!(/^'?/, "'") if options[:exact]
|
2198
2313
|
end
|
2199
2314
|
|
2200
|
-
opts = options
|
2315
|
+
opts = options.dup
|
2201
2316
|
opts[:search] = search
|
2202
2317
|
opts[:output] = output_format
|
2203
2318
|
opts[:count] = count
|
@@ -2277,6 +2392,10 @@ command %i[archive move] do |c|
|
|
2277
2392
|
c.desc 'Show items that *don\'t* match search string'
|
2278
2393
|
c.switch [:not], default_value: false, negatable: false
|
2279
2394
|
|
2395
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
2396
|
+
c.arg_name 'TYPE'
|
2397
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
2398
|
+
|
2280
2399
|
c.desc 'Archive entries older than date
|
2281
2400
|
(Flexible date format, e.g. 1/27/2021, 2020-07-19, or Monday 3pm)'
|
2282
2401
|
c.arg_name 'DATE_STRING'
|
@@ -2302,12 +2421,14 @@ command %i[archive move] do |c|
|
|
2302
2421
|
|
2303
2422
|
search = nil
|
2304
2423
|
|
2424
|
+
options[:case] = options[:case].normalize_case
|
2425
|
+
|
2305
2426
|
if options[:search]
|
2306
2427
|
search = options[:search]
|
2307
2428
|
search.sub!(/^'?/, "'") if options[:exact]
|
2308
2429
|
end
|
2309
2430
|
|
2310
|
-
opts = options
|
2431
|
+
opts = options.dup
|
2311
2432
|
opts[:search] = search
|
2312
2433
|
opts[:bool] = options[:bool].normalize_bool
|
2313
2434
|
opts[:destination] = options[:to]
|
@@ -2349,6 +2470,10 @@ command :rotate do |c|
|
|
2349
2470
|
c.desc 'Rotate items that *don\'t* match search string or tag filter'
|
2350
2471
|
c.switch [:not], default_value: false, negatable: false
|
2351
2472
|
|
2473
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
2474
|
+
c.arg_name 'TYPE'
|
2475
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
2476
|
+
|
2352
2477
|
c.desc 'Rotate entries older than date
|
2353
2478
|
(Flexible date format, e.g. 1/27/2021, 2020-07-19, or Monday 3pm)'
|
2354
2479
|
c.arg_name 'DATE_STRING'
|
@@ -2361,6 +2486,8 @@ command :rotate do |c|
|
|
2361
2486
|
|
2362
2487
|
options[:bool] = options[:bool].normalize_bool
|
2363
2488
|
|
2489
|
+
options[:case] = options[:case].normalize_case
|
2490
|
+
|
2364
2491
|
search = nil
|
2365
2492
|
|
2366
2493
|
if options[:search]
|
@@ -2563,6 +2690,10 @@ command :import do |c|
|
|
2563
2690
|
c.desc 'Import items that *don\'t* match search/tag/date filters'
|
2564
2691
|
c.switch [:not], default_value: false, negatable: false
|
2565
2692
|
|
2693
|
+
c.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]'
|
2694
|
+
c.arg_name 'TYPE'
|
2695
|
+
c.flag [:case], must_match: /^[csi]/, default_value: 'smart'
|
2696
|
+
|
2566
2697
|
c.desc 'Only import items with recorded time intervals'
|
2567
2698
|
c.switch [:only_timed], default_value: false, negatable: false
|
2568
2699
|
|
@@ -2620,6 +2751,8 @@ command :import do |c|
|
|
2620
2751
|
dates = [start, finish]
|
2621
2752
|
end
|
2622
2753
|
|
2754
|
+
options[:case] = options[:case].normalize_case
|
2755
|
+
|
2623
2756
|
if options[:type] =~ Doing::Plugins.plugin_regex(type: :import)
|
2624
2757
|
options[:no_overlap] = !options[:overlap]
|
2625
2758
|
options[:date_filter] = dates
|
data/doing.rdoc
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
== doing - A CLI for a What Was I Doing system
|
2
2
|
|
3
|
-
Doing uses a TaskPaper-like formatting to keep a plain text
|
3
|
+
Doing uses a TaskPaper-like formatting to keep a plain text
|
4
|
+
record of what you've been doing, complete with tag-based time tracking. The
|
5
|
+
command line tool allows you to add entries, annotate with tags and notes, and
|
6
|
+
view your entries with myriad options, with a focus on a "natural" language syntax.
|
4
7
|
|
5
|
-
v2.0.
|
8
|
+
v2.0.9.pre
|
6
9
|
|
7
10
|
=== Global Options
|
8
11
|
=== --config_file arg
|
@@ -87,6 +90,14 @@ Boolean used to combine multiple tags
|
|
87
90
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
88
91
|
|
89
92
|
|
93
|
+
===== --case TYPE
|
94
|
+
|
95
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
96
|
+
|
97
|
+
[Default Value] smart
|
98
|
+
[Must Match] (?-mix:^[csi])
|
99
|
+
|
100
|
+
|
90
101
|
===== --in SECTION_NAME
|
91
102
|
|
92
103
|
Add new entry to section (default: same section as repeated entry)
|
@@ -167,6 +178,14 @@ Tag boolean (AND|OR|NOT)
|
|
167
178
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
168
179
|
|
169
180
|
|
181
|
+
===== --case TYPE
|
182
|
+
|
183
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
184
|
+
|
185
|
+
[Default Value] smart
|
186
|
+
[Must Match] (?-mix:^[csi])
|
187
|
+
|
188
|
+
|
170
189
|
===== -k|--keep X
|
171
190
|
|
172
191
|
How many items to keep (ignored if archiving by tag or search)
|
@@ -284,6 +303,14 @@ Boolean (AND|OR|NOT) with which to combine multiple tag filters
|
|
284
303
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
285
304
|
|
286
305
|
|
306
|
+
===== --case TYPE
|
307
|
+
|
308
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
309
|
+
|
310
|
+
[Default Value] smart
|
311
|
+
[Must Match] (?-mix:^[csi])
|
312
|
+
|
313
|
+
|
287
314
|
===== -s|--section NAME
|
288
315
|
|
289
316
|
Section
|
@@ -291,6 +318,13 @@ Section
|
|
291
318
|
[Default Value] None
|
292
319
|
|
293
320
|
|
321
|
+
===== --search QUERY
|
322
|
+
|
323
|
+
Cancel the last X entries matching search filter, surround with slashes for regex (e.g. "/query.*/"), start with single quote for exact match ("'query")
|
324
|
+
|
325
|
+
[Default Value] None
|
326
|
+
|
327
|
+
|
294
328
|
===== --tag TAG
|
295
329
|
|
296
330
|
Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2)
|
@@ -308,11 +342,21 @@ Select item(s) to cancel from a menu of matching entries
|
|
308
342
|
|
309
343
|
|
310
344
|
|
345
|
+
===== --not
|
346
|
+
Finish items that *don't* match search/tag filters
|
347
|
+
|
348
|
+
|
349
|
+
|
311
350
|
===== -u|--unfinished
|
312
351
|
Cancel last entry (or entries) not already marked @done
|
313
352
|
|
314
353
|
|
315
354
|
|
355
|
+
===== -x|--exact
|
356
|
+
Force exact search string matching (case sensitive)
|
357
|
+
|
358
|
+
|
359
|
+
|
316
360
|
==== Command: <tt>choose </tt>
|
317
361
|
Select a section to display from a menu
|
318
362
|
|
@@ -493,6 +537,14 @@ Boolean (AND|OR|NOT) with which to combine multiple tag filters
|
|
493
537
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
494
538
|
|
495
539
|
|
540
|
+
===== --case TYPE
|
541
|
+
|
542
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
543
|
+
|
544
|
+
[Default Value] smart
|
545
|
+
[Must Match] (?-mix:^[csi])
|
546
|
+
|
547
|
+
|
496
548
|
===== -s|--section NAME
|
497
549
|
|
498
550
|
Section
|
@@ -585,6 +637,14 @@ Constrain search to entries older than date
|
|
585
637
|
[Default Value] None
|
586
638
|
|
587
639
|
|
640
|
+
===== --case TYPE
|
641
|
+
|
642
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
643
|
+
|
644
|
+
[Default Value] smart
|
645
|
+
[Must Match] (?-mix:^[csi])
|
646
|
+
|
647
|
+
|
588
648
|
===== -o|--output FORMAT
|
589
649
|
|
590
650
|
Output to export format (csv|doing|html|markdown|say|taskpaper|template|timeline|wiki)
|
@@ -607,11 +667,6 @@ Sort tags by (name|time)
|
|
607
667
|
[Must Match] (?i-mx:^(?:name|time)$)
|
608
668
|
|
609
669
|
|
610
|
-
===== --[no-]case
|
611
|
-
Force case sensitive matching
|
612
|
-
|
613
|
-
|
614
|
-
|
615
670
|
===== -i|--interactive
|
616
671
|
Display an interactive menu of results to perform further operations
|
617
672
|
|
@@ -671,6 +726,14 @@ Import entries older than date
|
|
671
726
|
[Default Value] None
|
672
727
|
|
673
728
|
|
729
|
+
===== --case TYPE
|
730
|
+
|
731
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
732
|
+
|
733
|
+
[Default Value] smart
|
734
|
+
[Must Match] (?-mix:^[csi])
|
735
|
+
|
736
|
+
|
674
737
|
===== -f|--from DATE_OR_RANGE
|
675
738
|
|
676
739
|
Date range to import. Date range argument should be quoted. Date specifications can be natural language.
|
@@ -753,6 +816,14 @@ Tag boolean
|
|
753
816
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
754
817
|
|
755
818
|
|
819
|
+
===== --case TYPE
|
820
|
+
|
821
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
822
|
+
|
823
|
+
[Default Value] smart
|
824
|
+
[Must Match] (?-mix:^[csi])
|
825
|
+
|
826
|
+
|
756
827
|
===== -s|--section NAME
|
757
828
|
|
758
829
|
Specify a section
|
@@ -834,6 +905,14 @@ How many recent entries to tag (0 for all)
|
|
834
905
|
[Must Match] (?-mix:^\d+$)
|
835
906
|
|
836
907
|
|
908
|
+
===== --case TYPE
|
909
|
+
|
910
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
911
|
+
|
912
|
+
[Default Value] smart
|
913
|
+
[Must Match] (?-mix:^[csi])
|
914
|
+
|
915
|
+
|
837
916
|
===== -s|--section SECTION_NAME
|
838
917
|
|
839
918
|
Section
|
@@ -944,6 +1023,14 @@ Boolean (AND|OR|NOT) with which to combine multiple tag filters
|
|
944
1023
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
945
1024
|
|
946
1025
|
|
1026
|
+
===== --case TYPE
|
1027
|
+
|
1028
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1029
|
+
|
1030
|
+
[Default Value] smart
|
1031
|
+
[Must Match] (?-mix:^[csi])
|
1032
|
+
|
1033
|
+
|
947
1034
|
===== -s|--section NAME
|
948
1035
|
|
949
1036
|
Section
|
@@ -1158,6 +1245,14 @@ Boolean (AND|OR|NOT) with which to combine multiple tag filters
|
|
1158
1245
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
1159
1246
|
|
1160
1247
|
|
1248
|
+
===== --case TYPE
|
1249
|
+
|
1250
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1251
|
+
|
1252
|
+
[Default Value] smart
|
1253
|
+
[Must Match] (?-mix:^[csi])
|
1254
|
+
|
1255
|
+
|
1161
1256
|
===== -s|--section NAME
|
1162
1257
|
|
1163
1258
|
Limit search to section
|
@@ -1220,6 +1315,14 @@ Tag boolean (AND|OR|NOT)
|
|
1220
1315
|
[Must Match] (?i-mx:^(?:and|all|any|or|not|none)$)
|
1221
1316
|
|
1222
1317
|
|
1318
|
+
===== --case TYPE
|
1319
|
+
|
1320
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1321
|
+
|
1322
|
+
[Default Value] smart
|
1323
|
+
[Must Match] (?-mix:^[csi])
|
1324
|
+
|
1325
|
+
|
1223
1326
|
===== -k|--keep X
|
1224
1327
|
|
1225
1328
|
How many items to keep in each section (most recent)
|
@@ -1278,6 +1381,14 @@ Multiple selections are allowed, hit tab to add the highlighted entry to the
|
|
1278
1381
|
selection, and use ctrl-a to select all visible items. Return processes the
|
1279
1382
|
selected entries.
|
1280
1383
|
===== Options
|
1384
|
+
===== --case TYPE
|
1385
|
+
|
1386
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1387
|
+
|
1388
|
+
[Default Value] smart
|
1389
|
+
[Must Match] (?-mix:^[csi])
|
1390
|
+
|
1391
|
+
|
1281
1392
|
===== -m|--move SECTION
|
1282
1393
|
|
1283
1394
|
Move selected items to section
|
@@ -1422,6 +1533,14 @@ Max count to show
|
|
1422
1533
|
[Default Value] 0
|
1423
1534
|
|
1424
1535
|
|
1536
|
+
===== --case TYPE
|
1537
|
+
|
1538
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1539
|
+
|
1540
|
+
[Default Value] smart
|
1541
|
+
[Must Match] (?-mix:^[csi])
|
1542
|
+
|
1543
|
+
|
1425
1544
|
===== -f|--from DATE_OR_RANGE
|
1426
1545
|
|
1427
1546
|
Date range to show, or a single day to filter date on.
|
@@ -1577,6 +1696,14 @@ How many recent entries to tag (0 for all)
|
|
1577
1696
|
[Must Match] (?-mix:^\d+$)
|
1578
1697
|
|
1579
1698
|
|
1699
|
+
===== --case TYPE
|
1700
|
+
|
1701
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1702
|
+
|
1703
|
+
[Default Value] smart
|
1704
|
+
[Must Match] (?-mix:^[csi])
|
1705
|
+
|
1706
|
+
|
1580
1707
|
===== --rename ORIG_TAG
|
1581
1708
|
|
1582
1709
|
Replace existing tag with tag argument, wildcards (*,?) allowed, or use with --regex
|
@@ -1655,9 +1782,7 @@ Force exact search string matching (case sensitive)
|
|
1655
1782
|
Output HTML, CSS, and Markdown (ERB) templates for customization
|
1656
1783
|
|
1657
1784
|
Templates are printed to STDOUT for piping to a file.
|
1658
|
-
Save them and use them in the configuration file under
|
1659
|
-
|
1660
|
-
Example `doing template haml > ~/styles/my_doing.haml`
|
1785
|
+
Save them and use them in the configuration file under export_templates.
|
1661
1786
|
===== Options
|
1662
1787
|
===== -c
|
1663
1788
|
List in single column for completion
|
@@ -1771,6 +1896,14 @@ Count to display
|
|
1771
1896
|
[Must Match] (?-mix:^\d+$)
|
1772
1897
|
|
1773
1898
|
|
1899
|
+
===== --case TYPE
|
1900
|
+
|
1901
|
+
Case sensitivity for search string matching [(c)ase-sensitive, (i)nsensitive, (s)mart]
|
1902
|
+
|
1903
|
+
[Default Value] smart
|
1904
|
+
[Must Match] (?-mix:^[csi])
|
1905
|
+
|
1906
|
+
|
1774
1907
|
===== -o|--output FORMAT
|
1775
1908
|
|
1776
1909
|
Output to export format (csv|doing|html|markdown|say|taskpaper|template|timeline|wiki)
|
data/lib/doing/item.rb
CHANGED
@@ -75,7 +75,7 @@ module Doing
|
|
75
75
|
negate ? !matches : matches
|
76
76
|
end
|
77
77
|
|
78
|
-
def search(search, negate: false)
|
78
|
+
def search(search, negate: false, case_type: :smart)
|
79
79
|
text = @title + @note.to_s
|
80
80
|
pattern = case search.strip
|
81
81
|
when %r{^/.*?/$}
|
@@ -84,7 +84,12 @@ module Doing
|
|
84
84
|
case_sensitive = true
|
85
85
|
search.sub(/^'(.*?)'?$/, '\1')
|
86
86
|
else
|
87
|
-
|
87
|
+
if case_type == :smart
|
88
|
+
case_sensitive = true if search =~ /[A-Z]/
|
89
|
+
else
|
90
|
+
case_sensitive = case_type == :sensitive
|
91
|
+
end
|
92
|
+
|
88
93
|
search.split('').join('.{0,3}')
|
89
94
|
end
|
90
95
|
rx = Regexp.new(pattern, !case_sensitive)
|
data/lib/doing/string.rb
CHANGED
@@ -164,6 +164,28 @@ module Doing
|
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
|
+
##
|
168
|
+
## @brief Convert a case sensitivity string to a symbol
|
169
|
+
##
|
170
|
+
## @return Symbol :smart, :sensitive, :insensitive
|
171
|
+
##
|
172
|
+
def normalize_case!
|
173
|
+
replace normalize_case
|
174
|
+
end
|
175
|
+
|
176
|
+
def normalize_case(default = :smart)
|
177
|
+
case self
|
178
|
+
when /^c/i
|
179
|
+
:sensitive
|
180
|
+
when /^i/i
|
181
|
+
:insensitive
|
182
|
+
when /^s/i
|
183
|
+
:smart
|
184
|
+
else
|
185
|
+
default.is_a?(Symbol) ? default : default.normalize_case
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
167
189
|
##
|
168
190
|
## @brief Convert a boolean string to a symbol
|
169
191
|
##
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -700,12 +700,17 @@ module Doing
|
|
700
700
|
end
|
701
701
|
|
702
702
|
if keep && opt[:search]
|
703
|
-
|
703
|
+
opt[:case] = opt[:case].normalize_case unless opt[:case].is_a?(Symbol)
|
704
|
+
search_match = if opt[:search].nil? || opt[:search].empty?
|
705
|
+
true
|
706
|
+
else
|
707
|
+
item.search(opt[:search], case_type: opt[:case])
|
708
|
+
end
|
709
|
+
|
704
710
|
keep = false unless search_match
|
705
711
|
keep = opt[:not] ? !keep : keep
|
706
712
|
end
|
707
713
|
|
708
|
-
|
709
714
|
if keep && opt[:date_filter]&.length == 2
|
710
715
|
start_date = opt[:date_filter][0]
|
711
716
|
end_date = opt[:date_filter][1]
|
@@ -773,14 +778,13 @@ module Doing
|
|
773
778
|
if opt[:search]
|
774
779
|
search = opt[:search]
|
775
780
|
search.sub!(/^'?/, "'") if opt[:exact]
|
776
|
-
search.downcase! if opt[:case] == false
|
777
781
|
opt[:search] = search
|
778
782
|
end
|
779
783
|
|
780
784
|
opt[:query] = opt[:search] if opt[:search] && !opt[:query]
|
781
785
|
opt[:query] = "!#{opt[:query]}" if opt[:not]
|
782
786
|
opt[:multiple] = true
|
783
|
-
items = filter_items([], opt: { section: section, search: opt[:search] })
|
787
|
+
items = filter_items([], opt: { section: section, search: opt[:search], case: opt[:case] })
|
784
788
|
|
785
789
|
selection = choose_from_items(items, opt, include_section: section =~ /^all$/i)
|
786
790
|
|
@@ -957,7 +961,7 @@ module Doing
|
|
957
961
|
if opt[:delete]
|
958
962
|
res = opt[:force] ? true : yn("Delete #{items.size} items?", default_response: 'y')
|
959
963
|
if res
|
960
|
-
items.each { |item| delete_item(item) }
|
964
|
+
items.each { |item| delete_item(item, single: items.count == 1) }
|
961
965
|
write(@doing_file)
|
962
966
|
end
|
963
967
|
return
|
@@ -1015,7 +1019,7 @@ module Doing
|
|
1015
1019
|
title = input_lines[0]&.strip
|
1016
1020
|
|
1017
1021
|
if title.nil? || title =~ /^#{divider.strip}$/ || title.strip.empty?
|
1018
|
-
delete_item(items[i])
|
1022
|
+
delete_item(items[i], single: new_items.count == 1)
|
1019
1023
|
else
|
1020
1024
|
note = input_lines.length > 1 ? input_lines[1..-1] : []
|
1021
1025
|
|
@@ -1265,13 +1269,13 @@ module Doing
|
|
1265
1269
|
##
|
1266
1270
|
## @param item The item
|
1267
1271
|
##
|
1268
|
-
def delete_item(item)
|
1272
|
+
def delete_item(item, single: false)
|
1269
1273
|
section = item.section
|
1270
1274
|
|
1271
1275
|
section_items = @content[section][:items]
|
1272
1276
|
deleted = section_items.delete(item)
|
1273
1277
|
logger.count(:deleted)
|
1274
|
-
logger.info('Entry deleted:', deleted.title)
|
1278
|
+
logger.info('Entry deleted:', deleted.title) if single
|
1275
1279
|
end
|
1276
1280
|
|
1277
1281
|
##
|
@@ -1897,6 +1901,7 @@ module Doing
|
|
1897
1901
|
end
|
1898
1902
|
|
1899
1903
|
opts[:search] = options[:search] if options[:search]
|
1904
|
+
opts[:case] = options[:case]
|
1900
1905
|
opts[:not] = options[:negate]
|
1901
1906
|
list_section(opts)
|
1902
1907
|
end
|
@@ -2070,7 +2075,7 @@ EOS
|
|
2070
2075
|
(max - k.length).times do
|
2071
2076
|
spacer += ' '
|
2072
2077
|
end
|
2073
|
-
|
2078
|
+
_d, h, m = format_time(v, human: true)
|
2074
2079
|
output.push("┃ #{spacer}#{k}:#{format('%<h> 4dh %<m>02dm', h: h, m: m)} ┃")
|
2075
2080
|
end
|
2076
2081
|
|