doing 2.1.42 → 2.1.43

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/bin/commands/changes.rb +11 -1
  6. data/bin/commands/flag.rb +1 -1
  7. data/bin/commands/grep.rb +3 -1
  8. data/bin/commands/last.rb +2 -0
  9. data/bin/commands/on.rb +8 -1
  10. data/bin/commands/recent.rb +3 -1
  11. data/bin/commands/show.rb +3 -0
  12. data/bin/commands/since.rb +2 -1
  13. data/bin/commands/template.rb +14 -25
  14. data/bin/commands/today.rb +3 -1
  15. data/bin/commands/view.rb +36 -73
  16. data/bin/commands/views.rb +40 -4
  17. data/bin/commands/yesterday.rb +3 -1
  18. data/bin/doing +7 -3
  19. data/docs/doc/Array.html +1 -1
  20. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  21. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  22. data/docs/doc/BooleanTermParser/Query.html +1 -1
  23. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  24. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  25. data/docs/doc/BooleanTermParser.html +1 -1
  26. data/docs/doc/Doing/ArrayCleanup.html +316 -0
  27. data/docs/doc/Doing/ArrayNestedHash.html +1 -1
  28. data/docs/doc/Doing/ArrayTags.html +1 -1
  29. data/docs/doc/Doing/CSVExport.html +1 -1
  30. data/docs/doc/Doing/CalendarImport.html +1 -1
  31. data/docs/doc/Doing/Change.html +74 -3
  32. data/docs/doc/Doing/Changes.html +3 -3
  33. data/docs/doc/Doing/ChronifyArray.html +1 -1
  34. data/docs/doc/Doing/ChronifyNumeric.html +1 -1
  35. data/docs/doc/Doing/ChronifyString.html +1 -1
  36. data/docs/doc/Doing/Color.html +1 -1
  37. data/docs/doc/Doing/Completion/BashCompletions.html +1 -1
  38. data/docs/doc/Doing/Completion/FishCompletions.html +1 -1
  39. data/docs/doc/Doing/Completion/StringUtils.html +1 -1
  40. data/docs/doc/Doing/Completion/ZshCompletions.html +1 -1
  41. data/docs/doc/Doing/Completion.html +1 -1
  42. data/docs/doc/Doing/Configuration.html +80 -1
  43. data/docs/doc/Doing/DayOneRenderer.html +1 -1
  44. data/docs/doc/Doing/DayoneExport.html +1 -1
  45. data/docs/doc/Doing/DoingImport.html +1 -1
  46. data/docs/doc/Doing/Entry.html +109 -4
  47. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  48. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  49. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  50. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  51. data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
  52. data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
  53. data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
  54. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  55. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  56. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  57. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  58. data/docs/doc/Doing/Errors.html +1 -1
  59. data/docs/doc/Doing/HTMLExport.html +1 -1
  60. data/docs/doc/Doing/Hooks.html +1 -1
  61. data/docs/doc/Doing/Item.html +1 -1
  62. data/docs/doc/Doing/ItemDates.html +1 -1
  63. data/docs/doc/Doing/ItemQuery.html +1 -1
  64. data/docs/doc/Doing/ItemState.html +1 -1
  65. data/docs/doc/Doing/ItemTags.html +1 -1
  66. data/docs/doc/Doing/Items.html +1 -1
  67. data/docs/doc/Doing/JSONExport.html +1 -1
  68. data/docs/doc/Doing/Logger.html +1 -1
  69. data/docs/doc/Doing/MarkdownExport.html +1 -1
  70. data/docs/doc/Doing/Note.html +1 -1
  71. data/docs/doc/Doing/Pager.html +1 -1
  72. data/docs/doc/Doing/Plugins.html +1 -1
  73. data/docs/doc/Doing/Prompt.html +1 -1
  74. data/docs/doc/Doing/PromptChoose.html +1 -1
  75. data/docs/doc/Doing/PromptFZF.html +1 -1
  76. data/docs/doc/Doing/PromptInput.html +1 -1
  77. data/docs/doc/Doing/PromptSTD.html +1 -1
  78. data/docs/doc/Doing/PromptYN.html +1 -1
  79. data/docs/doc/Doing/Section.html +1 -1
  80. data/docs/doc/Doing/StringHighlight.html +1 -1
  81. data/docs/doc/Doing/StringNormalize.html +35 -1
  82. data/docs/doc/Doing/StringQuery.html +1 -1
  83. data/docs/doc/Doing/StringTags.html +1 -1
  84. data/docs/doc/Doing/StringTransform.html +1 -1
  85. data/docs/doc/Doing/StringTruncate.html +1 -1
  86. data/docs/doc/Doing/StringURL.html +1 -1
  87. data/docs/doc/Doing/SymbolNormalize.html +1 -1
  88. data/docs/doc/Doing/TaskPaperExport.html +1 -1
  89. data/docs/doc/Doing/TemplateExport.html +1 -1
  90. data/docs/doc/Doing/TemplateString.html +2 -2
  91. data/docs/doc/Doing/TimingImport.html +1 -1
  92. data/docs/doc/Doing/Types.html +1 -1
  93. data/docs/doc/Doing/Util/Backup.html +1 -1
  94. data/docs/doc/Doing/Util.html +1 -1
  95. data/docs/doc/Doing/Version.html +1 -1
  96. data/docs/doc/Doing/WWID.html +71 -3
  97. data/docs/doc/Doing.html +2 -2
  98. data/docs/doc/FalseClass.html +1 -1
  99. data/docs/doc/GLI/Commands/Help.html +1 -1
  100. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  101. data/docs/doc/GLI/Commands.html +1 -1
  102. data/docs/doc/GLI.html +1 -1
  103. data/docs/doc/Hash.html +461 -6
  104. data/docs/doc/Numeric.html +1 -1
  105. data/docs/doc/Object.html +1 -1
  106. data/docs/doc/PhraseParser/Operator.html +1 -1
  107. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  108. data/docs/doc/PhraseParser/Query.html +1 -1
  109. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  110. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  111. data/docs/doc/PhraseParser/TermClause.html +1 -1
  112. data/docs/doc/PhraseParser.html +1 -1
  113. data/docs/doc/Status.html +1 -1
  114. data/docs/doc/String.html +2 -2
  115. data/docs/doc/Symbol.html +1 -1
  116. data/docs/doc/Time.html +1 -1
  117. data/docs/doc/TrueClass.html +1 -1
  118. data/docs/doc/_index.html +1 -1
  119. data/docs/doc/file.README.html +2 -2
  120. data/docs/doc/index.html +2 -2
  121. data/docs/doc/method_list.html +484 -388
  122. data/docs/doc/top-level-namespace.html +3 -1
  123. data/doing.rdoc +101 -6
  124. data/lib/completion/_doing.zsh +13 -13
  125. data/lib/completion/doing.bash +22 -22
  126. data/lib/completion/doing.fish +15 -1
  127. data/lib/doing/add_options.rb +35 -0
  128. data/lib/doing/changelog/change.rb +13 -5
  129. data/lib/doing/changelog/changes.rb +11 -2
  130. data/lib/doing/changelog/entry.rb +9 -2
  131. data/lib/doing/configuration.rb +17 -0
  132. data/lib/doing/hash.rb +126 -22
  133. data/lib/doing/normalize.rb +13 -0
  134. data/lib/doing/pager.rb +1 -1
  135. data/lib/doing/version.rb +1 -1
  136. data/lib/doing/wwid/wwid.rb +21 -3
  137. metadata +3 -2
@@ -228,6 +228,8 @@ complete -c doing -l all -s a -f -n '__fish_doing_using_command changes changel
228
228
  complete -c doing -l interactive -s i -f -n '__fish_doing_using_command changes changelog' -d Open\ changelog\ in\ interactive\ viewer
229
229
  complete -c doing -l lookup -s l -f -r -n '__fish_doing_using_command changes changelog' -d Look\ up\ a\ specific\ version
230
230
  complete -c doing -l markdown -f -n '__fish_doing_using_command changes changelog' -d Output\ raw\ Markdown
231
+ complete -c doing -l only -f -r -n '__fish_doing_using_command changes changelog' -d Only\ show\ changes\ of\ type\(s\)
232
+ complete -c doing -l prefix -s p -f -n '__fish_doing_using_command changes changelog' -d Include
231
233
  complete -c doing -l render -f -n '__fish_doing_using_command changes changelog' -d Force\ rendered\ output
232
234
  complete -c doing -l search -s s -f -r -n '__fish_doing_using_command changes changelog' -d Show\ changelogs\ matching\ search\ terms
233
235
  complete -c doing -l sort -f -r -n '__fish_doing_using_command changes changelog' -d Sort\ order
@@ -281,6 +283,7 @@ complete -c doing -l not -f -n '__fish_doing_using_command grep search' -d Sea
281
283
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command grep search' -d Output\ to\ export\ format
282
284
  complete -c doing -l only_timed -f -n '__fish_doing_using_command grep search' -d Only\ show\ items\ with\ recorded\ time\ intervals
283
285
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command grep search' -d Section
286
+ complete -c doing -l save -f -r -n '__fish_doing_using_command grep search' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
284
287
  complete -c doing -l times -s t -f -n '__fish_doing_using_command grep search' -d Show\ time\ intervals\ on\ @done\ tasks
285
288
  complete -c doing -l tag -f -r -n '__fish_doing_using_command grep search' -d Filter\ entries\ by\ tag
286
289
  complete -c doing -l tag_order -f -r -n '__fish_doing_using_command grep search' -d Tag\ sort\ direction
@@ -314,6 +317,7 @@ complete -c doing -l hilite -s h -f -n '__fish_doing_using_command last' -d Hig
314
317
  complete -c doing -l not -f -n '__fish_doing_using_command last' -d Show\ items\ that\ \*don\'t\*\ match\ search/tag\ filters
315
318
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command last' -d Output\ to\ export\ format
316
319
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command last' -d Specify\ a\ section
320
+ complete -c doing -l save -f -r -n '__fish_doing_using_command last' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
317
321
  complete -c doing -l search -f -r -n '__fish_doing_using_command last' -d Filter\ entries\ using\ a\ search\ query
318
322
  complete -c doing -l tag -f -r -n '__fish_doing_using_command last' -d Filter\ entries\ by\ tag
319
323
  complete -c doing -l template -f -r -n '__fish_doing_using_command last' -d Override\ output\ format\ with\ a\ template\ string\ containing\ \%placeholders
@@ -371,6 +375,7 @@ complete -c doing -l not -f -n '__fish_doing_using_command on' -d Show\ items\
371
375
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command on' -d Output\ to\ export\ format
372
376
  complete -c doing -l only_timed -f -n '__fish_doing_using_command on' -d Only\ show\ items\ with\ recorded\ time\ intervals
373
377
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command on' -d Section
378
+ complete -c doing -l save -f -r -n '__fish_doing_using_command on' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
374
379
  complete -c doing -l search -f -r -n '__fish_doing_using_command on' -d Filter\ entries\ using\ a\ search\ query
375
380
  complete -c doing -l times -s t -f -n '__fish_doing_using_command on' -d Show\ time\ intervals\ on\ @done\ tasks
376
381
  complete -c doing -l tag -f -r -n '__fish_doing_using_command on' -d Filter\ entries\ by\ tag
@@ -391,6 +396,7 @@ complete -c doing -l interactive -s i -f -n '__fish_doing_using_command recent'
391
396
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command recent' -d Output\ to\ export\ format
392
397
  complete -c doing -l only_timed -f -n '__fish_doing_using_command recent' -d Only\ show\ items\ with\ recorded\ time\ intervals
393
398
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command recent' -d Section
399
+ complete -c doing -l save -f -r -n '__fish_doing_using_command recent' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
394
400
  complete -c doing -l times -s t -f -n '__fish_doing_using_command recent' -d Show\ time\ intervals\ on\ @done\ tasks
395
401
  complete -c doing -l tag_order -f -r -n '__fish_doing_using_command recent' -d Tag\ sort\ direction
396
402
  complete -c doing -l tag_sort -f -r -n '__fish_doing_using_command recent' -d Sort\ tags\ by
@@ -461,6 +467,7 @@ complete -c doing -l not -f -n '__fish_doing_using_command show' -d Show\ item
461
467
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command show' -d Output\ to\ export\ format
462
468
  complete -c doing -l only_timed -f -n '__fish_doing_using_command show' -d Only\ show\ items\ with\ recorded\ time\ intervals
463
469
  complete -c doing -l sort -s s -f -r -n '__fish_doing_using_command show' -d Sort\ order
470
+ complete -c doing -l save -f -r -n '__fish_doing_using_command show' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
464
471
  complete -c doing -l search -f -r -n '__fish_doing_using_command show' -d Filter\ entries\ using\ a\ search\ query
465
472
  complete -c doing -l times -s t -f -n '__fish_doing_using_command show' -d Show\ time\ intervals\ on\ @done\ tasks
466
473
  complete -c doing -l tag -f -r -n '__fish_doing_using_command show' -d Filter\ entries\ by\ tag
@@ -478,6 +485,7 @@ complete -c doing -l not -f -n '__fish_doing_using_command since' -d Since\ it
478
485
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command since' -d Output\ to\ export\ format
479
486
  complete -c doing -l only_timed -f -n '__fish_doing_using_command since' -d Only\ show\ items\ with\ recorded\ time\ intervals
480
487
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command since' -d Section
488
+ complete -c doing -l save -f -r -n '__fish_doing_using_command since' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
481
489
  complete -c doing -l search -f -r -n '__fish_doing_using_command since' -d Filter\ entries\ using\ a\ search\ query
482
490
  complete -c doing -l times -s t -f -n '__fish_doing_using_command since' -d Show\ time\ intervals\ on\ @done\ tasks
483
491
  complete -c doing -l tag -f -r -n '__fish_doing_using_command since' -d Filter\ entries\ by\ tag
@@ -533,6 +541,7 @@ complete -c doing -l from -f -r -n '__fish_doing_using_command today' -d Time\
533
541
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command today' -d Output\ to\ export\ format
534
542
  complete -c doing -l only_timed -f -n '__fish_doing_using_command today' -d Only\ show\ items\ with\ recorded\ time\ intervals
535
543
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command today' -d Specify\ a\ section
544
+ complete -c doing -l save -f -r -n '__fish_doing_using_command today' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
536
545
  complete -c doing -l times -s t -f -n '__fish_doing_using_command today' -d Show\ time\ intervals\ on\ @done\ tasks
537
546
  complete -c doing -l tag_order -f -r -n '__fish_doing_using_command today' -d Tag\ sort\ direction
538
547
  complete -c doing -l tag_sort -f -r -n '__fish_doing_using_command today' -d Sort\ tags\ by
@@ -549,6 +558,7 @@ complete -c doing -l bool -f -r -n '__fish_doing_using_command view' -d Boolean
549
558
  complete -c doing -l count -s c -f -r -n '__fish_doing_using_command view' -d Count\ to\ display
550
559
  complete -c doing -l case -f -r -n '__fish_doing_using_command view' -d Case\ sensitivity\ for\ search\ string\ matching\ \[\(c\)ase-sensitive
551
560
  complete -c doing -l color -f -n '__fish_doing_using_command view' -d Include\ colors\ in\ output
561
+ complete -c doing -l config_template -f -r -n '__fish_doing_using_command view' -d Output\ using\ a\ template\ from\ configuration
552
562
  complete -c doing -l duration -f -n '__fish_doing_using_command view' -d Show\ elapsed\ time\ on\ entries\ without\ @done\ tag
553
563
  complete -c doing -l from -f -r -n '__fish_doing_using_command view' -d Date\ range
554
564
  complete -c doing -l hilite -s h -f -n '__fish_doing_using_command view' -d Highlight\ search\ matches\ in\ output
@@ -562,10 +572,13 @@ complete -c doing -l times -s t -f -n '__fish_doing_using_command view' -d Show
562
572
  complete -c doing -l tag -f -r -n '__fish_doing_using_command view' -d Filter\ entries\ by\ tag
563
573
  complete -c doing -l tag_order -f -r -n '__fish_doing_using_command view' -d Tag\ sort\ direction
564
574
  complete -c doing -l tag_sort -f -r -n '__fish_doing_using_command view' -d Sort\ tags\ by
575
+ complete -c doing -l template -f -r -n '__fish_doing_using_command view' -d Override\ output\ format\ with\ a\ template\ string\ containing\ \%placeholders
565
576
  complete -c doing -l totals -f -n '__fish_doing_using_command view' -d Show\ intervals\ with\ totals\ at\ the\ end\ of\ output
566
577
  complete -c doing -l val -f -r -n '__fish_doing_using_command view' -d Perform\ a\ tag\ value\ query
567
578
  complete -c doing -l exact -s x -f -n '__fish_doing_using_command view' -d Force\ exact\ search\ string\ matching
568
579
  complete -c doing -l column -s c -f -n '__fish_doing_using_command views' -d List\ in\ single\ column
580
+ complete -c doing -l editor -s e -f -n '__fish_doing_using_command views' -d Open\ YAML\ for\ view\ in\ editor
581
+ complete -c doing -l output -s o -f -r -n '__fish_doing_using_command views' -d Output/edit\ view\ in\ alternative\ format
569
582
  complete -c doing -l after -f -r -n '__fish_doing_using_command wiki' -d Include\ entries\ newer\ than\ date
570
583
  complete -c doing -l bool -s b -f -r -n '__fish_doing_using_command wiki' -d Tag\ boolean
571
584
  complete -c doing -l before -f -r -n '__fish_doing_using_command wiki' -d Include\ entries\ older\ than\ date
@@ -582,12 +595,13 @@ complete -c doing -l from -f -r -n '__fish_doing_using_command yesterday' -d Ti
582
595
  complete -c doing -l output -s o -f -r -n '__fish_doing_using_command yesterday' -d Output\ to\ export\ format
583
596
  complete -c doing -l only_timed -f -n '__fish_doing_using_command yesterday' -d Only\ show\ items\ with\ recorded\ time\ intervals
584
597
  complete -c doing -l section -s s -f -r -n '__fish_doing_using_command yesterday' -d Specify\ a\ section
598
+ complete -c doing -l save -f -r -n '__fish_doing_using_command yesterday' -d Save\ all\ current\ command\ line\ options\ as\ a\ new\ view
585
599
  complete -c doing -l times -s t -f -n '__fish_doing_using_command yesterday' -d Show\ time\ intervals\ on\ @done\ tasks
586
600
  complete -c doing -l tag_order -f -r -n '__fish_doing_using_command yesterday' -d Tag\ sort\ direction
587
601
  complete -c doing -l tag_sort -f -r -n '__fish_doing_using_command yesterday' -d Sort\ tags\ by
588
602
  complete -c doing -l template -f -r -n '__fish_doing_using_command yesterday' -d Override\ output\ format\ with\ a\ template\ string\ containing\ \%placeholders
589
603
  complete -c doing -l totals -f -n '__fish_doing_using_command yesterday' -d Show\ time\ totals\ at\ the\ end\ of\ output
590
- complete -f -c doing -s o -l output -x -n '__fish_doing_using_command grep search last on recent select show since today view yesterday' -a '(__fish_doing_export_plugin)'
604
+ complete -f -c doing -s o -l output -x -n '__fish_doing_using_command grep search last on recent select show since today view views yesterday' -a '(__fish_doing_export_plugin)'
591
605
  complete -f -c doing -s b -l bool -x -n '__fish_doing_using_command again resume archive move autotag cancel finish grep search last mark flag note on reset begin rotate show since tag tags view wiki' -a 'and or not pattern'
592
606
  complete -f -c doing -l case -x -n '__fish_doing_using_command again resume archive move cancel finish grep search import last mark flag note on reset begin rotate select show since tag tags view' -a 'case-sensitive ignore smart'
593
607
  complete -f -c doing -l sort -x -n '__fish_doing_using_command changes changelog show tags' -a 'asc desc'
@@ -19,6 +19,8 @@
19
19
  ##
20
20
  ## :date_filter => --before, --after, --from
21
21
  ##
22
+ ## :save => --save
23
+ ##
22
24
  ## @param type [Symbol] The type
23
25
  ## @param cmd The GLI command to which the options will be added
24
26
  ##
@@ -47,6 +49,18 @@ def add_options(type, cmd, default_template: 'default')
47
49
  cmd.arg_name 'TEMPLATE_KEY'
48
50
  cmd.flag [:config_template], type: TemplateName, default_value: default_template
49
51
 
52
+ cmd.desc 'Override output format with a template string containing %placeholders'
53
+ cmd.arg_name 'TEMPLATE_STRING'
54
+ cmd.flag [:template]
55
+ when :output_template_no_defaults
56
+ cmd.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
57
+ cmd.arg_name 'FORMAT'
58
+ cmd.flag %i[o output]
59
+
60
+ cmd.desc "Output using a template from configuration"
61
+ cmd.arg_name 'TEMPLATE_KEY'
62
+ cmd.flag [:config_template], type: TemplateName
63
+
50
64
  cmd.desc 'Override output format with a template string containing %placeholders'
51
65
  cmd.arg_name 'TEMPLATE_STRING'
52
66
  cmd.flag [:template]
@@ -138,6 +152,23 @@ def add_options(type, cmd, default_template: 'default')
138
152
  cmd.flag [:bool], must_match: REGEX_BOOL,
139
153
  default_value: :pattern,
140
154
  type: BooleanSymbol
155
+ when :tag_filter_no_defaults
156
+ cmd.desc 'Filter entries by tag. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
157
+ cmd.arg_name 'TAG'
158
+ cmd.flag [:tag], type: TagArray
159
+
160
+ cmd.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50").
161
+ May be used multiple times, combined with --bool'
162
+ cmd.arg_name 'QUERY'
163
+ cmd.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
164
+
165
+ cmd.desc "#{action} items that *don't* match search/tag filters"
166
+ cmd.switch [:not], negatable: false
167
+
168
+ cmd.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
169
+ cmd.arg_name 'BOOLEAN'
170
+ cmd.flag [:bool], must_match: REGEX_BOOL,
171
+ type: BooleanSymbol
141
172
  when :time_filter
142
173
  cmd.desc 'View entries before specified time (e.g. 8am, 12:30pm, 15:00)'
143
174
  cmd.arg_name 'TIME_STRING'
@@ -186,5 +217,9 @@ def add_options(type, cmd, default_template: 'default')
186
217
  end
187
218
  cmd.arg_name 'DATE_OR_RANGE'
188
219
  cmd.flag [:from], type: DateRangeString
220
+ when :save
221
+ cmd.desc 'Save all current command line options as a new view'
222
+ cmd.arg_name 'VIEW_NAME'
223
+ cmd.flag %i[save]
189
224
  end
190
225
  end
@@ -7,9 +7,13 @@ module Doing
7
7
 
8
8
  attr_accessor :entries, :change_date
9
9
 
10
- def initialize(version, content)
10
+ attr_writer :prefix
11
+
12
+ def initialize(version, content, prefix: false, only: %i[changed new improved fixed])
11
13
  @version = Version.new(version)
12
14
  @content = content
15
+ @prefix = prefix
16
+ @only = only
13
17
  parse_entries
14
18
  end
15
19
 
@@ -18,10 +22,10 @@ module Doing
18
22
  @change_date = Time.parse(date[0]) if date
19
23
 
20
24
  @entries = []
21
- types = @content.scan(/(?<=\n|\A)#### (NEW|IMPROVED|FIXED)(.*?)(?=\n####|\Z)/m)
25
+ types = @content.scan(/(?<=\n|\A)#### (CHANGED|NEW|IMPROVED|FIXED)(.*?)(?=\n####|\Z)/m)
22
26
  types.each do |type|
23
27
  type[1].scan(/\s*- +(.*?)$/).each do |entry|
24
- @entries << Entry.new(entry[0].strip, type[0])
28
+ @entries << Entry.new(entry[0].strip, type[0], prefix: @prefix)
25
29
  end
26
30
  end
27
31
  end
@@ -57,7 +61,7 @@ module Doing
57
61
  end
58
62
 
59
63
  def split_items
60
- items = { new: [], improved: [], fixed: [], other: [] }
64
+ items = { changed: [], new: [], improved: [], fixed: [], other: [] }
61
65
 
62
66
  @entries.each do |e|
63
67
  type = e.type.downcase.to_sym
@@ -76,6 +80,8 @@ module Doing
76
80
  out = ["### __#{@version}__#{date}"]
77
81
 
78
82
  split_items.each do |type, members|
83
+ next unless @only.include?(type)
84
+
79
85
  if members.count.positive?
80
86
  out << "#### #{type.to_s.capitalize}"
81
87
  out << members.map(&:to_s).join("\n")
@@ -88,7 +94,9 @@ module Doing
88
94
  def changes_only
89
95
  out = []
90
96
 
91
- split_items.each do |_, members|
97
+ split_items.each do |type, members|
98
+ next unless @only.include?(type)
99
+
92
100
  out << members.map(&:to_s).join("\n")
93
101
  end
94
102
 
@@ -6,8 +6,10 @@ module Doing
6
6
  attr_reader :changes
7
7
  attr_writer :changes_only
8
8
 
9
- def initialize(lookup: nil, search: nil, changes: false, sort: :desc)
9
+ def initialize(lookup: nil, search: nil, changes: false, sort: :desc, prefix: false, only: %i[changed new improved fixed])
10
10
  @changes_only = changes
11
+ @prefix = prefix
12
+ @only = only
11
13
  changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'CHANGELOG.md'))
12
14
  raise 'Error locating changelog' unless File.exist?(changelog)
13
15
 
@@ -56,9 +58,10 @@ module Doing
56
58
  @changes = @content.scan(change_rx).each_with_object([]) do |m, a|
57
59
  next if m[0].nil? || m[1].nil?
58
60
 
59
- a << Change.new(m[0], m[1].strip)
61
+ a << Change.new(m[0], m[1].strip, prefix: @prefix)
60
62
  end
61
63
 
64
+ select_type
62
65
  lookup(lookup) unless lookup.nil?
63
66
  search(search) unless search.nil?
64
67
  end
@@ -98,5 +101,11 @@ module Doing
98
101
 
99
102
  @changes.delete_if { |c| c.nil? || c.entries.nil? }
100
103
  end
104
+
105
+ def select_type
106
+ @changes.map do |c|
107
+ c.entries.delete_if { |e| !@only.include?(e.type.normalize_change_type) }
108
+ end
109
+ end
101
110
  end
102
111
  end
@@ -5,17 +5,24 @@ module Doing
5
5
  class Entry
6
6
  attr_reader :type, :string
7
7
 
8
- def initialize(string, type)
8
+ attr_writer :prefix
9
+
10
+ def initialize(string, type, prefix: false)
9
11
  @string = string
10
12
  @type = type
13
+ @prefix = prefix
11
14
  end
12
15
 
13
16
  def clean(string)
14
17
  string.gsub(/\|/, '\|')
15
18
  end
16
19
 
20
+ def print_prefix
21
+ @prefix ? "#{@type}: " : ''
22
+ end
23
+
17
24
  def to_s
18
- "- #{clean(@string)}"
25
+ "- #{print_prefix}#{clean(@string)}"
19
26
  end
20
27
  end
21
28
  end
@@ -361,6 +361,23 @@ module Doing
361
361
  config
362
362
  end
363
363
 
364
+ ##
365
+ ## Save a set of options to the `views` configuration
366
+ ##
367
+ ## @param view [Hash] view options
368
+ ## @param title [String] view title
369
+ ##
370
+ def save_view(view, title)
371
+ title.downcase!
372
+ user_config = Util.safe_load_file(config_file)
373
+ user_config['views'] = {} unless user_config.key?('views')
374
+ user_config['views'][title] = view
375
+ Util.write_to_file(config_file, YAML.dump(user_config), backup: true)
376
+ Doing.logger.warn('Config:', %(View "#{title}" saved to #{config_file}))
377
+ Doing.logger.info('Config:', %(to use, run `doing view #{title}`))
378
+ Hooks.trigger :post_config, self
379
+ end
380
+
364
381
  # @private
365
382
  def inspect
366
383
  %(<Doing::Configuration #{@settings.hash}>)
data/lib/doing/hash.rb CHANGED
@@ -40,14 +40,46 @@ module Doing
40
40
 
41
41
  # Turn all keys into string
42
42
  #
43
- # Return a copy of the hash where all its keys are strings
43
+ # If the hash has both a string and a symbol for key,
44
+ # keep the string value, discarding the symnbol value
45
+ #
46
+ # @return [Hash] a copy of the hash where all its
47
+ # keys are strings
48
+ #
44
49
  def stringify_keys
45
- each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v.is_a?(Hash) ? v.stringify_keys : v }
50
+ each_with_object({}) do |(k, v), hsh|
51
+ next if k.is_a?(Symbol) && key?(k.to_s)
52
+
53
+ hsh[k.to_s] = v.is_a?(Hash) ? v.stringify_keys : v
54
+ end
46
55
  end
47
56
 
48
57
  # Turn all keys into symbols
58
+ #
59
+ # If the hash has both a string and a symbol for a key,
60
+ # keep the symbol value and discard the string value
61
+ #
62
+ # @return [Hash] a copy of the hash where all its
63
+ # keys are symbols
64
+ #
49
65
  def symbolize_keys
50
- each_with_object({}) { |(k, v), hsh| hsh[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v }
66
+ each_with_object({}) do |(k, v), hsh|
67
+ next if k.is_a?(String) && key?(k.to_sym)
68
+
69
+ hsh[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v
70
+ end
71
+ end
72
+
73
+ def stringify_values
74
+ transform_values do |v|
75
+ if v.is_a?(Hash)
76
+ v.stringify_values
77
+ elsif v.is_a?(Symbol)
78
+ v.to_s
79
+ else
80
+ v
81
+ end
82
+ end
51
83
  end
52
84
 
53
85
  # Set a nested hash value using an array
@@ -61,30 +93,102 @@ module Doing
61
93
  #
62
94
  def deep_set(path, value)
63
95
  if path.count == 1
64
- unless value.nil? || value =~ /^ *$/
65
- self[path[0]] = value
66
- else
96
+ if value.nil? || value =~ /^ *$/
67
97
  delete(path[0])
98
+ else
99
+ self[path[0]] = value
68
100
  end
101
+ elsif value
102
+ self.default_proc = ->(h, k) { h[k] = Hash.new(&h.default_proc) }
103
+ dig(*path[0..-2])[path.fetch(-1)] = value
69
104
  else
70
- if value
71
- self.default_proc = ->(h, k) { h[k] = Hash.new(&h.default_proc) }
72
- dig(*path[0..-2])[path.fetch(-1)] = value
73
- else
74
- return self unless dig(*path)
75
-
76
- dig(*path[0..-2]).delete(path.fetch(-1))
77
- path.pop
78
- cleaned = self
79
- path.each do |key|
80
- if cleaned[key].empty?
81
- cleaned.delete(key)
82
- break
83
- end
84
- cleaned = cleaned[key]
105
+ return self unless dig(*path)
106
+
107
+ dig(*path[0..-2]).delete(path.fetch(-1))
108
+ path.pop
109
+ cleaned = self
110
+ path.each do |key|
111
+ if cleaned[key].empty?
112
+ cleaned.delete(key)
113
+ break
85
114
  end
86
- empty? ? nil : self
115
+ cleaned = cleaned[key]
87
116
  end
117
+ empty? ? nil : self
118
+ end
119
+ end
120
+
121
+ ##
122
+ ## Rename a key, deleting old key
123
+ ##
124
+ ## @param old_key The original key
125
+ ## @param new_key The new key
126
+ ## @param keep [Boolean] if true, keep old key
127
+ ## in addition to new key
128
+ ##
129
+ def rename_key(old_key, new_key, keep: false)
130
+ return unless key?(old_key)
131
+
132
+ self[new_key] = self[old_key]
133
+ self[new_key.to_s] = self[old_key] if key?(new_key.to_s)
134
+ delete(old_key) unless keep
135
+ end
136
+
137
+ ##
138
+ ## Rename keys in batch
139
+ ##
140
+ ## @param pairs [Array] pairs of old and new keys
141
+ ##
142
+ def rename_keys(*pairs)
143
+ pairs.each { |p| rename_key(p[0], p[1]) }
144
+ end
145
+
146
+ ##
147
+ ## Remove keys with empty values
148
+ ##
149
+ def remove_empty
150
+ delete_if { |k, v| !v.is_a?(FalseClass) && !v.good? }
151
+ end
152
+
153
+ def tag_filter_to_options
154
+ hsh = dup
155
+ if hsh.key?(:tag_filter)
156
+ hsh[:tags] = hsh[:tag_filter][:tags]
157
+ hsh[:bool] = hsh[:tag_filter][:bool]
158
+ hsh.delete(:tag_filter)
159
+ end
160
+ replace hsh
161
+ end
162
+
163
+ ##
164
+ ## Convert an options hash to a view config
165
+ ##
166
+ ## @return [Hash] View representation of the object.
167
+ ##
168
+ def to_view
169
+ hsh = symbolize_keys
170
+ %w[x save c a s o h e editor m menu i interactive d delete t fuzzy time_filter sort_tags].each do |key|
171
+ hsh.delete(key.to_sym) if hsh.key?(key.to_sym)
172
+ end
173
+
174
+ hsh.delete_unless_key(:tag, %i[bool])
175
+ hsh.delete_unless_key(:search, %i[exact case])
176
+ hsh.rename_keys(%i[not negate], %i[tag tags])
177
+ hsh.tag_filter_to_options
178
+
179
+ hsh = hsh.remove_empty.stringify_keys.stringify_values
180
+ hsh.keys.sort.each_with_object({}) { |k, out| out[k] = hsh[k] }
181
+ end
182
+
183
+ ##
184
+ ## Delete array of keys unless key exists
185
+ ##
186
+ ## @param key The key to verify
187
+ ## @param to_delete [Array] the keys to delete if key doesn't exist
188
+ ##
189
+ def delete_unless_key(key, to_delete)
190
+ unless key?(key)
191
+ to_delete.each { |k| delete(k) }
88
192
  end
89
193
  end
90
194
  end
@@ -155,6 +155,19 @@ module Doing
155
155
  def normalize_trigger!
156
156
  replace normalize_trigger
157
157
  end
158
+
159
+ def normalize_change_type
160
+ case self
161
+ when /^c/i
162
+ :changed
163
+ when /^i/i
164
+ :improved
165
+ when /^f/i
166
+ :fixed
167
+ when /^n/i
168
+ :new
169
+ end
170
+ end
158
171
  end
159
172
 
160
173
  ##
data/lib/doing/pager.rb CHANGED
@@ -73,7 +73,7 @@ module Doing
73
73
  [
74
74
  Doing.setting('editors.pager'),
75
75
  ENV['PAGER'],
76
- 'less -Xr',
76
+ 'less -FXr',
77
77
  ENV['GIT_PAGER'],
78
78
  git_pager,
79
79
  'more -r'
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.42'
2
+ VERSION = '2.1.43'
3
3
  end
@@ -100,10 +100,28 @@ module Doing
100
100
  ##
101
101
  ## @param title [String] The title of the view to retrieve
102
102
  ##
103
- def get_view(title)
104
- return Doing.setting(['views', title], nil)
103
+ def get_view(title, fallback: nil)
104
+ Doing.setting(['views', title], fallback)
105
+ end
106
+
107
+ def rename_view_keys(view)
108
+ options = view.symbolize_keys
109
+ # options.rename_key(:tags, :tag, keep: true)
110
+ options.rename_key(:output_format, :output)
111
+ options.rename_key(:tags_bool, :bool)
112
+ options.rename_key(:tag_sort, :sort_tags)
113
+ options.rename_key(:negate, :not)
114
+ options.rename_key(:order, :sort)
115
+
116
+ options
117
+ end
105
118
 
106
- false
119
+ def view_to_options(title)
120
+ view = rename_view_keys(get_view(guess_view(title)))
121
+ view.deep_merge(rename_view_keys(get_view(guess_view(view[:parent]), fallback: {}))) if view.key?(:parent)
122
+ view.deep_merge(rename_view_keys(get_view(view[:config_template], fallback: {}))) if view.key?(:config_template)
123
+ view.deep_merge(Doing.setting('templates.default').symbolize_keys)
124
+ view
107
125
  end
108
126
 
109
127
  private
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.42
4
+ version: 2.1.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-18 00:00:00.000000000 Z
11
+ date: 2022-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: github-markup
@@ -489,6 +489,7 @@ files:
489
489
  - docs/doc/BooleanTermParser/QueryParser.html
490
490
  - docs/doc/BooleanTermParser/QueryTransformer.html
491
491
  - docs/doc/Doing.html
492
+ - docs/doc/Doing/ArrayCleanup.html
492
493
  - docs/doc/Doing/ArrayNestedHash.html
493
494
  - docs/doc/Doing/ArrayTags.html
494
495
  - docs/doc/Doing/CLIFormat.html