doing 1.0.60 → 1.0.64

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd894959b5ebbff0cd1f08537ec0b754f5a1cc85bce8dbda3f59788ac4f0c230
4
- data.tar.gz: eb490a0bdaf48e7197dd1f2257d13142b6e2ec7629bf923aeb87a42c57dc0ec0
3
+ metadata.gz: 6e6ebff7b78368227b7642297b5b88c8f018f0a9049f42478fc070f545421b1c
4
+ data.tar.gz: bff5c3852e60db87cacaba489f30fcf93fbdb01a8b7e4cba5fd06b6fc23db936
5
5
  SHA512:
6
- metadata.gz: 762db76fac95e65bf0d684ac0f88d7ce7e0af7b22fd77792424d73f237d0501e111f4b2d892f74a6f7ca0564470f1a823c4f6843b1def0496502bf3f7f5d2ac0
7
- data.tar.gz: 9df0af7494c8a550119249dc6f30d5d6208e6adcea50dc1cd41b12749447eb042450eb29a144ef82a0235db99b71d4b5e0dc9aa23f331932be88cf157bb817b3
6
+ metadata.gz: 3c987d7c4a54bb331a3d9db464c5e35b86b1bcc777418547067b8f3bf609756663990c42b53b12d0f36a536f86b3041943eacd539d4d0cf8d1610ff7f3333801
7
+ data.tar.gz: 514fa3c1e8acefc9ebfde3e71e517918648b57c6b52c6d2c86bc9fe79d555d158edae4a9a2dc54c91bbfc32962280e328d97e26875114d4e1b0c98f693923b04
data/README.md CHANGED
@@ -29,7 +29,7 @@ _Side note:_ I actually use the library behind this utility as part of another s
29
29
 
30
30
  ## Installation
31
31
 
32
- The current version of `doing` is <!--VER-->1.0.59<!--END VER-->.
32
+ The current version of `doing` is <!--VER-->1.0.63<!--END VER-->.
33
33
 
34
34
  $ [sudo] gem install doing
35
35
 
@@ -167,7 +167,7 @@ The config also contains templates for various command outputs. Include placehol
167
167
  - there are some random special combo colors. Use `doing colors` to see the list
168
168
  - `%interval`: when used with the `-t` switch on the `show` command, it will display the time between a timestamp or _@start(date)_ tag and the _@done(date)_ tag, if it exists. Otherwise, it will remain empty.
169
169
 
170
- Date formats are based on Ruby [`strftime`](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-strftime) formatting.
170
+ Date formats are based on Ruby [`strftime`](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-strftime) formatting. You can try it out [here](http://strftime.net).
171
171
 
172
172
  My normal template for the `recent` command looks like this:
173
173
 
@@ -394,24 +394,41 @@ Note that you can include a tag with synonyms in the whitelist as well to tag it
394
394
 
395
395
  #### Adding entries:
396
396
 
397
- now, did - Add an entry
397
+ now, next - Add an entry
398
398
  later - Add an item to the Later section
399
- done - Add a completed item with @done(date). No argument finishes last entry.
399
+ done, did - Add a completed item with @done(date). No argument finishes last entry.
400
400
  meanwhile - Finish any @meanwhile tasks and optionally create a new one
401
401
  again, resume - Duplicate the last entry as new entry (without @done tag)
402
402
 
403
- The `doing now` command can accept `-s section_name` to send the new entry straight to a non-default section. It also accepts `--back=AMOUNT` to let you specify a start date in the past using "natural language." For example, `doing now --back=25m ENTRY` or `doing now --back="yesterday 3:30pm" ENTRY`.
403
+ ##### now
404
404
 
405
- If you want to use `--back` with `doing done` but want the end time to be different than the start time, you can either use `--took` in addition, or just use `--took` on its own as it will backdate the start time such that the end time is now and the duration is equal to the value of the `--took` argument.
405
+ The `doing now` command adds an entry to the "Currently" section by default. It accepts `-s section_name` to send the new entry straight to a non-default section. It also accepts `--back=AMOUNT` to let you specify a start date in the past using "natural language." For example, `doing now --back=25m ENTRY` or `doing now --back="yesterday 3:30pm" ENTRY`.
406
406
 
407
407
  You can finish the last unfinished task when starting a new one using `doing now` with the `-f` switch. It will look for the last task not marked _@done_ and add the _@done_ tag with the start time of the new task (either the current time or what you specified with `--back`).
408
408
 
409
- `doing done` is used to add an entry that you've already completed. Like `now`, you can specify a section with `-s section_name`. You can also skip straight to Archive with `-a`.
409
+ > __Examples:__
410
+ >
411
+ > - `doing now Working on project X` --- Add a new entry at the current time
412
+ > - `doing now --section=Projects Working on @projectX` --- Add a new entry to a section titled "Projects"
413
+ > - `doing now --back 30m` --- Add a new entry with a backdated start time, indicating you've been working on it for 30 minutes already
414
+ > - `doing now --back 8am` --- Backdate a new entry to a specific time
415
+ > - `doing now -f Starting the next thing` --- Add a new entry at the current time, and add a @done tag to the previous item with the current time as its completion date
416
+ > - `doing now -f --back 30m Working on something new` --- Add a new entry and complete the last entry, but use a timestamp from 30 minutes ago for both.
410
417
 
411
- `doing done` can also backdate entries using natural language with `--back 15m` or `--back "3/15 3pm"`. That will modify the starting timestamp of the entry. You can also use `--took 1h20m` or `--took 1:20` to set the finish date based on a "natural language" time interval. If `--took` is used without `--back`, then the start date is adjusted (`--took` interval is subtracted) so that the completion date is the current time.
418
+ ##### done/finish
419
+
420
+ `doing done` is used to add an entry that you've already completed. Like `now`, you can specify a section with `-s section_name`. You can also skip straight to the Archive with `-a`.
421
+
422
+ `doing done` can also backdate entries using natural language with `--back 15m` or `--back "3/15 3pm"`. That will modify the starting timestamp of the entry. Used on its own, it will set the start date, and the finish date will be the current time. You can also use `--took 1h20m` or `--took 1:20` to set the finish date based on a "natural language" time interval. If `--took` is used without `--back`, then the start date is adjusted (`--took` interval is subtracted) so that the completion date is the current time.
412
423
 
413
424
  When used with `doing done`, `--back` and `--took` allow time intervals to be accurately counted when entering items after the fact. `--took` is also available for the `doing finish` command, but cannot be used in conjunction with `--back`. (In `finish` they both set the end date, and neither has priority. `--back` allows specific days/times, `--took` uses time intervals.)
414
425
 
426
+ > __Examples:__
427
+ >
428
+ > - `doing done --back 1h The thing I just did` --- Add an entry for a completed task that you started an hour ago and just finished
429
+ > - `doing done --back 1h --took 20m The thing I just finished` --- Record an entry you started an hour ago and finished 20 minutes later
430
+ > - `doing done --took 20m` --- Finish the last task but change the finish date so that the total elapsed time is only 20 minutes (if the finish date would be in the future, start date will be adjusted accordingly)
431
+
415
432
  All of these commands accept a `-e` argument. This opens your command line editor (as defined in the environment variable `$EDITOR`). Add your entry, save the temp file, and close it. The new entry is added. Anything after the first line is included as a note on the entry.
416
433
 
417
434
  `doing again` (or `doing resume`) will duplicate the last @done entry (most recently completed) with a new start date (and without the @done tag). To resume the last entry matching specific tags, use `--tag=TAG`. You can specify multiple tags by separating with a comma. Multiple tags are combined with 'AND' by default (all tags must exist on the entry to match), but you can use `--bool=` to set it to 'OR' or 'NOT'. By default the new entry will be added to the same section as the matching entry, but you can specify a section with `--in=SECTION`.
@@ -429,7 +446,7 @@ See `doing help meanwhile` for more options.
429
446
 
430
447
  ##### Finishing
431
448
 
432
- `doing finish` by itself is the same as `doing done` by itself. It adds _@done(timestamp)_ to the last entry. It also accepts a numeric argument to complete X number of tasks back in history. Add `-a` to also archive the affected entries.
449
+ `doing finish` by itself is the same as `doing done` by itself. It adds _@done(timestamp)_ to the last entry. It also accepts a numeric argument to complete X number of tasks back in history (0 affects all entries). Add `-a` to also archive the affected entries.
433
450
 
434
451
  `doing finish` also provides an `--auto` flag, which you can use to set the end time of any entry to 1 minute before the start time of the next. Running a command such as `doing finish --auto 10` will go through the last 10 entries and sequentially update any without a _@done_ tag with one set to the time just before the next entry in the list.
435
452
 
@@ -445,6 +462,8 @@ You can change the boolean using `--bool=OR` (last entry containing any of the s
445
462
 
446
463
  You can also include a `--no-date` switch to add `@done` without a finish date, meaning no time is tracked for the task. `doing cancel` is an alias for this. Like `finish`, `cancel` accepts a count to act on the last X entries, as well as `--archive` and `--section` options. `cancel` also accepts the `--tag` and `--bool` flags for tag filtering.
447
464
 
465
+ By default `doing finish` works on a single entry, the last entry or the most recent entry matching a `--tag` or `--search` query. Specifying `doing finish 10` would finish any unfinished entries within the last 10 entries. In the case of `--tag` or `--search` queries, the count serves as the maximum number of matches doing will act on, sorted in reverse date order (most recent first). A count of 0 will disable the limit entirely, acting on all matching entries.
466
+
448
467
 
449
468
  ##### Tagging and Autotagging
450
469
 
data/bin/doing CHANGED
@@ -310,7 +310,7 @@ end
310
310
 
311
311
  desc 'Add a completed item with @done(date). No argument finishes last entry.'
312
312
  arg_name 'ENTRY'
313
- command [:done, :did] do |c|
313
+ command %i[done did] do |c|
314
314
  c.desc 'Remove @done tag'
315
315
  c.switch %i[r remove], negatable: false, default_value: false
316
316
 
@@ -367,15 +367,18 @@ command [:done, :did] do |c|
367
367
 
368
368
  date = options[:took] ? finish_date - took : finish_date
369
369
  elsif options[:took]
370
- finish_date = date + took
370
+ finish_date = options[:back] ? date + took : nil
371
371
  elsif options[:back]
372
372
  finish_date = date
373
373
  else
374
374
  finish_date = Time.now
375
375
  end
376
376
 
377
+ if finish_date
378
+ donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ''
379
+ end
380
+
377
381
  section = wwid.guess_section(options[:s]) || options[:s].cap_first
378
- donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ''
379
382
 
380
383
  if options[:e]
381
384
  raise 'No EDITOR variable defined in environment' if ENV['EDITOR'].nil?
@@ -394,8 +397,15 @@ command [:done, :did] do |c|
394
397
  if options[:r]
395
398
  wwid.tag_last({ tags: ['done'], count: 1, section: section, remove: true })
396
399
  else
397
- wwid.tag_last({ tags: ['done'], count: 1, section: section, archive: options[:a], back: finish_date,
398
- date: options[:date] })
400
+ options = { tags: ['done'],
401
+ archive: options[:a],
402
+ back: finish_date,
403
+ count: 1,
404
+ date: options[:date],
405
+ section: section,
406
+ took: took == 0 ? nil : took
407
+ }
408
+ wwid.tag_last(options)
399
409
  end
400
410
  elsif !args.empty?
401
411
  title, note = wwid.format_input(args.join(' '))
@@ -1230,14 +1240,17 @@ desc 'Move entries between sections'
1230
1240
  arg_name 'SECTION_NAME'
1231
1241
  default_value wwid.current_section
1232
1242
  command :archive do |c|
1233
- c.desc 'Count to keep (ignored if archiving by tag)'
1234
- c.arg_name 'COUNT'
1235
- c.flag %i[k keep], default_value: 5, must_match: /^\d+$/, type: Integer
1243
+ c.desc 'How many items to keep (ignored if archiving by tag or search)'
1244
+ c.arg_name 'X'
1245
+ c.flag %i[k keep], must_match: /^\d+$/, type: Integer
1236
1246
 
1237
1247
  c.desc 'Move entries to'
1238
1248
  c.arg_name 'SECTION_NAME'
1239
1249
  c.flag %i[t to], default_value: 'Archive'
1240
1250
 
1251
+ c.desc 'Label moved items with @from(SECTION_NAME)'
1252
+ c.switch [:label], default_value: true, negatable: true
1253
+
1241
1254
  c.desc 'Tag filter, combine multiple tags with a comma. Added for compatibility with other commands.'
1242
1255
  c.arg_name 'TAG'
1243
1256
  c.flag [:tag]
@@ -1246,21 +1259,36 @@ command :archive do |c|
1246
1259
  c.arg_name 'BOOLEAN'
1247
1260
  c.flag [:bool], must_match: /(and|or|not)/i, default_value: 'AND'
1248
1261
 
1262
+ c.desc 'Search filter'
1263
+ c.arg_name 'QUERY'
1264
+ c.flag [:search]
1265
+
1249
1266
  c.action do |_global_options, options, args|
1250
1267
  if args.empty?
1251
1268
  section = wwid.current_section
1252
1269
  tags = []
1270
+ elsif args[0] =~ /^all/i
1271
+ section = 'all'
1253
1272
  elsif args[0] =~ /^@\S+/
1254
1273
  section = 'all'
1255
1274
  tags = args.map { |t| t.sub(/^@/, '').strip }
1256
1275
  else
1257
1276
  section = args[0].cap_first
1258
- tags = args.length > 1 ? args[1..].map { |t| t.sub(/^@/, '').strip } : nil
1277
+ tags = args.length > 1 ? args[1..].map { |t| t.sub(/^@/, '').strip } : []
1259
1278
  end
1260
1279
 
1280
+ raise '--keep and --count can\'t be used together' if options[:keep] && options[:count]
1281
+
1261
1282
  tags.concat(options[:tag].split(/ *, */).map { |t| t.sub(/^@/, '').strip }) if options[:tag]
1262
1283
 
1263
- wwid.archive(section, options[:keep], options[:to], tags, options[:bool])
1284
+ opts = {
1285
+ bool: options[:bool],
1286
+ destination: options[:to],
1287
+ keep: options[:keep],
1288
+ search: options[:search],
1289
+ tags: tags
1290
+ }
1291
+ wwid.archive(section, opts)
1264
1292
  end
1265
1293
  end
1266
1294
 
@@ -1363,6 +1391,41 @@ command :undo do |c|
1363
1391
  end
1364
1392
  end
1365
1393
 
1394
+ desc 'Import entries from an external source'
1395
+ long_desc 'Imports entries from other sources. Currently only handles JSON reports exported from Timing.app.'
1396
+ arg_name 'PATH'
1397
+ command [:import] do |c|
1398
+ c.desc 'Import type'
1399
+ c.arg_name 'TYPE'
1400
+ c.flag [:type], default_value: 'timing'
1401
+
1402
+ c.desc 'Target section'
1403
+ c.arg_name 'NAME'
1404
+ c.flag %i[s section], default_value: wwid.current_section
1405
+
1406
+ c.desc 'Tag all imported entries'
1407
+ c.arg_name 'TAGS'
1408
+ c.flag [:tag]
1409
+
1410
+ c.desc 'Prefix entries with'
1411
+ c.arg_name 'PREFIX'
1412
+ c.flag [:prefix]
1413
+
1414
+ c.action do |_global_options, options, args|
1415
+
1416
+ section = wwid.guess_section(options[:s]) || options[:s].cap_first
1417
+
1418
+ if options[:type] =~ /^tim/i
1419
+ args.each do |path|
1420
+ wwid.import_timing(path, { section: section, tag: options[:tag], prefix: options[:prefix] })
1421
+ wwid.write(wwid.doing_file)
1422
+ end
1423
+ else
1424
+ raise 'Invalid import type'
1425
+ end
1426
+ end
1427
+ end
1428
+
1366
1429
  pre do |global, _command, _options, _args|
1367
1430
  if global[:config_file] && global[:config_file] != wwid.config_file
1368
1431
  wwid.config_file = global[:config_file]
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '1.0.60'
2
+ VERSION = '1.0.64'
3
3
  end
data/lib/doing/wwid.rb CHANGED
@@ -310,7 +310,7 @@ class WWID
310
310
  else
311
311
  @content[section]['items'][current - 1]['note'] = [] unless @content[section]['items'][current - 1].key? 'note'
312
312
 
313
- @content[section]['items'][current - 1]['note'].push(line.gsub(/ *$/, ''))
313
+ @content[section]['items'][current - 1]['note'].push(line.chomp)
314
314
  # end
315
315
  end
316
316
  end
@@ -667,6 +667,55 @@ class WWID
667
667
  @results.push(%(Added "#{entry['title']}" to #{section}))
668
668
  end
669
669
 
670
+ ##
671
+ ## @brief Imports a Timing report
672
+ ##
673
+ ## @param path (String) Path to JSON report file
674
+ ## @param section (String) The section to add to
675
+ ## @param opt (Hash) Additional Options
676
+ ##
677
+ def import_timing(path, opt = {})
678
+ section = opt[:section] || @current_section
679
+ add_section(section) unless @content.has_key?(section)
680
+
681
+ add_tags = opt[:tag] ? opt[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '@') }.join(' ') : ''
682
+ prefix = opt[:prefix] ? opt[:prefix] : '[Timing.app]'
683
+ raise "File not found" unless File.exist?(File.expand_path(path))
684
+
685
+ data = JSON.parse(IO.read(File.expand_path(path)))
686
+ new_items = []
687
+ data.each do |entry|
688
+ # Only process task entries
689
+ next if entry.key?('activityType') && entry['activityType'] != 'Task'
690
+ # Only process entries with a start and end date
691
+ next unless entry.key?('startDate') && entry.key?('endDate')
692
+
693
+ start_time = Time.parse(entry['startDate'])
694
+ end_time = Time.parse(entry['endDate'])
695
+ next unless start_time && end_time
696
+ tags = entry['project'].split(/ ▸ /).map {|proj| proj.gsub(/ +/, '').downcase }
697
+ title = "#{prefix} "
698
+ title += entry.key?('activityTitle') && entry['activityTitle'] != '(Untitled Task)' ? entry['activityTitle'] : 'Working on'
699
+ tags.each do |tag|
700
+ if title =~ /\b#{tag}\b/i
701
+ title.sub!(/\b#{tag}\b/i, "@#{tag}")
702
+ else
703
+ title += " @#{tag}"
704
+ end
705
+ end
706
+ title = autotag(title) if @auto_tag
707
+ title += " @done(#{end_time.strftime('%Y-%m-%d %H:%M')})"
708
+ title.gsub!(/ +/, ' ')
709
+ title.strip!
710
+ new_entry = { 'title' => title, 'date' => start_time, 'section' => section }
711
+ new_entry['note'] = entry['notes'].split(/\n/).map(&:chomp) if entry.key?('notes')
712
+ new_items.push(new_entry)
713
+ end
714
+
715
+ @content[section]['items'].concat(new_items)
716
+ @results.push(%(Imported #{new_items.count} items to #{section}))
717
+ end
718
+
670
719
  ##
671
720
  ## @brief Return the content of the last note for a given section
672
721
  ##
@@ -776,6 +825,7 @@ class WWID
776
825
  opt[:remove] ||= false
777
826
  opt[:autotag] ||= false
778
827
  opt[:back] ||= false
828
+ opt[:took] ||= nil
779
829
 
780
830
  sec_arr = []
781
831
 
@@ -833,6 +883,13 @@ class WWID
833
883
  else
834
884
  done_date = item['date'] + (opt[:back] - item['date'])
835
885
  end
886
+ elsif opt[:took]
887
+ if item['date'] + opt[:took] > Time.now
888
+ item['date'] = Time.now - opt[:took]
889
+ done_date = Time.now
890
+ else
891
+ done_date = item['date'] + opt[:took]
892
+ end
836
893
  else
837
894
  done_date = Time.now
838
895
  end
@@ -1551,31 +1608,24 @@ class WWID
1551
1608
  ## section
1552
1609
  ##
1553
1610
  ## @param section (String) The source section
1554
- ## @param count (Integer) The count
1555
- ## @param destination (String) The destination section
1556
- ## @param tags (Array) Tags to archive
1557
- ## @param bool (String) Tag boolean combinator
1611
+ ## @param options (Hash) Options
1558
1612
  ##
1559
- def archive(section = 'Currently', count = 5, destination = nil, tags = nil, bool = nil, _export = nil)
1613
+ def archive(section = 'Currently', options = {})
1614
+ count = options[:keep] || 0
1615
+ destination = options[:destination] || 'Archive'
1616
+ tags = options[:tags] || []
1617
+ bool = options[:bool] || 'AND'
1618
+
1560
1619
  section = choose_section if section.nil? || section =~ /choose/i
1561
- archive_all = section =~ /all/i # && !(tags.nil? || tags.empty?)
1620
+ archive_all = section =~ /^all$/i # && !(tags.nil? || tags.empty?)
1562
1621
  section = guess_section(section) unless archive_all
1563
1622
 
1564
- add_section('Archive') if destination =~ /archive/i && !sections.include?('Archive')
1623
+ add_section('Archive') if destination =~ /^archive$/i && !sections.include?('Archive')
1565
1624
 
1566
1625
  destination = guess_section(destination)
1567
1626
 
1568
1627
  if sections.include?(destination) && (sections.include?(section) || archive_all)
1569
- if archive_all
1570
- to_archive = sections.dup
1571
- to_archive.delete(destination)
1572
- to_archive.each do |source, _v|
1573
- do_archive(source, destination, { count: count, tags: tags, bool: bool, label: true })
1574
- end
1575
- else
1576
- do_archive(section, destination, { count: count, tags: tags, bool: bool, label: true })
1577
- end
1578
-
1628
+ do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label] })
1579
1629
  write(doing_file)
1580
1630
  else
1581
1631
  raise 'Either source or destination does not exist'
@@ -1589,74 +1639,69 @@ class WWID
1589
1639
  ## @param destination (String) The destination section
1590
1640
  ## @param opt (Hash) Additional Options
1591
1641
  ##
1592
- def do_archive(section, destination, opt = {})
1593
- count = opt[:count] || 5
1594
- tags = opt[:tags] || []
1595
- bool = opt[:bool] || 'AND'
1596
- label = opt[:label] || false
1642
+ def do_archive(sect, destination, opt = {})
1643
+ count = opt[:count] || 0
1644
+ tags = opt[:tags] || []
1645
+ bool = opt[:bool] || 'AND'
1646
+ label = opt[:label] || true
1597
1647
 
1598
- items = @content[section]['items']
1599
- moved_items = []
1648
+ if sect =~ /^all$/i
1649
+ all_sections = sections.dup
1650
+ all_sections.delete(destination)
1651
+ else
1652
+ all_sections = [sect]
1653
+ end
1600
1654
 
1601
- if tags && !tags.empty?
1602
- items.delete_if do |item|
1603
- case bool
1604
- when /(AND|ALL)/i
1605
- score = 0
1606
- tags.each do |tag|
1607
- score += 1 if item['title'] =~ /@#{tag}/i
1608
- end
1609
- res = score < tags.length
1610
- moved_items.push(item) if res
1611
- res
1612
- when /NONE/i
1613
- del = false
1614
- tags.each do |tag|
1615
- del = true if item['title'] =~ /@#{tag}/i
1655
+ counter = 0
1656
+
1657
+ all_sections.each do |section|
1658
+ items = @content[section]['items']
1659
+
1660
+ moved_items = []
1661
+ if !tags.empty? || opt[:search]
1662
+ items.delete_if do |item|
1663
+ if (!tags.empty? && item.has_tags?(tags, bool) || (opt[:search] && item.matches_search?(opt[:search].to_s)))
1664
+ moved_items.push(item)
1665
+ counter += 1
1666
+ true
1667
+ else
1668
+ false
1616
1669
  end
1617
- moved_items.push(item) if del
1618
- del
1619
- when /(OR|ANY)/i
1620
- del = true
1621
- tags.each do |tag|
1622
- del = false if item['title'] =~ /@#{tag}/i
1670
+ end
1671
+ moved_items.each do |item|
1672
+ if label && section != 'Currently'
1673
+ item['title'] =
1674
+ item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
1623
1675
  end
1624
- moved_items.push(item) if del
1625
- del
1626
1676
  end
1627
- end
1628
- moved_items.each do |item|
1629
- if label && section != 'Currently'
1630
- item['title'] =
1631
- item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
1677
+
1678
+ @content[section]['items'] = items
1679
+ @content[destination]['items'].concat(moved_items)
1680
+ @results.push("Archived #{moved_items.length} items from #{section} to #{destination}")
1681
+ else
1682
+ count = items.length if count == 0 || items.length < count
1683
+
1684
+ @content[section]['items'] = if count.zero?
1685
+ []
1686
+ else
1687
+ items[0..count - 1]
1688
+ end
1689
+
1690
+ items.map! do |item|
1691
+ if label && section != 'Currently'
1692
+ item['title'] =
1693
+ item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
1694
+ end
1695
+ item
1632
1696
  end
1633
- end
1634
- @content[section]['items'] = moved_items
1635
- @content[destination]['items'] += items
1636
- @results.push("Archived #{items.length} items from #{section} to #{destination}")
1637
- else
1638
- count = items.length if items.length < count
1639
-
1640
- @content[section]['items'] = if count.zero?
1641
- []
1642
- else
1643
- items[0..count - 1]
1644
- end
1645
-
1646
- items.map! do |item|
1647
- if label && section != 'Currently'
1648
- item['title'] =
1649
- item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
1697
+ if items.count > count
1698
+ @content[destination]['items'].concat(items[count..-1])
1699
+ else
1700
+ @content[destination]['items'].concat(items)
1650
1701
  end
1651
- item
1652
- end
1653
- if items.count > count
1654
- @content[destination]['items'].concat(items[count..-1])
1655
- else
1656
- @content[destination]['items'].concat(items)
1657
- end
1658
1702
 
1659
- @results.push("Archived #{items.length - count} items from #{section} to #{destination}")
1703
+ @results.push("Archived #{items.length - count} items from #{section} to #{destination}")
1704
+ end
1660
1705
  end
1661
1706
  end
1662
1707
 
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.60
4
+ version: 1.0.64
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-07-07 00:00:00.000000000 Z
11
+ date: 2021-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake