doing 1.0.82 → 1.0.83
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 +4 -4
- data/README.md +10 -4
- data/bin/doing +34 -9
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +55 -31
- 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: fb85f27f305f246d4ab182268c9e5188da67f22fde46d3ee4ae716996c78b2c3
|
4
|
+
data.tar.gz: 7b302748d9837511adc77679fd619c6daf85b2f7e15f541d530c8cc211e0aac3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbf5e04626a97e5287c2417cf5afffd6516860a1fa5f3ed64e93fe15bdc62b85f045d0a54adc08c774b4d711add29f02799cf3d4a2c22853e1273a691d0a9f00
|
7
|
+
data.tar.gz: 87bf6eac2e770b161c8ae4fd2fee4adea5ed261b828f2142997858393a627e0d36788981fe52a4c66486f442da2de349ce1ac157732d824b0ef633e4dcbdc703
|
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.82<!--END VER-->.
|
31
31
|
|
32
32
|
$ [sudo] gem install doing
|
33
33
|
|
@@ -245,7 +245,7 @@ You can create your own "views" in the `~/.doingrc` file and view them with `doi
|
|
245
245
|
|
246
246
|
views:
|
247
247
|
old:
|
248
|
-
section:
|
248
|
+
section: Archive
|
249
249
|
count: 5
|
250
250
|
wrap_width: 0
|
251
251
|
date_format: '%F %_I:%M%P'
|
@@ -253,6 +253,10 @@ You can create your own "views" in the `~/.doingrc` file and view them with `doi
|
|
253
253
|
order: asc
|
254
254
|
tags: done finished cancelled
|
255
255
|
tags_bool: ANY
|
256
|
+
only_timed: false
|
257
|
+
tag_sort: time
|
258
|
+
tag_order: asc
|
259
|
+
totals: true
|
256
260
|
|
257
261
|
You can add additional custom views. Just nest them under the `views` key (indented two spaces from the edge). Multiple views would look like this:
|
258
262
|
|
@@ -276,7 +280,9 @@ You can add new sections with `doing add_section section_name`. You can also cre
|
|
276
280
|
|
277
281
|
The `tags` and `tags_bool` keys allow you to specify tags that the view is filtered by. You can list multiple tags separated by spaces, and then use `tags_bool` to specify `ALL`, `ANY`, or `NONE` to determine how it handles the multiple tags.
|
278
282
|
|
279
|
-
The `order` key defines the sort order of the output. This is applied _after_ the tasks are retrieved and cut off at the maximum number specified in `count`.
|
283
|
+
The `order` key defines the sort order of the output (asc or desc). This is applied _after_ the tasks are retrieved and cut off at the maximum number specified in `count`.
|
284
|
+
|
285
|
+
You can include tag timers and totals in the output with `totals: true`. Control tag output using `tag_sort` (name or title) and `tag_order` (asc or desc). You can also output only timed entries using `only_timed: true`. All of these options can be overridden using flags on the `doing view` command.
|
280
286
|
|
281
287
|
Regarding colors, you can use them to create very nice displays if you're outputting to a color terminal. Example:
|
282
288
|
|
@@ -291,7 +297,7 @@ Outputs:
|
|
291
297
|
|
292
298
|

|
293
299
|
|
294
|
-
You can also specify a default output format for a view. Most of the optional output formats override the template specification (`html`, `csv`, `json`). If the `view` command is used with the `-o` flag, it will override what's specified in the
|
300
|
+
You can also specify a default output format for a view. Most of the optional output formats override the template specification (`html`, `csv`, `json`). If the `view` command is used with the `-o` flag, it will override what's specified for the view in the config.
|
295
301
|
|
296
302
|
### Colors
|
297
303
|
|
data/bin/doing
CHANGED
@@ -1344,13 +1344,14 @@ command :colors do |c|
|
|
1344
1344
|
end
|
1345
1345
|
|
1346
1346
|
desc 'Display a user-created view'
|
1347
|
+
long_desc 'Command line options override associated view settings'
|
1347
1348
|
arg_name 'VIEW_NAME'
|
1348
1349
|
command :view do |c|
|
1349
|
-
c.desc 'Section
|
1350
|
+
c.desc 'Section'
|
1350
1351
|
c.arg_name 'NAME'
|
1351
1352
|
c.flag %i[s section]
|
1352
1353
|
|
1353
|
-
c.desc 'Count to display
|
1354
|
+
c.desc 'Count to display'
|
1354
1355
|
c.arg_name 'COUNT'
|
1355
1356
|
c.flag %i[c count], must_match: /^\d+$/, type: Integer
|
1356
1357
|
|
@@ -1368,12 +1369,14 @@ command :view do |c|
|
|
1368
1369
|
c.switch [:color], default_value: true, negatable: true
|
1369
1370
|
|
1370
1371
|
c.desc 'Sort tags by (name|time)'
|
1371
|
-
default = 'time'
|
1372
|
-
default = wwid.config['tag_sort'] if wwid.config.key?('tag_sort')
|
1373
1372
|
c.arg_name 'KEY'
|
1374
|
-
c.flag [:tag_sort], must_match: /^(?:name|time)$/i
|
1373
|
+
c.flag [:tag_sort], must_match: /^(?:name|time)$/i
|
1375
1374
|
|
1376
|
-
c.desc '
|
1375
|
+
c.desc 'Tag sort direction (asc|desc)'
|
1376
|
+
c.arg_name 'DIRECTION'
|
1377
|
+
c.flag [:tag_order], must_match: /^(?:a(?:sc)?|d(?:esc)?)$/i
|
1378
|
+
|
1379
|
+
c.desc 'Only show items with recorded time intervals (override view settings)'
|
1377
1380
|
c.switch [:only_timed], default_value: false, negatable: false
|
1378
1381
|
|
1379
1382
|
c.action do |_global_options, options, args|
|
@@ -1422,10 +1425,31 @@ command :view do |c|
|
|
1422
1425
|
end
|
1423
1426
|
order = view.key?('order') ? view['order'] : 'asc'
|
1424
1427
|
|
1425
|
-
|
1428
|
+
totals = if options[:totals]
|
1429
|
+
true
|
1430
|
+
else
|
1431
|
+
view.key?('totals') ? view['totals'] : false
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
options[:t] = true if totals
|
1426
1435
|
options[:output]&.downcase!
|
1427
|
-
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
1428
1436
|
|
1437
|
+
options[:sort_tags] = if options[:tag_sort]
|
1438
|
+
options[:tag_sort] =~ /^n/i ? true : false
|
1439
|
+
elsif view.key?('tag_sort')
|
1440
|
+
view['tag_sort'] =~ /^n/i ? true : false
|
1441
|
+
else
|
1442
|
+
false
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
tag_order = if options[:tag_order]
|
1446
|
+
options[:tag_order] =~ /^d/i ? 'desc' : 'asc'
|
1447
|
+
elsif view.key?('tag_order')
|
1448
|
+
view['tag_order'] =~ /^d/i ? 'desc' : 'asc'
|
1449
|
+
else
|
1450
|
+
'asc'
|
1451
|
+
end
|
1452
|
+
warn "TAG ORDER: #{options[:tag_order]}"
|
1429
1453
|
opts = {
|
1430
1454
|
count: count,
|
1431
1455
|
format: format,
|
@@ -1436,10 +1460,11 @@ command :view do |c|
|
|
1436
1460
|
section: section,
|
1437
1461
|
sort_tags: options[:sort_tags],
|
1438
1462
|
tag_filter: tag_filter,
|
1463
|
+
tag_order: tag_order,
|
1439
1464
|
tags_color: tags_color,
|
1440
1465
|
template: template,
|
1441
1466
|
times: options[:t],
|
1442
|
-
totals:
|
1467
|
+
totals: totals
|
1443
1468
|
}
|
1444
1469
|
|
1445
1470
|
puts wwid.list_section(opts)
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -84,6 +84,7 @@ class WWID
|
|
84
84
|
##
|
85
85
|
def configure(opt = {})
|
86
86
|
@timers = {}
|
87
|
+
@recorded_items = []
|
87
88
|
opt[:ignore_local] ||= false
|
88
89
|
|
89
90
|
@config_file ||= File.join(@user_home, @default_config_file)
|
@@ -583,17 +584,17 @@ class WWID
|
|
583
584
|
end
|
584
585
|
|
585
586
|
def same_time?(item_a, item_b)
|
586
|
-
item_a['date'] == item_b['date'] ? get_interval(item_a, false) == get_interval(item_b, false) : false
|
587
|
+
item_a['date'] == item_b['date'] ? get_interval(item_a, formatted: false, record: false) == get_interval(item_b, formatted: false, record: false) : false
|
587
588
|
end
|
588
589
|
|
589
590
|
def overlapping_time?(item_a, item_b)
|
590
591
|
return true if same_time?(item_a, item_b)
|
591
592
|
|
592
593
|
start_a = item_a['date']
|
593
|
-
interval = get_interval(item_a, false)
|
594
|
+
interval = get_interval(item_a, formatted: false, record: false)
|
594
595
|
end_a = interval ? start_a + interval.to_i : start_a
|
595
596
|
start_b = item_b['date']
|
596
|
-
interval = get_interval(item_b, false)
|
597
|
+
interval = get_interval(item_b, formatted: false, record: false)
|
597
598
|
end_b = interval ? start_b + interval.to_i : start_b
|
598
599
|
(start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
|
599
600
|
end
|
@@ -1569,20 +1570,21 @@ class WWID
|
|
1569
1570
|
def list_section(opt = {})
|
1570
1571
|
opt[:count] ||= 0
|
1571
1572
|
count = opt[:count] - 1
|
1572
|
-
opt[:section] ||= nil
|
1573
|
-
opt[:format] ||= @default_date_format
|
1574
|
-
opt[:template] ||= @default_template
|
1575
1573
|
opt[:age] ||= 'newest'
|
1574
|
+
opt[:date_filter] ||= []
|
1575
|
+
opt[:format] ||= @default_date_format
|
1576
|
+
opt[:only_timed] ||= false
|
1576
1577
|
opt[:order] ||= 'desc'
|
1577
|
-
opt[:
|
1578
|
+
opt[:search] ||= false
|
1579
|
+
opt[:section] ||= nil
|
1580
|
+
opt[:sort_tags] ||= false
|
1578
1581
|
opt[:tag_filter] ||= false
|
1582
|
+
opt[:tag_order] ||= 'asc'
|
1579
1583
|
opt[:tags_color] ||= false
|
1584
|
+
opt[:template] ||= @default_template
|
1580
1585
|
opt[:times] ||= false
|
1586
|
+
opt[:today] ||= false
|
1581
1587
|
opt[:totals] ||= false
|
1582
|
-
opt[:sort_tags] ||= false
|
1583
|
-
opt[:search] ||= false
|
1584
|
-
opt[:only_timed] ||= false
|
1585
|
-
opt[:date_filter] ||= []
|
1586
1588
|
|
1587
1589
|
# opt[:highlight] ||= true
|
1588
1590
|
section = ''
|
@@ -1635,7 +1637,7 @@ class WWID
|
|
1635
1637
|
|
1636
1638
|
if opt[:only_timed]
|
1637
1639
|
items.delete_if do |item|
|
1638
|
-
get_interval(item) == false
|
1640
|
+
get_interval(item, record: false) == false
|
1639
1641
|
end
|
1640
1642
|
end
|
1641
1643
|
|
@@ -1670,7 +1672,7 @@ class WWID
|
|
1670
1672
|
arr = i['note'].map { |line| line.strip }.delete_if { |e| e =~ /^\s*$/ }
|
1671
1673
|
note = arr.join("\n") unless arr.nil?
|
1672
1674
|
end
|
1673
|
-
interval = get_interval(i, false) if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
1675
|
+
interval = get_interval(i, formatted: false) if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
1674
1676
|
interval ||= 0
|
1675
1677
|
output.push(CSV.generate_line([i['date'], i['title'], note, interval, i['section']]))
|
1676
1678
|
end
|
@@ -1689,7 +1691,7 @@ class WWID
|
|
1689
1691
|
end
|
1690
1692
|
if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
1691
1693
|
end_date = Time.parse(Regexp.last_match(1))
|
1692
|
-
interval = get_interval(i, false)
|
1694
|
+
interval = get_interval(i, formatted: false)
|
1693
1695
|
end
|
1694
1696
|
end_date ||= ''
|
1695
1697
|
interval ||= 0
|
@@ -1738,7 +1740,7 @@ class WWID
|
|
1738
1740
|
out = {
|
1739
1741
|
'section' => section,
|
1740
1742
|
'items' => items_out,
|
1741
|
-
'timers' => tag_times('json', opt[:sort_tags])
|
1743
|
+
'timers' => tag_times(format: 'json', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order])
|
1742
1744
|
}.to_json
|
1743
1745
|
elsif opt[:output] == 'timeline'
|
1744
1746
|
template = <<~EOTEMPLATE
|
@@ -1819,7 +1821,7 @@ class WWID
|
|
1819
1821
|
css_template
|
1820
1822
|
end
|
1821
1823
|
|
1822
|
-
totals = opt[:totals] ? tag_times('html', opt[:sort_tags]) : ''
|
1824
|
+
totals = opt[:totals] ? tag_times(format: 'html', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
|
1823
1825
|
engine = Haml::Engine.new(template)
|
1824
1826
|
out = engine.render(Object.new,
|
1825
1827
|
{ :@items => items_out, :@page_title => page_title, :@style => style, :@totals => totals })
|
@@ -1860,7 +1862,7 @@ class WWID
|
|
1860
1862
|
|
1861
1863
|
output.sub!(/%date/, item['date'].strftime(opt[:format]))
|
1862
1864
|
|
1863
|
-
interval = get_interval(item) if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
1865
|
+
interval = get_interval(item, record: true) if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
1864
1866
|
interval ||= ''
|
1865
1867
|
output.sub!(/%interval/, interval)
|
1866
1868
|
|
@@ -1910,7 +1912,8 @@ class WWID
|
|
1910
1912
|
|
1911
1913
|
out += "#{output}\n"
|
1912
1914
|
end
|
1913
|
-
|
1915
|
+
|
1916
|
+
out += tag_times(format: 'text', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) if opt[:totals]
|
1914
1917
|
end
|
1915
1918
|
out
|
1916
1919
|
end
|
@@ -2173,11 +2176,15 @@ class WWID
|
|
2173
2176
|
end
|
2174
2177
|
|
2175
2178
|
##
|
2176
|
-
## @brief Get total elapsed time for all tags in
|
2179
|
+
## @brief Get total elapsed time for all tags in
|
2180
|
+
## selection
|
2177
2181
|
##
|
2178
|
-
## @param format
|
2182
|
+
## @param format (String) return format (html,
|
2183
|
+
## json, or text)
|
2184
|
+
## @param sort_by_name (Boolean) Sort by name if true, otherwise by time
|
2185
|
+
## @param sort_order (String) The sort order (asc or desc)
|
2179
2186
|
##
|
2180
|
-
def tag_times(format
|
2187
|
+
def tag_times(format: 'text', sort_by_name: false, sort_order: 'asc')
|
2181
2188
|
return '' if @timers.empty?
|
2182
2189
|
|
2183
2190
|
max = @timers.keys.sort_by { |k| k.length }.reverse[0].length + 1
|
@@ -2186,11 +2193,13 @@ class WWID
|
|
2186
2193
|
|
2187
2194
|
tags_data = @timers.delete_if { |_k, v| v == 0 }
|
2188
2195
|
sorted_tags_data = if sort_by_name
|
2189
|
-
tags_data.sort_by { |k, _v| k }
|
2196
|
+
tags_data.sort_by { |k, _v| k }
|
2190
2197
|
else
|
2191
2198
|
tags_data.sort_by { |_k, v| v }
|
2192
2199
|
end
|
2193
2200
|
|
2201
|
+
sorted_tags_data.reverse! if sort_order =~ /^asc/i
|
2202
|
+
|
2194
2203
|
if format == 'html'
|
2195
2204
|
output = <<EOS
|
2196
2205
|
<table>
|
@@ -2324,19 +2333,20 @@ EOS
|
|
2324
2333
|
## @param item (Hash) The entry
|
2325
2334
|
## @param formatted (Bool) Return human readable time (default seconds)
|
2326
2335
|
##
|
2327
|
-
def get_interval(item, formatted
|
2336
|
+
def get_interval(item, formatted: true, record: true)
|
2328
2337
|
done = nil
|
2329
2338
|
start = nil
|
2330
2339
|
|
2331
2340
|
if @interval_cache.keys.include? item['title']
|
2332
2341
|
seconds = @interval_cache[item['title']]
|
2342
|
+
record_tag_times(item, seconds) if record
|
2333
2343
|
return seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
|
2334
2344
|
end
|
2335
2345
|
|
2336
2346
|
if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
|
2337
2347
|
done = Time.parse(Regexp.last_match(1))
|
2338
2348
|
else
|
2339
|
-
return
|
2349
|
+
return false
|
2340
2350
|
end
|
2341
2351
|
|
2342
2352
|
start = if item['title'] =~ /@start\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
|
@@ -2347,20 +2357,34 @@ EOS
|
|
2347
2357
|
|
2348
2358
|
seconds = (done - start).to_i
|
2349
2359
|
|
2360
|
+
if record
|
2361
|
+
record_tag_times(item, seconds)
|
2362
|
+
end
|
2363
|
+
|
2364
|
+
@interval_cache[item['title']] = seconds
|
2365
|
+
|
2366
|
+
return seconds > 0 ? seconds : false unless formatted
|
2367
|
+
|
2368
|
+
seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
|
2369
|
+
end
|
2370
|
+
|
2371
|
+
##
|
2372
|
+
## @brief Record times for item tags
|
2373
|
+
##
|
2374
|
+
## @param item The item
|
2375
|
+
##
|
2376
|
+
def record_tag_times(item, seconds)
|
2377
|
+
return if @recorded_items.include?(item)
|
2378
|
+
|
2350
2379
|
item['title'].scan(/(?mi)@(\S+?)(\(.*\))?(?=\s|$)/).each do |m|
|
2351
2380
|
k = m[0] == 'done' ? 'All' : m[0].downcase
|
2352
|
-
if @timers.
|
2381
|
+
if @timers.key?(k)
|
2353
2382
|
@timers[k] += seconds
|
2354
2383
|
else
|
2355
2384
|
@timers[k] = seconds
|
2356
2385
|
end
|
2386
|
+
@recorded_items.push(item)
|
2357
2387
|
end
|
2358
|
-
|
2359
|
-
@interval_cache[item['title']] = seconds
|
2360
|
-
|
2361
|
-
return seconds unless formatted
|
2362
|
-
|
2363
|
-
seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
|
2364
2388
|
end
|
2365
2389
|
|
2366
2390
|
##
|
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.83
|
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-
|
11
|
+
date: 2021-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|