doing 2.1.12 → 2.1.13

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +8 -8
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +11 -0
  6. data/Gemfile.lock +1 -1
  7. data/README.md +1 -1
  8. data/bin/doing +120 -45
  9. data/docs/doc/Array.html +1 -1
  10. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  11. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  12. data/docs/doc/BooleanTermParser/Query.html +1 -1
  13. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  14. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  15. data/docs/doc/BooleanTermParser.html +1 -1
  16. data/docs/doc/Doing/Color.html +1 -1
  17. data/docs/doc/Doing/Completion.html +1 -1
  18. data/docs/doc/Doing/Configuration.html +3 -3
  19. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  20. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  21. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  22. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  23. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  24. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  25. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  26. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  27. data/docs/doc/Doing/Errors.html +1 -1
  28. data/docs/doc/Doing/Hooks.html +1 -1
  29. data/docs/doc/Doing/Item.html +116 -1
  30. data/docs/doc/Doing/Items.html +65 -1
  31. data/docs/doc/Doing/LogAdapter.html +1 -1
  32. data/docs/doc/Doing/Note.html +1 -1
  33. data/docs/doc/Doing/Pager.html +1 -1
  34. data/docs/doc/Doing/Plugins.html +1 -1
  35. data/docs/doc/Doing/Prompt.html +1 -1
  36. data/docs/doc/Doing/Section.html +1 -1
  37. data/docs/doc/Doing/TemplateString.html +1 -1
  38. data/docs/doc/Doing/Util/Backup.html +84 -1
  39. data/docs/doc/Doing/Util.html +1 -1
  40. data/docs/doc/Doing/WWID.html +174 -1
  41. data/docs/doc/Doing.html +2 -2
  42. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  43. data/docs/doc/GLI/Commands.html +1 -1
  44. data/docs/doc/GLI.html +1 -1
  45. data/docs/doc/Hash.html +1 -1
  46. data/docs/doc/PhraseParser/Operator.html +1 -1
  47. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  48. data/docs/doc/PhraseParser/Query.html +1 -1
  49. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  50. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  51. data/docs/doc/PhraseParser/TermClause.html +1 -1
  52. data/docs/doc/PhraseParser.html +1 -1
  53. data/docs/doc/Status.html +1 -1
  54. data/docs/doc/String.html +1 -1
  55. data/docs/doc/Symbol.html +1 -1
  56. data/docs/doc/Time.html +1 -1
  57. data/docs/doc/_index.html +1 -1
  58. data/docs/doc/file.README.html +2 -2
  59. data/docs/doc/index.html +2 -2
  60. data/docs/doc/method_list.html +253 -197
  61. data/docs/doc/top-level-namespace.html +1 -1
  62. data/doing.rdoc +202 -40
  63. data/lib/completion/_doing.zsh +24 -20
  64. data/lib/completion/doing.bash +41 -30
  65. data/lib/completion/doing.fish +23 -1
  66. data/lib/doing/item.rb +119 -0
  67. data/lib/doing/version.rb +1 -1
  68. data/lib/doing/wwid.rb +20 -5
  69. metadata +2 -2
data/lib/doing/item.rb CHANGED
@@ -197,6 +197,29 @@ module Doing
197
197
  negate ? !matches : matches
198
198
  end
199
199
 
200
+ ##
201
+ ## Test if item matches tag values
202
+ ##
203
+ ## @param queries (Array) The tag value queries to test
204
+ ## @param bool (Symbol) The boolean to use for multiple tags (:and, :or, :not)
205
+ ## @param negate [Boolean] negate the result?
206
+ ##
207
+ ## @return [Boolean] true if tag/bool combination passes
208
+ ##
209
+ def tag_values?(queries, bool = :and, negate: false)
210
+ bool = bool.normalize_bool
211
+
212
+ matches = case bool
213
+ when :and
214
+ all_values?(queries)
215
+ when :not
216
+ no_values?(queries)
217
+ else
218
+ any_values?(queries)
219
+ end
220
+ negate ? !matches : matches
221
+ end
222
+
200
223
  def ignore_case(search, case_type)
201
224
  (case_type == :smart && search !~ /[A-Z]/) || case_type == :ignore
202
225
  end
@@ -385,6 +408,102 @@ module Doing
385
408
  false
386
409
  end
387
410
 
411
+ def tag_value(tag)
412
+ res = @title.match(/@#{tag.sub(/^@/, '').wildcard_to_rx}\((.*?)\)/)
413
+ res ? res[1] : nil
414
+ end
415
+
416
+ def number_or_date(value)
417
+ return nil unless value
418
+
419
+ if value.strip =~ /^[0-9.]+%?$/
420
+ value.strip.to_f
421
+ else
422
+ value.strip.chronify(guess: :end)
423
+ end
424
+ end
425
+
426
+ def split_value_query(query)
427
+ val_rx = /^(!)?@?(\S+) +(!?[<>=][=*]?|[$*^]=) +(.*?)$/
428
+ query.match(val_rx)
429
+ end
430
+
431
+ def any_values?(queries)
432
+ return true if queries.nil? || queries.empty?
433
+
434
+ queries.each do |q|
435
+ parts = split_value_query(q)
436
+ return true if tag_value_matches?(parts[2], parts[3], parts[4], parts[1])
437
+ end
438
+ false
439
+ end
440
+
441
+ def all_values?(queries)
442
+ return true if queries.nil? || queries.empty?
443
+
444
+ queries.each do |q|
445
+ parts = split_value_query(q)
446
+ return false unless tag_value_matches?(parts[2], parts[3], parts[4], parts[1])
447
+ end
448
+ true
449
+ end
450
+
451
+ def no_values?(queries)
452
+ return true if queries.nil? || queries.empty?
453
+
454
+ queries.each do |q|
455
+ parts = split_value_query(q)
456
+ return false if tag_value_matches?(parts[2], parts[3], parts[4], parts[1])
457
+ end
458
+ true
459
+ end
460
+
461
+ def tag_value_matches?(tag, comp, value, negate)
462
+ if all_tags?([tag])
463
+ tag_val = tag_value(tag)
464
+
465
+ if (value.chronify.nil? && value =~ /[a-z]/i && comp =~ /^!?==?$/) || comp =~ /[$*^]=/
466
+ is_match = case comp
467
+ when /\^=/
468
+ tag_val =~ /^#{value.wildcard_to_rx}/i
469
+ when /\$=/
470
+ tag_val =~ /#{value.wildcard_to_rx}$/i
471
+ when %r{==}
472
+ tag_val =~ /^#{value.wildcard_to_rx}$/i
473
+ else
474
+ tag_val =~ /#{value.wildcard_to_rx}/i
475
+ end
476
+
477
+ comp =~ /!/ || negate ? !is_match : is_match
478
+ else
479
+ tag_val = number_or_date(tag_val)
480
+ val = number_or_date(value)
481
+
482
+ return false if val.nil? || tag_val.nil?
483
+
484
+ return false unless val.class == tag_val.class
485
+
486
+ matches = case comp
487
+ when /^<$/
488
+ tag_val < val
489
+ when /^<=$/
490
+ tag_val <= val
491
+ when /^>$/
492
+ tag_val > val
493
+ when /^>=$/
494
+ tag_val >= val
495
+ when /^!=/
496
+ tag_val != val
497
+ when /^=/
498
+ tag_val == val
499
+ end
500
+ negate.nil? ? matches : !matches
501
+ end
502
+ else
503
+ false
504
+ end
505
+ end
506
+
388
507
  def to_query(query)
389
508
  parser = BooleanTermParser::QueryParser.new
390
509
  transformer = BooleanTermParser::QueryTransformer.new
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.12'
2
+ VERSION = '2.1.13'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -640,6 +640,7 @@ module Doing
640
640
  ## @option opt [Boolean] :yesterday (false) limit to entries from yesterday
641
641
  ## @option opt [Number] :count (0) max entries to return
642
642
  ## @option opt [String] :age (new) 'old' or 'new'
643
+ ## @option opt [Array] :val (nil) Array of tag value queries
643
644
  ##
644
645
  def filter_items(items = Items.new, opt: {})
645
646
  time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
@@ -701,6 +702,16 @@ module Doing
701
702
  keep = false if finished
702
703
  end
703
704
 
705
+ if keep && opt[:val]&.count&.positive?
706
+ bool = opt[:bool].normalize_bool if opt[:bool]
707
+ bool ||= :and
708
+ bool = :and if bool == :pattern
709
+
710
+ val_match = opt[:val].nil? || opt[:val].empty? ? true : item.tag_values?(opt[:val], bool)
711
+ keep = false unless val_match
712
+ keep = opt[:not] ? !keep : keep
713
+ end
714
+
704
715
  if keep && opt[:tag]
705
716
  opt[:tag_bool] = opt[:bool].normalize_bool if opt[:bool]
706
717
  opt[:tag_bool] ||= :and
@@ -887,7 +898,7 @@ module Doing
887
898
  opt[:query] = "!#{opt[:query]}" if opt[:not]
888
899
  opt[:multiple] = true
889
900
  opt[:show_if_single] = true
890
- filter_options = %i[after before case date_filter from fuzzy not search section].each_with_object({}) {
901
+ filter_options = %i[after before case date_filter from fuzzy not search section val].each_with_object({}) {
891
902
  |k, hsh| hsh[k] = opt[k]
892
903
  }
893
904
  items = filter_items(Items.new, opt: filter_options)
@@ -1221,14 +1232,17 @@ module Doing
1221
1232
  end
1222
1233
 
1223
1234
  tag = tag.strip
1224
- if opt[:remove] || opt[:rename]
1235
+ if opt[:remove] || opt[:rename] || opt[:value]
1225
1236
  rename_to = nil
1226
- if opt[:rename]
1237
+ if opt[:value]
1238
+ rename_to = tag
1239
+ elsif opt[:rename]
1227
1240
  rename_to = tag
1228
1241
  tag = opt[:rename]
1229
1242
  end
1230
1243
  old_title = item.title.dup
1231
- item.title.tag!(tag, remove: opt[:remove], rename_to: rename_to, regex: opt[:regex])
1244
+ force = opt[:value].nil? ? false : true
1245
+ item.title.tag!(tag, remove: opt[:remove], rename_to: rename_to, regex: opt[:regex], value: opt[:value], force: force)
1232
1246
  if old_title != item.title
1233
1247
  removed << tag
1234
1248
  added << rename_to if rename_to
@@ -1823,7 +1837,8 @@ module Doing
1823
1837
  case: options[:case],
1824
1838
  not: options[:negate],
1825
1839
  config_template: 'last',
1826
- delete: options[:delete]
1840
+ delete: options[:delete],
1841
+ val: options[:val]
1827
1842
  }
1828
1843
 
1829
1844
  if options[:tag]
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.12
4
+ version: 2.1.13
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-01-12 00:00:00.000000000 Z
11
+ date: 2022-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: safe_yaml