doing 1.0.83 → 1.0.84
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/doing +114 -18
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +78 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c11e6c75768b8dc2db3a36c5cdd572ad03eb884e118848ebbe413df2988a53df
|
4
|
+
data.tar.gz: a3f45b396e4c6b06bab65d24007f0437e72687c6811f559ece8f6c5ca2e7bbba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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]
|
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
|
-
|
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
|
-
|
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]
|
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
|
-
|
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
|
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]
|
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
|
-
|
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]
|
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
|
-
|
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]
|
615
|
+
c.flag %i[s section]
|
594
616
|
|
595
617
|
c.action do |_global_options, options, args|
|
596
|
-
|
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[:
|
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]
|
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
|
-
|
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]
|
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
|
-
|
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
|
-
|
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
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 =~
|
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
|
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 =
|
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 !=
|
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 !=
|
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.
|
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-
|
11
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|