doing 1.0.83 → 1.0.84

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb85f27f305f246d4ab182268c9e5188da67f22fde46d3ee4ae716996c78b2c3
4
- data.tar.gz: 7b302748d9837511adc77679fd619c6daf85b2f7e15f541d530c8cc211e0aac3
3
+ metadata.gz: c11e6c75768b8dc2db3a36c5cdd572ad03eb884e118848ebbe413df2988a53df
4
+ data.tar.gz: a3f45b396e4c6b06bab65d24007f0437e72687c6811f559ece8f6c5ca2e7bbba
5
5
  SHA512:
6
- metadata.gz: dbf5e04626a97e5287c2417cf5afffd6516860a1fa5f3ed64e93fe15bdc62b85f045d0a54adc08c774b4d711add29f02799cf3d4a2c22853e1273a691d0a9f00
7
- data.tar.gz: 87bf6eac2e770b161c8ae4fd2fee4adea5ed261b828f2142997858393a627e0d36788981fe52a4c66486f442da2de349ce1ac157732d824b0ef633e4dcbdc703
6
+ metadata.gz: 7be6844f9f6caa072014afeded310cbaddf2a15380fde5498aea0f980dd5e8448ca44f5c5d9692a2075818f632bbbd19cce93e0db338c621a487abed8259f555
7
+ data.tar.gz: d0af857fee4113e2055af031059901b56e2ff94e849f9d3a0d167d8edde0519e4d6a6ebdeef55050ee313ed628ba6fa2fbd17e73cfc66143e57e7a2c42f93c8f
data/README.md CHANGED
@@ -27,7 +27,7 @@ If there's something I want to look at later but doesn't need to be added to a t
27
27
 
28
28
  ## Installation
29
29
 
30
- The current version of `doing` is <!--VER-->1.0.82<!--END VER-->.
30
+ The current version of `doing` is <!--VER-->1.0.83<!--END VER-->.
31
31
 
32
32
  $ [sudo] gem install doing
33
33
 
data/bin/doing CHANGED
@@ -55,7 +55,7 @@ arg_name 'ENTRY'
55
55
  command %i[now next] do |c|
56
56
  c.desc 'Section'
57
57
  c.arg_name 'NAME'
58
- c.flag %i[s section], default_value: wwid.current_section
58
+ c.flag %i[s section]
59
59
 
60
60
  c.desc "Edit entry with #{ENV['EDITOR']}"
61
61
  c.switch %i[e editor], negatable: false, default_value: false
@@ -84,7 +84,11 @@ command %i[now next] do |c|
84
84
  date = Time.now
85
85
  end
86
86
 
87
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
87
+ if options[:section]
88
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
89
+ else
90
+ options[:section] = wwid.config['current_section']
91
+ end
88
92
 
89
93
  if options[:e] || (args.empty? && $stdin.stat.size.zero?)
90
94
  exit_now! 'No EDITOR variable defined in environment' if ENV['EDITOR'].nil?
@@ -135,7 +139,9 @@ command :note do |c|
135
139
  c.switch %i[r remove], negatable: false, default_value: false
136
140
 
137
141
  c.action do |_global_options, options, args|
138
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
142
+ if options[:section]
143
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
144
+ end
139
145
 
140
146
  if options[:e] || (args.empty? && $stdin.stat.size.zero? && !options[:r])
141
147
  exit_now! 'No EDITOR variable defined in environment' if ENV['EDITOR'].nil?
@@ -176,7 +182,7 @@ arg_name 'ENTRY'
176
182
  command :meanwhile do |c|
177
183
  c.desc 'Section'
178
184
  c.arg_name 'NAME'
179
- c.flag %i[s section], default_value: wwid.current_section
185
+ c.flag %i[s section]
180
186
 
181
187
  c.desc "Edit entry with #{ENV['EDITOR']}"
182
188
  c.switch %i[e editor], negatable: false, default_value: false
@@ -201,7 +207,11 @@ command :meanwhile do |c|
201
207
  date = Time.now
202
208
  end
203
209
 
204
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
210
+ if options[:section]
211
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
212
+ else
213
+ section = wwid.config['current_section']
214
+ end
205
215
  input = ''
206
216
 
207
217
  if options[:e]
@@ -308,7 +318,7 @@ command :select do |c|
308
318
  c.arg_name 'FILE'
309
319
  c.flag %i[save_to]
310
320
 
311
- c.desc 'Output format for export (doing|taskpaper|csv|html|json|template|timeline)'
321
+ c.desc 'Output entries to format (doing|taskpaper|csv|html|json|template|timeline)'
312
322
  c.arg_name 'FORMAT'
313
323
  c.flag %i[o output], must_match: /^(?:doing|taskpaper|html|csv|json|template|timeline)$/i
314
324
 
@@ -399,7 +409,7 @@ command %i[done did] do |c|
399
409
 
400
410
  c.desc 'Section'
401
411
  c.arg_name 'NAME'
402
- c.flag %i[s section], default_value: wwid.current_section
412
+ c.flag %i[s section]
403
413
 
404
414
  c.desc "Edit entry with #{ENV['EDITOR']}"
405
415
  c.switch %i[e editor], negatable: false, default_value: false
@@ -440,7 +450,11 @@ command %i[done did] do |c|
440
450
  donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ''
441
451
  end
442
452
 
443
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
453
+ if options[:section]
454
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
455
+ else
456
+ section = wwid.config['current_section']
457
+ end
444
458
 
445
459
  if options[:e]
446
460
  exit_now! 'No EDITOR variable defined in environment' if ENV['EDITOR'].nil?
@@ -497,7 +511,7 @@ command :cancel do |c|
497
511
 
498
512
  c.desc 'Section'
499
513
  c.arg_name 'NAME'
500
- c.flag %i[s section], default_value: wwid.current_section
514
+ c.flag %i[s section]
501
515
 
502
516
  c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2)'
503
517
  c.arg_name 'TAG'
@@ -511,7 +525,11 @@ command :cancel do |c|
511
525
  c.switch %i[u unfinished], negatable: false, default_value: false
512
526
 
513
527
  c.action do |_global_options, options, args|
514
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
528
+ if options[:section]
529
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
530
+ else
531
+ section = wwid.config['current_section']
532
+ end
515
533
 
516
534
  if options[:tag].nil?
517
535
  tags = []
@@ -564,6 +582,10 @@ command :finish do |c|
564
582
  c.arg_name 'INTERVAL'
565
583
  c.flag %i[t took]
566
584
 
585
+ c.desc %(Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm). If used, ignores --back.)
586
+ c.arg_name 'DATE_STRING'
587
+ c.flag [:at]
588
+
567
589
  c.desc 'Finish the last X entries containing TAG.
568
590
  Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool'
569
591
  c.arg_name 'TAG'
@@ -590,17 +612,31 @@ command :finish do |c|
590
612
 
591
613
  c.desc 'Section'
592
614
  c.arg_name 'NAME'
593
- c.flag %i[s section], default_value: wwid.current_section
615
+ c.flag %i[s section]
594
616
 
595
617
  c.action do |_global_options, options, args|
596
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
618
+ if options[:section]
619
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
620
+ else
621
+ section = wwid.config['current_section']
622
+ end
597
623
 
598
624
  unless options[:auto]
625
+ if options[:took]
626
+ took = wwid.chronify_qty(options[:took])
627
+ exit_now! 'Unable to parse date string for --took' if took.nil?
628
+ end
629
+
599
630
  exit_now! '--back and --took cannot be used together' if options[:back] && options[:took]
600
631
 
601
632
  exit_now! '--search and --tag cannot be used together' if options[:search] && options[:tag]
602
633
 
603
- if options[:back]
634
+ if options[:at]
635
+ finish_date = wwid.chronify(options[:at])
636
+ exit_now! 'Unable to parse date string for --at' if finish_date.nil?
637
+
638
+ date = options[:took] ? finish_date - took : finish_date
639
+ elsif options[:back]
604
640
  date = wwid.chronify(options[:back])
605
641
 
606
642
  exit_now! 'Unable to parse date string' if date.nil?
@@ -826,7 +862,7 @@ desc 'Mark last entry as highlighted'
826
862
  command [:mark, :flag] do |c|
827
863
  c.desc 'Section'
828
864
  c.arg_name 'NAME'
829
- c.flag %i[s section], default_value: wwid.current_section
865
+ c.flag %i[s section]
830
866
 
831
867
  c.desc 'Remove mark'
832
868
  c.switch %i[r remove], negatable: false, default_value: false
@@ -1386,7 +1422,11 @@ command :view do |c|
1386
1422
  wwid.guess_view(args[0])
1387
1423
  end
1388
1424
 
1389
- section = wwid.guess_section(options[:s]) || options[:s].cap_first if options[:s]
1425
+ if options[:section]
1426
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
1427
+ else
1428
+ section = wwid.config['current_section']
1429
+ end
1390
1430
 
1391
1431
  view = wwid.get_view(title)
1392
1432
  if view
@@ -1553,6 +1593,48 @@ command :archive do |c|
1553
1593
  end
1554
1594
  end
1555
1595
 
1596
+ desc 'Move entries to archive file'
1597
+ command :rotate do |c|
1598
+ c.desc 'How many items to keep in each section (most recent)'
1599
+ c.arg_name 'X'
1600
+ c.flag %i[k keep], must_match: /^\d+$/, type: Integer
1601
+
1602
+ c.desc 'Section to rotate'
1603
+ c.arg_name 'SECTION_NAME'
1604
+ c.flag %i[s section], default_value: 'All'
1605
+
1606
+ c.desc 'Tag filter, combine multiple tags with a comma. Added for compatibility with other commands.'
1607
+ c.arg_name 'TAG'
1608
+ c.flag [:tag]
1609
+
1610
+ c.desc 'Tag boolean (AND|OR|NOT)'
1611
+ c.arg_name 'BOOLEAN'
1612
+ c.flag [:bool], must_match: /(?:and|all|any|or|not|none)/i, default_value: 'AND'
1613
+
1614
+ c.desc 'Search filter'
1615
+ c.arg_name 'QUERY'
1616
+ c.flag [:search]
1617
+
1618
+ c.action do |_global_options, options, args|
1619
+ if options[:section] && options[:section] !~ /^all$/i
1620
+ options[:section] = wwid.guess_section(options[:section])
1621
+ end
1622
+
1623
+ options[:bool] = case options[:bool]
1624
+ when /(and|all)/i
1625
+ 'AND'
1626
+ when /(any|or)/i
1627
+ 'OR'
1628
+ when /(not|none)/i
1629
+ 'NOT'
1630
+ else
1631
+ 'AND'
1632
+ end
1633
+
1634
+ wwid.rotate(options)
1635
+ end
1636
+ end
1637
+
1556
1638
  desc 'Open the "doing" file in an editor'
1557
1639
  long_desc "`doing open` defaults to using the editor_app setting in #{wwid.config_file} (#{wwid.config.key?('editor_app') ? wwid.config['editor_app'] : 'not set'})"
1558
1640
  command :open do |c|
@@ -1662,12 +1744,15 @@ command :import do |c|
1662
1744
 
1663
1745
  c.desc 'Target section'
1664
1746
  c.arg_name 'NAME'
1665
- c.flag %i[s section], default_value: wwid.current_section
1747
+ c.flag %i[s section]
1666
1748
 
1667
1749
  c.desc 'Tag all imported entries'
1668
1750
  c.arg_name 'TAGS'
1669
1751
  c.flag :tag
1670
1752
 
1753
+ c.desc 'Autotag entries'
1754
+ c.switch :autotag, negatable: true, default_value: true
1755
+
1671
1756
  c.desc 'Prefix entries with'
1672
1757
  c.arg_name 'PREFIX'
1673
1758
  c.flag :prefix
@@ -1677,11 +1762,22 @@ command :import do |c|
1677
1762
 
1678
1763
  c.action do |_global_options, options, args|
1679
1764
 
1680
- section = wwid.guess_section(options[:s]) || options[:s].cap_first
1765
+ if options[:section]
1766
+ section = wwid.guess_section(options[:section]) || options[:section].cap_first
1767
+ else
1768
+ section = wwid.config['current_section']
1769
+ end
1681
1770
 
1682
1771
  if options[:type] =~ /^tim/i
1683
1772
  args.each do |path|
1684
- wwid.import_timing(path, { section: section, tag: options[:tag], prefix: options[:prefix], no_overlap: !options[:overlap] })
1773
+ options = {
1774
+ autotag: options[:autotag],
1775
+ no_overlap: !options[:overlap],
1776
+ prefix: options[:prefix],
1777
+ section: section,
1778
+ tag: options[:tag]
1779
+ }
1780
+ wwid.import_timing(path, options)
1685
1781
  wwid.write(wwid.doing_file)
1686
1782
  end
1687
1783
  else
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '1.0.83'
2
+ VERSION = '1.0.84'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -425,8 +425,8 @@ class WWID
425
425
  ## @param guessed (Boolean) already guessed and failed
426
426
  ##
427
427
  def guess_section(frag, guessed: false)
428
- return 'All' if frag =~ /all/i
429
-
428
+ return 'All' if frag =~ /^all$/i
429
+ frag ||= @current_section
430
430
  sections.each { |section| return section.cap_first if frag.downcase == section.downcase }
431
431
  section = false
432
432
  re = frag.split('').join('.*?')
@@ -627,6 +627,7 @@ class WWID
627
627
  def import_timing(path, opt = {})
628
628
  section = opt[:section] || @current_section
629
629
  opt[:no_overlap] ||= false
630
+ opt[:autotag] ||= @auto_tag
630
631
 
631
632
  add_section(section) unless @content.has_key?(section)
632
633
 
@@ -657,7 +658,7 @@ class WWID
657
658
  title += " @#{tag}"
658
659
  end
659
660
  end
660
- title = autotag(title) if @auto_tag
661
+ title = autotag(title) if opt[:autotag]
661
662
  title += " @done(#{end_time.strftime('%Y-%m-%d %H:%M')})"
662
663
  title.gsub!(/ +/, ' ')
663
664
  title.strip!
@@ -1521,6 +1522,77 @@ class WWID
1521
1522
  end
1522
1523
  end
1523
1524
 
1525
+ ##
1526
+ ## @brief Rename doing file with date and start fresh one
1527
+ ##
1528
+ def rotate(opt = {})
1529
+ count = opt[:keep] || 0
1530
+ tags = []
1531
+ tags.concat(opt[:tag].split(/ *, */).map { |t| t.sub(/^@/, '').strip }) if opt[:tag]
1532
+ bool = opt[:bool] || :and
1533
+ sect = opt[:section] !~ /^all$/i ? guess_section(opt[:section]) : 'all'
1534
+
1535
+ if sect =~ /^all$/i
1536
+ all_sections = sections.dup
1537
+ else
1538
+ all_sections = [sect]
1539
+ end
1540
+
1541
+ counter = 0
1542
+ new_content = {}
1543
+
1544
+
1545
+ all_sections.each do |section|
1546
+ items = @content[section]['items'].dup
1547
+ new_content[section] = {}
1548
+ new_content[section]['original'] = @content[section]['original']
1549
+ new_content[section]['items'] = []
1550
+
1551
+ moved_items = []
1552
+ if !tags.empty? || opt[:search]
1553
+ items.delete_if do |item|
1554
+ if ((!tags.empty? && item.has_tags?(tags, bool)) || (opt[:search] && item.matches_search?(opt[:search].to_s)))
1555
+ moved_items.push(item)
1556
+ counter += 1
1557
+ true
1558
+ else
1559
+ false
1560
+ end
1561
+ end
1562
+ @content[section]['items'] = items
1563
+ new_content[section]['items'] = moved_items
1564
+ @results.push("Rotated #{moved_items.length} items from #{section}")
1565
+ else
1566
+ new_content[section]['items'] = []
1567
+ moved_items = []
1568
+
1569
+ count = items.length if items.length < count
1570
+
1571
+ if items.count > count
1572
+ moved_items.concat(items[count..-1])
1573
+ else
1574
+ moved_items.concat(items)
1575
+ end
1576
+
1577
+ @content[section]['items'] = if count.zero?
1578
+ []
1579
+ else
1580
+ items[0..count - 1]
1581
+ end
1582
+ new_content[section]['items'] = moved_items
1583
+
1584
+ @results.push("Rotated #{items.length - count} items from #{section}")
1585
+ end
1586
+ end
1587
+
1588
+ write(@doing_file)
1589
+
1590
+ file = @doing_file.sub(/(\.\w+)$/, "_#{Time.now.strftime('%Y-%m-%d%H:%M')}\\1")
1591
+ @content = new_content
1592
+
1593
+ write(file)
1594
+ end
1595
+
1524
1596
  ##
1525
1597
  ## @brief Generate a menu of sections and allow user selection
1526
1598
  ##
@@ -1925,7 +1997,7 @@ class WWID
1925
1997
  ## @param section (String) The source section
1926
1998
  ## @param options (Hash) Options
1927
1999
  ##
1928
- def archive(section = 'Currently', options = {})
2000
+ def archive(section = @current_section, options = {})
1929
2001
  count = options[:keep] || 0
1930
2002
  destination = options[:destination] || 'Archive'
1931
2003
  tags = options[:tags] || []
@@ -1984,7 +2056,7 @@ class WWID
1984
2056
  end
1985
2057
  end
1986
2058
  moved_items.each do |item|
1987
- if label && section != 'Currently'
2059
+ if label && section != @current_section
1988
2060
  item['title'] =
1989
2061
  item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
1990
2062
  end
@@ -1997,7 +2069,7 @@ class WWID
1997
2069
  count = items.length if items.length < count
1998
2070
 
1999
2071
  items.map! do |item|
2000
- if label && section != 'Currently'
2072
+ if label && section != @current_section
2001
2073
  item['title'] =
2002
2074
  item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
2003
2075
  end
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: 1.0.83
4
+ version: 1.0.84
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-13 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake