doing 1.0.80 → 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 +4 -4
 - data/README.md +10 -4
 - data/bin/doing +154 -29
 - data/lib/doing/version.rb +1 -1
 - data/lib/doing/wwid.rb +222 -101
 - data/lib/doing.rb +3 -2
 - 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 
     | 
    
         | 
| 
         @@ -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
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #!/usr/bin/env ruby
         
     | 
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby -W1
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            $LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
         
     | 
| 
         @@ -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]
         
     | 
| 
         @@ -301,11 +311,14 @@ command :select do |c| 
     | 
|
| 
       301 
311 
     | 
    
         
             
              c.desc 'Add flag to selected item(s)'
         
     | 
| 
       302 
312 
     | 
    
         
             
              c.switch %i[flag], negatable: false, default_value: false
         
     | 
| 
       303 
313 
     | 
    
         | 
| 
      
 314 
     | 
    
         
            +
              c.desc 'Perform action without confirmation'
         
     | 
| 
      
 315 
     | 
    
         
            +
              c.switch %i[force], negatable: false, default_value: false
         
     | 
| 
      
 316 
     | 
    
         
            +
             
     | 
| 
       304 
317 
     | 
    
         
             
              c.desc 'Save selected entries to file using --output format'
         
     | 
| 
       305 
318 
     | 
    
         
             
              c.arg_name 'FILE'
         
     | 
| 
       306 
319 
     | 
    
         
             
              c.flag %i[save_to]
         
     | 
| 
       307 
320 
     | 
    
         | 
| 
       308 
     | 
    
         
            -
              c.desc 'Output  
     | 
| 
      
 321 
     | 
    
         
            +
              c.desc 'Output entries to format (doing|taskpaper|csv|html|json|template|timeline)'
         
     | 
| 
       309 
322 
     | 
    
         
             
              c.arg_name 'FORMAT'
         
     | 
| 
       310 
323 
     | 
    
         
             
              c.flag %i[o output], must_match: /^(?:doing|taskpaper|html|csv|json|template|timeline)$/i
         
     | 
| 
       311 
324 
     | 
    
         | 
| 
         @@ -396,7 +409,7 @@ command %i[done did] do |c| 
     | 
|
| 
       396 
409 
     | 
    
         | 
| 
       397 
410 
     | 
    
         
             
              c.desc 'Section'
         
     | 
| 
       398 
411 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       399 
     | 
    
         
            -
              c.flag %i[s section] 
     | 
| 
      
 412 
     | 
    
         
            +
              c.flag %i[s section]
         
     | 
| 
       400 
413 
     | 
    
         | 
| 
       401 
414 
     | 
    
         
             
              c.desc "Edit entry with #{ENV['EDITOR']}"
         
     | 
| 
       402 
415 
     | 
    
         
             
              c.switch %i[e editor], negatable: false, default_value: false
         
     | 
| 
         @@ -437,7 +450,11 @@ command %i[done did] do |c| 
     | 
|
| 
       437 
450 
     | 
    
         
             
                  donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ''
         
     | 
| 
       438 
451 
     | 
    
         
             
                end
         
     | 
| 
       439 
452 
     | 
    
         | 
| 
       440 
     | 
    
         
            -
                 
     | 
| 
      
 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
         
     | 
| 
       441 
458 
     | 
    
         | 
| 
       442 
459 
     | 
    
         
             
                if options[:e]
         
     | 
| 
       443 
460 
     | 
    
         
             
                  exit_now! 'No EDITOR variable defined in environment' if ENV['EDITOR'].nil?
         
     | 
| 
         @@ -494,7 +511,7 @@ command :cancel do |c| 
     | 
|
| 
       494 
511 
     | 
    
         | 
| 
       495 
512 
     | 
    
         
             
              c.desc 'Section'
         
     | 
| 
       496 
513 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       497 
     | 
    
         
            -
              c.flag %i[s section] 
     | 
| 
      
 514 
     | 
    
         
            +
              c.flag %i[s section]
         
     | 
| 
       498 
515 
     | 
    
         | 
| 
       499 
516 
     | 
    
         
             
              c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag1,tag2)'
         
     | 
| 
       500 
517 
     | 
    
         
             
              c.arg_name 'TAG'
         
     | 
| 
         @@ -508,7 +525,11 @@ command :cancel do |c| 
     | 
|
| 
       508 
525 
     | 
    
         
             
              c.switch %i[u unfinished], negatable: false, default_value: false
         
     | 
| 
       509 
526 
     | 
    
         | 
| 
       510 
527 
     | 
    
         
             
              c.action do |_global_options, options, args|
         
     | 
| 
       511 
     | 
    
         
            -
                 
     | 
| 
      
 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
         
     | 
| 
       512 
533 
     | 
    
         | 
| 
       513 
534 
     | 
    
         
             
                if options[:tag].nil?
         
     | 
| 
       514 
535 
     | 
    
         
             
                  tags = []
         
     | 
| 
         @@ -561,6 +582,10 @@ command :finish do |c| 
     | 
|
| 
       561 
582 
     | 
    
         
             
              c.arg_name 'INTERVAL'
         
     | 
| 
       562 
583 
     | 
    
         
             
              c.flag %i[t took]
         
     | 
| 
       563 
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 
     | 
    
         
            +
             
     | 
| 
       564 
589 
     | 
    
         
             
              c.desc 'Finish the last X entries containing TAG.
         
     | 
| 
       565 
590 
     | 
    
         
             
              Separate multiple tags with comma (--tag=tag1,tag2), combine with --bool'
         
     | 
| 
       566 
591 
     | 
    
         
             
              c.arg_name 'TAG'
         
     | 
| 
         @@ -587,17 +612,31 @@ command :finish do |c| 
     | 
|
| 
       587 
612 
     | 
    
         | 
| 
       588 
613 
     | 
    
         
             
              c.desc 'Section'
         
     | 
| 
       589 
614 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       590 
     | 
    
         
            -
              c.flag %i[s section] 
     | 
| 
      
 615 
     | 
    
         
            +
              c.flag %i[s section]
         
     | 
| 
       591 
616 
     | 
    
         | 
| 
       592 
617 
     | 
    
         
             
              c.action do |_global_options, options, args|
         
     | 
| 
       593 
     | 
    
         
            -
                 
     | 
| 
      
 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
         
     | 
| 
       594 
623 
     | 
    
         | 
| 
       595 
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 
     | 
    
         
            +
             
     | 
| 
       596 
630 
     | 
    
         
             
                  exit_now! '--back and --took cannot be used together' if options[:back] && options[:took]
         
     | 
| 
       597 
631 
     | 
    
         | 
| 
       598 
632 
     | 
    
         
             
                  exit_now! '--search and --tag cannot be used together' if options[:search] && options[:tag]
         
     | 
| 
       599 
633 
     | 
    
         | 
| 
       600 
     | 
    
         
            -
                  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]
         
     | 
| 
       601 
640 
     | 
    
         
             
                    date = wwid.chronify(options[:back])
         
     | 
| 
       602 
641 
     | 
    
         | 
| 
       603 
642 
     | 
    
         
             
                    exit_now! 'Unable to parse date string' if date.nil?
         
     | 
| 
         @@ -823,7 +862,7 @@ desc 'Mark last entry as highlighted' 
     | 
|
| 
       823 
862 
     | 
    
         
             
            command [:mark, :flag] do |c|
         
     | 
| 
       824 
863 
     | 
    
         
             
              c.desc 'Section'
         
     | 
| 
       825 
864 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       826 
     | 
    
         
            -
              c.flag %i[s section] 
     | 
| 
      
 865 
     | 
    
         
            +
              c.flag %i[s section]
         
     | 
| 
       827 
866 
     | 
    
         | 
| 
       828 
867 
     | 
    
         
             
              c.desc 'Remove mark'
         
     | 
| 
       829 
868 
     | 
    
         
             
              c.switch %i[r remove], negatable: false, default_value: false
         
     | 
| 
         @@ -1306,7 +1345,8 @@ desc 'Select a section to display from a menu' 
     | 
|
| 
       1306 
1345 
     | 
    
         
             
            command :choose do |c|
         
     | 
| 
       1307 
1346 
     | 
    
         
             
              c.action do |_global_options, _options, _args|
         
     | 
| 
       1308 
1347 
     | 
    
         
             
                section = wwid.choose_section
         
     | 
| 
       1309 
     | 
    
         
            -
             
     | 
| 
      
 1348 
     | 
    
         
            +
             
     | 
| 
      
 1349 
     | 
    
         
            +
                puts wwid.list_section({ section: section.cap_first, count: 0 }) if section
         
     | 
| 
       1310 
1350 
     | 
    
         
             
              end
         
     | 
| 
       1311 
1351 
     | 
    
         
             
            end
         
     | 
| 
       1312 
1352 
     | 
    
         | 
| 
         @@ -1340,13 +1380,14 @@ command :colors do |c| 
     | 
|
| 
       1340 
1380 
     | 
    
         
             
            end
         
     | 
| 
       1341 
1381 
     | 
    
         | 
| 
       1342 
1382 
     | 
    
         
             
            desc 'Display a user-created view'
         
     | 
| 
      
 1383 
     | 
    
         
            +
            long_desc 'Command line options override associated view settings'
         
     | 
| 
       1343 
1384 
     | 
    
         
             
            arg_name 'VIEW_NAME'
         
     | 
| 
       1344 
1385 
     | 
    
         
             
            command :view do |c|
         
     | 
| 
       1345 
     | 
    
         
            -
              c.desc 'Section 
     | 
| 
      
 1386 
     | 
    
         
            +
              c.desc 'Section'
         
     | 
| 
       1346 
1387 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       1347 
1388 
     | 
    
         
             
              c.flag %i[s section]
         
     | 
| 
       1348 
1389 
     | 
    
         | 
| 
       1349 
     | 
    
         
            -
              c.desc 'Count to display 
     | 
| 
      
 1390 
     | 
    
         
            +
              c.desc 'Count to display'
         
     | 
| 
       1350 
1391 
     | 
    
         
             
              c.arg_name 'COUNT'
         
     | 
| 
       1351 
1392 
     | 
    
         
             
              c.flag %i[c count], must_match: /^\d+$/, type: Integer
         
     | 
| 
       1352 
1393 
     | 
    
         | 
| 
         @@ -1364,12 +1405,14 @@ command :view do |c| 
     | 
|
| 
       1364 
1405 
     | 
    
         
             
              c.switch [:color], default_value: true, negatable: true
         
     | 
| 
       1365 
1406 
     | 
    
         | 
| 
       1366 
1407 
     | 
    
         
             
              c.desc 'Sort tags by (name|time)'
         
     | 
| 
       1367 
     | 
    
         
            -
              default = 'time'
         
     | 
| 
       1368 
     | 
    
         
            -
              default = wwid.config['tag_sort'] if wwid.config.key?('tag_sort')
         
     | 
| 
       1369 
1408 
     | 
    
         
             
              c.arg_name 'KEY'
         
     | 
| 
       1370 
     | 
    
         
            -
              c.flag [:tag_sort], must_match: /^(?:name|time)$/i 
     | 
| 
      
 1409 
     | 
    
         
            +
              c.flag [:tag_sort], must_match: /^(?:name|time)$/i
         
     | 
| 
       1371 
1410 
     | 
    
         | 
| 
       1372 
     | 
    
         
            -
              c.desc ' 
     | 
| 
      
 1411 
     | 
    
         
            +
              c.desc 'Tag sort direction (asc|desc)'
         
     | 
| 
      
 1412 
     | 
    
         
            +
              c.arg_name 'DIRECTION'
         
     | 
| 
      
 1413 
     | 
    
         
            +
              c.flag [:tag_order], must_match: /^(?:a(?:sc)?|d(?:esc)?)$/i
         
     | 
| 
      
 1414 
     | 
    
         
            +
             
     | 
| 
      
 1415 
     | 
    
         
            +
              c.desc 'Only show items with recorded time intervals (override view settings)'
         
     | 
| 
       1373 
1416 
     | 
    
         
             
              c.switch [:only_timed], default_value: false, negatable: false
         
     | 
| 
       1374 
1417 
     | 
    
         | 
| 
       1375 
1418 
     | 
    
         
             
              c.action do |_global_options, options, args|
         
     | 
| 
         @@ -1379,7 +1422,11 @@ command :view do |c| 
     | 
|
| 
       1379 
1422 
     | 
    
         
             
                          wwid.guess_view(args[0])
         
     | 
| 
       1380 
1423 
     | 
    
         
             
                        end
         
     | 
| 
       1381 
1424 
     | 
    
         | 
| 
       1382 
     | 
    
         
            -
                 
     | 
| 
      
 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
         
     | 
| 
       1383 
1430 
     | 
    
         | 
| 
       1384 
1431 
     | 
    
         
             
                view = wwid.get_view(title)
         
     | 
| 
       1385 
1432 
     | 
    
         
             
                if view
         
     | 
| 
         @@ -1418,10 +1465,31 @@ command :view do |c| 
     | 
|
| 
       1418 
1465 
     | 
    
         
             
                            end
         
     | 
| 
       1419 
1466 
     | 
    
         
             
                  order = view.key?('order') ? view['order'] : 'asc'
         
     | 
| 
       1420 
1467 
     | 
    
         | 
| 
       1421 
     | 
    
         
            -
                   
     | 
| 
      
 1468 
     | 
    
         
            +
                  totals = if options[:totals]
         
     | 
| 
      
 1469 
     | 
    
         
            +
                             true
         
     | 
| 
      
 1470 
     | 
    
         
            +
                           else
         
     | 
| 
      
 1471 
     | 
    
         
            +
                             view.key?('totals') ? view['totals'] : false
         
     | 
| 
      
 1472 
     | 
    
         
            +
                           end
         
     | 
| 
      
 1473 
     | 
    
         
            +
             
     | 
| 
      
 1474 
     | 
    
         
            +
                  options[:t] = true if totals
         
     | 
| 
       1422 
1475 
     | 
    
         
             
                  options[:output]&.downcase!
         
     | 
| 
       1423 
     | 
    
         
            -
                  options[:sort_tags] = options[:tag_sort] =~ /^n/i
         
     | 
| 
       1424 
1476 
     | 
    
         | 
| 
      
 1477 
     | 
    
         
            +
                  options[:sort_tags] = if options[:tag_sort]
         
     | 
| 
      
 1478 
     | 
    
         
            +
                                          options[:tag_sort] =~ /^n/i ? true : false
         
     | 
| 
      
 1479 
     | 
    
         
            +
                                        elsif view.key?('tag_sort')
         
     | 
| 
      
 1480 
     | 
    
         
            +
                                          view['tag_sort'] =~ /^n/i ? true : false
         
     | 
| 
      
 1481 
     | 
    
         
            +
                                        else
         
     | 
| 
      
 1482 
     | 
    
         
            +
                                          false
         
     | 
| 
      
 1483 
     | 
    
         
            +
                                        end
         
     | 
| 
      
 1484 
     | 
    
         
            +
             
     | 
| 
      
 1485 
     | 
    
         
            +
                  tag_order = if options[:tag_order]
         
     | 
| 
      
 1486 
     | 
    
         
            +
                                options[:tag_order] =~ /^d/i ? 'desc' : 'asc'
         
     | 
| 
      
 1487 
     | 
    
         
            +
                              elsif view.key?('tag_order')
         
     | 
| 
      
 1488 
     | 
    
         
            +
                                view['tag_order'] =~ /^d/i ? 'desc' : 'asc'
         
     | 
| 
      
 1489 
     | 
    
         
            +
                              else
         
     | 
| 
      
 1490 
     | 
    
         
            +
                                'asc'
         
     | 
| 
      
 1491 
     | 
    
         
            +
                              end
         
     | 
| 
      
 1492 
     | 
    
         
            +
                  warn "TAG ORDER: #{options[:tag_order]}"
         
     | 
| 
       1425 
1493 
     | 
    
         
             
                  opts = {
         
     | 
| 
       1426 
1494 
     | 
    
         
             
                    count: count,
         
     | 
| 
       1427 
1495 
     | 
    
         
             
                    format: format,
         
     | 
| 
         @@ -1432,10 +1500,11 @@ command :view do |c| 
     | 
|
| 
       1432 
1500 
     | 
    
         
             
                    section: section,
         
     | 
| 
       1433 
1501 
     | 
    
         
             
                    sort_tags: options[:sort_tags],
         
     | 
| 
       1434 
1502 
     | 
    
         
             
                    tag_filter: tag_filter,
         
     | 
| 
      
 1503 
     | 
    
         
            +
                    tag_order: tag_order,
         
     | 
| 
       1435 
1504 
     | 
    
         
             
                    tags_color: tags_color,
         
     | 
| 
       1436 
1505 
     | 
    
         
             
                    template: template,
         
     | 
| 
       1437 
1506 
     | 
    
         
             
                    times: options[:t],
         
     | 
| 
       1438 
     | 
    
         
            -
                    totals:  
     | 
| 
      
 1507 
     | 
    
         
            +
                    totals: totals
         
     | 
| 
       1439 
1508 
     | 
    
         
             
                  }
         
     | 
| 
       1440 
1509 
     | 
    
         | 
| 
       1441 
1510 
     | 
    
         
             
                  puts wwid.list_section(opts)
         
     | 
| 
         @@ -1524,6 +1593,48 @@ command :archive do |c| 
     | 
|
| 
       1524 
1593 
     | 
    
         
             
              end
         
     | 
| 
       1525 
1594 
     | 
    
         
             
            end
         
     | 
| 
       1526 
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 
     | 
    
         
            +
             
     | 
| 
       1527 
1638 
     | 
    
         
             
            desc 'Open the "doing" file in an editor'
         
     | 
| 
       1528 
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'})"
         
     | 
| 
       1529 
1640 
     | 
    
         
             
            command :open do |c|
         
     | 
| 
         @@ -1633,12 +1744,15 @@ command :import do |c| 
     | 
|
| 
       1633 
1744 
     | 
    
         | 
| 
       1634 
1745 
     | 
    
         
             
              c.desc 'Target section'
         
     | 
| 
       1635 
1746 
     | 
    
         
             
              c.arg_name 'NAME'
         
     | 
| 
       1636 
     | 
    
         
            -
              c.flag %i[s section] 
     | 
| 
      
 1747 
     | 
    
         
            +
              c.flag %i[s section]
         
     | 
| 
       1637 
1748 
     | 
    
         | 
| 
       1638 
1749 
     | 
    
         
             
              c.desc 'Tag all imported entries'
         
     | 
| 
       1639 
1750 
     | 
    
         
             
              c.arg_name 'TAGS'
         
     | 
| 
       1640 
1751 
     | 
    
         
             
              c.flag :tag
         
     | 
| 
       1641 
1752 
     | 
    
         | 
| 
      
 1753 
     | 
    
         
            +
              c.desc 'Autotag entries'
         
     | 
| 
      
 1754 
     | 
    
         
            +
              c.switch :autotag, negatable: true, default_value: true
         
     | 
| 
      
 1755 
     | 
    
         
            +
             
     | 
| 
       1642 
1756 
     | 
    
         
             
              c.desc 'Prefix entries with'
         
     | 
| 
       1643 
1757 
     | 
    
         
             
              c.arg_name 'PREFIX'
         
     | 
| 
       1644 
1758 
     | 
    
         
             
              c.flag :prefix
         
     | 
| 
         @@ -1648,11 +1762,22 @@ command :import do |c| 
     | 
|
| 
       1648 
1762 
     | 
    
         | 
| 
       1649 
1763 
     | 
    
         
             
              c.action do |_global_options, options, args|
         
     | 
| 
       1650 
1764 
     | 
    
         | 
| 
       1651 
     | 
    
         
            -
                 
     | 
| 
      
 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
         
     | 
| 
       1652 
1770 
     | 
    
         | 
| 
       1653 
1771 
     | 
    
         
             
                if options[:type] =~ /^tim/i
         
     | 
| 
       1654 
1772 
     | 
    
         
             
                  args.each do |path|
         
     | 
| 
       1655 
     | 
    
         
            -
                     
     | 
| 
      
 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)
         
     | 
| 
       1656 
1781 
     | 
    
         
             
                    wwid.write(wwid.doing_file)
         
     | 
| 
       1657 
1782 
     | 
    
         
             
                  end
         
     | 
| 
       1658 
1783 
     | 
    
         
             
                else
         
     | 
    
        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)
         
     | 
| 
         @@ -424,8 +425,8 @@ class WWID 
     | 
|
| 
       424 
425 
     | 
    
         
             
              ## @param      guessed  (Boolean) already guessed and failed
         
     | 
| 
       425 
426 
     | 
    
         
             
              ##
         
     | 
| 
       426 
427 
     | 
    
         
             
              def guess_section(frag, guessed: false)
         
     | 
| 
       427 
     | 
    
         
            -
                return 'All' if frag =~  
     | 
| 
       428 
     | 
    
         
            -
             
     | 
| 
      
 428 
     | 
    
         
            +
                return 'All' if frag =~ /^all$/i
         
     | 
| 
      
 429 
     | 
    
         
            +
                frag ||= @current_section
         
     | 
| 
       429 
430 
     | 
    
         
             
                sections.each { |section| return section.cap_first if frag.downcase == section.downcase }
         
     | 
| 
       430 
431 
     | 
    
         
             
                section = false
         
     | 
| 
       431 
432 
     | 
    
         
             
                re = frag.split('').join('.*?')
         
     | 
| 
         @@ -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
         
     | 
| 
         @@ -626,6 +627,7 @@ class WWID 
     | 
|
| 
       626 
627 
     | 
    
         
             
              def import_timing(path, opt = {})
         
     | 
| 
       627 
628 
     | 
    
         
             
                section = opt[:section] || @current_section
         
     | 
| 
       628 
629 
     | 
    
         
             
                opt[:no_overlap] ||= false
         
     | 
| 
      
 630 
     | 
    
         
            +
                opt[:autotag] ||= @auto_tag
         
     | 
| 
       629 
631 
     | 
    
         | 
| 
       630 
632 
     | 
    
         
             
                add_section(section) unless @content.has_key?(section)
         
     | 
| 
       631 
633 
     | 
    
         | 
| 
         @@ -656,7 +658,7 @@ class WWID 
     | 
|
| 
       656 
658 
     | 
    
         
             
                      title += " @#{tag}"
         
     | 
| 
       657 
659 
     | 
    
         
             
                    end
         
     | 
| 
       658 
660 
     | 
    
         
             
                  end
         
     | 
| 
       659 
     | 
    
         
            -
                  title = autotag(title) if  
     | 
| 
      
 661 
     | 
    
         
            +
                  title = autotag(title) if opt[:autotag]
         
     | 
| 
       660 
662 
     | 
    
         
             
                  title += " @done(#{end_time.strftime('%Y-%m-%d %H:%M')})"
         
     | 
| 
       661 
663 
     | 
    
         
             
                  title.gsub!(/ +/, ' ')
         
     | 
| 
       662 
664 
     | 
    
         
             
                  title.strip!
         
     | 
| 
         @@ -757,7 +759,7 @@ class WWID 
     | 
|
| 
       757 
759 
     | 
    
         
             
                  all_items.concat(@content[section]['items'].dup) if @content.key?(section)
         
     | 
| 
       758 
760 
     | 
    
         
             
                end
         
     | 
| 
       759 
761 
     | 
    
         | 
| 
       760 
     | 
    
         
            -
                if opt[:tag] 
     | 
| 
      
 762 
     | 
    
         
            +
                if opt[:tag]&.length
         
     | 
| 
       761 
763 
     | 
    
         
             
                  all_items.select! { |item| item.has_tags?(opt[:tag], opt[:tag_bool]) }
         
     | 
| 
       762 
764 
     | 
    
         
             
                elsif opt[:search]&.length
         
     | 
| 
       763 
765 
     | 
    
         
             
                  all_items.select! { |item| item.matches_search?(opt[:search]) }
         
     | 
| 
         @@ -771,9 +773,14 @@ class WWID 
     | 
|
| 
       771 
773 
     | 
    
         
             
              ##
         
     | 
| 
       772 
774 
     | 
    
         
             
              ## @return     (String) The selected option
         
     | 
| 
       773 
775 
     | 
    
         
             
              ##
         
     | 
| 
       774 
     | 
    
         
            -
              def choose_from(options, prompt)
         
     | 
| 
      
 776 
     | 
    
         
            +
              def choose_from(options, prompt: 'Make a selection: ', multiple: false, fzf_args: [])
         
     | 
| 
       775 
777 
     | 
    
         
             
                fzf = File.join(File.dirname(__FILE__), '../helpers/fuzzyfilefinder')
         
     | 
| 
       776 
     | 
    
         
            -
                 
     | 
| 
      
 778 
     | 
    
         
            +
                fzf_args << '-1'
         
     | 
| 
      
 779 
     | 
    
         
            +
                fzf_args << %(--prompt "#{prompt}")
         
     | 
| 
      
 780 
     | 
    
         
            +
                fzf_args << '--multi' if multiple
         
     | 
| 
      
 781 
     | 
    
         
            +
                header = "esc: cancel,#{multiple ? ' tab: multi-select, ctrl-a: select all,' : ''} return: confirm"
         
     | 
| 
      
 782 
     | 
    
         
            +
                fzf_args << %(--header "#{header}")
         
     | 
| 
      
 783 
     | 
    
         
            +
                res = `echo #{Shellwords.escape(options.join("\n"))}|#{fzf} #{fzf_args.join(' ')}`
         
     | 
| 
       777 
784 
     | 
    
         
             
                return false if res.strip.size.zero?
         
     | 
| 
       778 
785 
     | 
    
         | 
| 
       779 
786 
     | 
    
         
             
                res
         
     | 
| 
         @@ -807,7 +814,7 @@ class WWID 
     | 
|
| 
       807 
814 
     | 
    
         
             
                    ') ',
         
     | 
| 
       808 
815 
     | 
    
         
             
                    item['date'],
         
     | 
| 
       809 
816 
     | 
    
         
             
                    ' | ',
         
     | 
| 
       810 
     | 
    
         
            -
                    item['title'] 
     | 
| 
      
 817 
     | 
    
         
            +
                    item['title']
         
     | 
| 
       811 
818 
     | 
    
         
             
                  ]
         
     | 
| 
       812 
819 
     | 
    
         
             
                  if opt[:section] =~ /^all/i
         
     | 
| 
       813 
820 
     | 
    
         
             
                    out.concat([
         
     | 
| 
         @@ -818,8 +825,15 @@ class WWID 
     | 
|
| 
       818 
825 
     | 
    
         
             
                  end
         
     | 
| 
       819 
826 
     | 
    
         
             
                  out.join('')
         
     | 
| 
       820 
827 
     | 
    
         
             
                end
         
     | 
| 
       821 
     | 
    
         
            -
             
     | 
| 
       822 
     | 
    
         
            -
             
     | 
| 
      
 828 
     | 
    
         
            +
                fzf_args = [
         
     | 
| 
      
 829 
     | 
    
         
            +
                  %(--header="Arrows: navigate, tab: mark for selection, ctrl-a: select all, enter: commit"),
         
     | 
| 
      
 830 
     | 
    
         
            +
                  %(--prompt="Select entries to act on > "),
         
     | 
| 
      
 831 
     | 
    
         
            +
                  '-1',
         
     | 
| 
      
 832 
     | 
    
         
            +
                  '-m',
         
     | 
| 
      
 833 
     | 
    
         
            +
                  '--bind ctrl-a:select-all',
         
     | 
| 
      
 834 
     | 
    
         
            +
                  %(-q "#{opt[:query]}")
         
     | 
| 
      
 835 
     | 
    
         
            +
                ]
         
     | 
| 
      
 836 
     | 
    
         
            +
                res = `echo #{Shellwords.escape(options.join("\n"))}|#{fzf} #{fzf_args.join(' ')}`
         
     | 
| 
       823 
837 
     | 
    
         
             
                selected = []
         
     | 
| 
       824 
838 
     | 
    
         
             
                res.split(/\n/).each do |item|
         
     | 
| 
       825 
839 
     | 
    
         
             
                  idx = item.match(/^(\d+)\)/)[1].to_i
         
     | 
| 
         @@ -841,62 +855,71 @@ class WWID 
     | 
|
| 
       841 
855 
     | 
    
         
             
                end
         
     | 
| 
       842 
856 
     | 
    
         | 
| 
       843 
857 
     | 
    
         
             
                unless has_action
         
     | 
| 
       844 
     | 
    
         
            -
                   
     | 
| 
       845 
     | 
    
         
            -
             
     | 
| 
       846 
     | 
    
         
            -
             
     | 
| 
       847 
     | 
    
         
            -
             
     | 
| 
       848 
     | 
    
         
            -
             
     | 
| 
       849 
     | 
    
         
            -
             
     | 
| 
       850 
     | 
    
         
            -
             
     | 
| 
       851 
     | 
    
         
            -
             
     | 
| 
       852 
     | 
    
         
            -
             
     | 
| 
       853 
     | 
    
         
            -
             
     | 
| 
       854 
     | 
    
         
            -
             
     | 
| 
       855 
     | 
    
         
            -
             
     | 
| 
       856 
     | 
    
         
            -
             
     | 
| 
       857 
     | 
    
         
            -
             
     | 
| 
       858 
     | 
    
         
            -
             
     | 
| 
       859 
     | 
    
         
            -
                   
     | 
| 
       860 
     | 
    
         
            -
             
     | 
| 
       861 
     | 
    
         
            -
             
     | 
| 
       862 
     | 
    
         
            -
             
     | 
| 
       863 
     | 
    
         
            -
                     
     | 
| 
       864 
     | 
    
         
            -
                     
     | 
| 
       865 
     | 
    
         
            -
             
     | 
| 
       866 
     | 
    
         
            -
             
     | 
| 
       867 
     | 
    
         
            -
             
     | 
| 
       868 
     | 
    
         
            -
             
     | 
| 
       869 
     | 
    
         
            -
             
     | 
| 
       870 
     | 
    
         
            -
             
     | 
| 
       871 
     | 
    
         
            -
                       
     | 
| 
       872 
     | 
    
         
            -
                       
     | 
| 
       873 
     | 
    
         
            -
                       
     | 
| 
       874 
     | 
    
         
            -
                      opt[: 
     | 
| 
      
 858 
     | 
    
         
            +
                  choice = choose_from([
         
     | 
| 
      
 859 
     | 
    
         
            +
                                         'add tag',
         
     | 
| 
      
 860 
     | 
    
         
            +
                                         'remove tag',
         
     | 
| 
      
 861 
     | 
    
         
            +
                                         'cancel',
         
     | 
| 
      
 862 
     | 
    
         
            +
                                         'delete',
         
     | 
| 
      
 863 
     | 
    
         
            +
                                         'finish',
         
     | 
| 
      
 864 
     | 
    
         
            +
                                         'flag',
         
     | 
| 
      
 865 
     | 
    
         
            +
                                         'archive',
         
     | 
| 
      
 866 
     | 
    
         
            +
                                         'move',
         
     | 
| 
      
 867 
     | 
    
         
            +
                                         'edit',
         
     | 
| 
      
 868 
     | 
    
         
            +
                                         'output formatted'
         
     | 
| 
      
 869 
     | 
    
         
            +
                                       ],
         
     | 
| 
      
 870 
     | 
    
         
            +
                                       prompt: 'What do you want to do with the selected items? > ',
         
     | 
| 
      
 871 
     | 
    
         
            +
                                       multiple: true,
         
     | 
| 
      
 872 
     | 
    
         
            +
                                       fzf_args: ['--height=60%', '--tac', '--no-sort'])
         
     | 
| 
      
 873 
     | 
    
         
            +
                  return unless choice
         
     | 
| 
      
 874 
     | 
    
         
            +
             
     | 
| 
      
 875 
     | 
    
         
            +
                  to_do = choice.strip.split(/\n/)
         
     | 
| 
      
 876 
     | 
    
         
            +
                  to_do.each do |action|
         
     | 
| 
      
 877 
     | 
    
         
            +
                    case action
         
     | 
| 
      
 878 
     | 
    
         
            +
                    when /(add|remove) tag/
         
     | 
| 
      
 879 
     | 
    
         
            +
                      type = action =~ /^add/ ? 'add' : 'remove'
         
     | 
| 
      
 880 
     | 
    
         
            +
                      if opt[:tag]
         
     | 
| 
      
 881 
     | 
    
         
            +
                        warn "'add tag' and 'remove tag' can not be used together"
         
     | 
| 
      
 882 
     | 
    
         
            +
                        Process.exit 1
         
     | 
| 
      
 883 
     | 
    
         
            +
                      end
         
     | 
| 
      
 884 
     | 
    
         
            +
                      print "#{colors['yellow']}Tag to #{type}: #{colors['reset']}"
         
     | 
| 
      
 885 
     | 
    
         
            +
                      tag = STDIN.gets
         
     | 
| 
      
 886 
     | 
    
         
            +
                      return if tag =~ /^ *$/
         
     | 
| 
      
 887 
     | 
    
         
            +
                      opt[:tag] = tag.strip.sub(/^@/, '')
         
     | 
| 
      
 888 
     | 
    
         
            +
                      opt[:remove] = true if type == 'remove'
         
     | 
| 
      
 889 
     | 
    
         
            +
                    when /output formatted/
         
     | 
| 
      
 890 
     | 
    
         
            +
                      output_format = choose_from(%w[doing taskpaper json timeline html csv].sort, prompt: 'Which output format? > ', fzf_args: ['--height=60%', '--tac', '--no-sort'])
         
     | 
| 
      
 891 
     | 
    
         
            +
                      return if tag =~ /^ *$/
         
     | 
| 
      
 892 
     | 
    
         
            +
                      opt[:output] = output_format.strip
         
     | 
| 
      
 893 
     | 
    
         
            +
                      res = opt[:force] ? false : yn('Save to file?', default_response: 'n')
         
     | 
| 
      
 894 
     | 
    
         
            +
                      if res
         
     | 
| 
      
 895 
     | 
    
         
            +
                        print "#{colors['yellow']}File path/name: #{colors['reset']}"
         
     | 
| 
      
 896 
     | 
    
         
            +
                        filename = STDIN.gets.strip
         
     | 
| 
      
 897 
     | 
    
         
            +
                        return if filename.empty?
         
     | 
| 
      
 898 
     | 
    
         
            +
                        opt[:save_to] = filename
         
     | 
| 
      
 899 
     | 
    
         
            +
                      end
         
     | 
| 
      
 900 
     | 
    
         
            +
                    when /archive/
         
     | 
| 
      
 901 
     | 
    
         
            +
                      opt[:archive] = true
         
     | 
| 
      
 902 
     | 
    
         
            +
                    when /delete/
         
     | 
| 
      
 903 
     | 
    
         
            +
                      opt[:delete] = true
         
     | 
| 
      
 904 
     | 
    
         
            +
                    when /edit/
         
     | 
| 
      
 905 
     | 
    
         
            +
                      opt[:editor] = true
         
     | 
| 
      
 906 
     | 
    
         
            +
                    when /finish/
         
     | 
| 
      
 907 
     | 
    
         
            +
                      opt[:finish] = true
         
     | 
| 
      
 908 
     | 
    
         
            +
                    when /cancel/
         
     | 
| 
      
 909 
     | 
    
         
            +
                      opt[:cancel] = true
         
     | 
| 
      
 910 
     | 
    
         
            +
                    when /move/
         
     | 
| 
      
 911 
     | 
    
         
            +
                      section = choose_section.strip
         
     | 
| 
      
 912 
     | 
    
         
            +
                      opt[:move] = section.strip unless section =~ /^ *$/
         
     | 
| 
      
 913 
     | 
    
         
            +
                    when /flag/
         
     | 
| 
      
 914 
     | 
    
         
            +
                      opt[:flag] = true
         
     | 
| 
       875 
915 
     | 
    
         
             
                    end
         
     | 
| 
       876 
     | 
    
         
            -
                  when /archive/
         
     | 
| 
       877 
     | 
    
         
            -
                    opt[:archive] = true
         
     | 
| 
       878 
     | 
    
         
            -
                  when /delete/
         
     | 
| 
       879 
     | 
    
         
            -
                    opt[:delete] = true
         
     | 
| 
       880 
     | 
    
         
            -
                  when /edit/
         
     | 
| 
       881 
     | 
    
         
            -
                    opt[:editor] = true
         
     | 
| 
       882 
     | 
    
         
            -
                  when /finish/
         
     | 
| 
       883 
     | 
    
         
            -
                    opt[:finish] = true
         
     | 
| 
       884 
     | 
    
         
            -
                  when /cancel/
         
     | 
| 
       885 
     | 
    
         
            -
                    opt[:cancel] = true
         
     | 
| 
       886 
     | 
    
         
            -
                  when /move/
         
     | 
| 
       887 
     | 
    
         
            -
                    section = choose_section.strip
         
     | 
| 
       888 
     | 
    
         
            -
                    return if section =~ /^ *$/
         
     | 
| 
       889 
     | 
    
         
            -
                    opt[:move] = section.strip
         
     | 
| 
       890 
     | 
    
         
            -
                  when /flag/
         
     | 
| 
       891 
     | 
    
         
            -
                    opt[:flag] = true
         
     | 
| 
       892 
916 
     | 
    
         
             
                  end
         
     | 
| 
       893 
917 
     | 
    
         
             
                end
         
     | 
| 
       894 
918 
     | 
    
         | 
| 
       895 
     | 
    
         
            -
             
     | 
| 
       896 
919 
     | 
    
         
             
                if opt[:delete]
         
     | 
| 
       897 
     | 
    
         
            -
                  res = yn("Delete #{selected.size} items?", default_response: 'y')
         
     | 
| 
      
 920 
     | 
    
         
            +
                  res = opt[:force] ? true : yn("Delete #{selected.size} items?", default_response: 'y')
         
     | 
| 
       898 
921 
     | 
    
         
             
                  if res
         
     | 
| 
       899 
     | 
    
         
            -
                    selected.each {|item| delete_item(item) }
         
     | 
| 
      
 922 
     | 
    
         
            +
                    selected.each { |item| delete_item(item) }
         
     | 
| 
       900 
923 
     | 
    
         
             
                    write(@doing_file)
         
     | 
| 
       901 
924 
     | 
    
         
             
                  end
         
     | 
| 
       902 
925 
     | 
    
         
             
                  return
         
     | 
| 
         @@ -990,13 +1013,16 @@ class WWID 
     | 
|
| 
       990 
1013 
     | 
    
         
             
                    item
         
     | 
| 
       991 
1014 
     | 
    
         
             
                  end
         
     | 
| 
       992 
1015 
     | 
    
         | 
| 
       993 
     | 
    
         
            -
                  @content = {'Export' => {'original' => 'Export:', 'items' => selected}}
         
     | 
| 
       994 
     | 
    
         
            -
                  options = {section: 'Export'}
         
     | 
| 
      
 1016 
     | 
    
         
            +
                  @content = { 'Export' => { 'original' => 'Export:', 'items' => selected } }
         
     | 
| 
      
 1017 
     | 
    
         
            +
                  options = { section: 'Export' }
         
     | 
| 
       995 
1018 
     | 
    
         | 
| 
       996 
     | 
    
         
            -
                   
     | 
| 
       997 
     | 
    
         
            -
             
     | 
| 
       998 
     | 
    
         
            -
                  else
         
     | 
| 
      
 1019 
     | 
    
         
            +
                  case opt[:output]
         
     | 
| 
      
 1020 
     | 
    
         
            +
                  when /doing/
         
     | 
| 
       999 
1021 
     | 
    
         
             
                    options[:template] = '- %date | %title%note'
         
     | 
| 
      
 1022 
     | 
    
         
            +
                  when /taskpaper/
         
     | 
| 
      
 1023 
     | 
    
         
            +
                    options[:template] = '- %title @date(%date)%note'
         
     | 
| 
      
 1024 
     | 
    
         
            +
                  else
         
     | 
| 
      
 1025 
     | 
    
         
            +
                    options[:output] = opt[:output]
         
     | 
| 
       1000 
1026 
     | 
    
         
             
                  end
         
     | 
| 
       1001 
1027 
     | 
    
         | 
| 
       1002 
1028 
     | 
    
         
             
                  output = list_section(options)
         
     | 
| 
         @@ -1078,7 +1104,6 @@ class WWID 
     | 
|
| 
       1078 
1104 
     | 
    
         
             
                    count = (opt[:count]).zero? ? items.length : opt[:count]
         
     | 
| 
       1079 
1105 
     | 
    
         
             
                    items.map! do |item|
         
     | 
| 
       1080 
1106 
     | 
    
         
             
                      break if idx == count
         
     | 
| 
       1081 
     | 
    
         
            -
             
     | 
| 
       1082 
1107 
     | 
    
         
             
                      finished = opt[:unfinished] && item.has_tags?('done', :and)
         
     | 
| 
       1083 
1108 
     | 
    
         
             
                      tag_match = opt[:tag].nil? || opt[:tag].empty? ? true : item.has_tags?(opt[:tag], opt[:tag_bool])
         
     | 
| 
       1084 
1109 
     | 
    
         
             
                      search_match = opt[:search].nil? || opt[:search].empty? ? true : item.matches_search?(opt[:search])
         
     | 
| 
         @@ -1497,13 +1522,85 @@ class WWID 
     | 
|
| 
       1497 
1522 
     | 
    
         
             
                end
         
     | 
| 
       1498 
1523 
     | 
    
         
             
              end
         
     | 
| 
       1499 
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 
     | 
    
         
            +
             
     | 
| 
       1500 
1596 
     | 
    
         
             
              ##
         
     | 
| 
       1501 
1597 
     | 
    
         
             
              ## @brief      Generate a menu of sections and allow user selection
         
     | 
| 
       1502 
1598 
     | 
    
         
             
              ##
         
     | 
| 
       1503 
1599 
     | 
    
         
             
              ## @return     (String) The selected section name
         
     | 
| 
       1504 
1600 
     | 
    
         
             
              ##
         
     | 
| 
       1505 
1601 
     | 
    
         
             
              def choose_section
         
     | 
| 
       1506 
     | 
    
         
            -
                choose_from(sections, 'Choose a section > ') 
     | 
| 
      
 1602 
     | 
    
         
            +
                choice = choose_from(sections.sort, prompt: 'Choose a section > ', fzf_args: ['--height=60%'])
         
     | 
| 
      
 1603 
     | 
    
         
            +
                choice ? choice.strip : choice
         
     | 
| 
       1507 
1604 
     | 
    
         
             
              end
         
     | 
| 
       1508 
1605 
     | 
    
         | 
| 
       1509 
1606 
     | 
    
         
             
              ##
         
     | 
| 
         @@ -1521,7 +1618,8 @@ class WWID 
     | 
|
| 
       1521 
1618 
     | 
    
         
             
              ## @return     (String) The selected view name
         
     | 
| 
       1522 
1619 
     | 
    
         
             
              ##
         
     | 
| 
       1523 
1620 
     | 
    
         
             
              def choose_view
         
     | 
| 
       1524 
     | 
    
         
            -
                choose_from(views, 'Choose a view > ') 
     | 
| 
      
 1621 
     | 
    
         
            +
                choice = choose_from(views.sort, prompt: 'Choose a view > ', fzf_args: ['--height=60%'])
         
     | 
| 
      
 1622 
     | 
    
         
            +
                choice ? choice.strip : choice
         
     | 
| 
       1525 
1623 
     | 
    
         
             
              end
         
     | 
| 
       1526 
1624 
     | 
    
         | 
| 
       1527 
1625 
     | 
    
         
             
              ##
         
     | 
| 
         @@ -1544,20 +1642,21 @@ class WWID 
     | 
|
| 
       1544 
1642 
     | 
    
         
             
              def list_section(opt = {})
         
     | 
| 
       1545 
1643 
     | 
    
         
             
                opt[:count] ||= 0
         
     | 
| 
       1546 
1644 
     | 
    
         
             
                count = opt[:count] - 1
         
     | 
| 
       1547 
     | 
    
         
            -
                opt[:section] ||= nil
         
     | 
| 
       1548 
     | 
    
         
            -
                opt[:format] ||= @default_date_format
         
     | 
| 
       1549 
     | 
    
         
            -
                opt[:template] ||= @default_template
         
     | 
| 
       1550 
1645 
     | 
    
         
             
                opt[:age] ||= 'newest'
         
     | 
| 
      
 1646 
     | 
    
         
            +
                opt[:date_filter] ||= []
         
     | 
| 
      
 1647 
     | 
    
         
            +
                opt[:format] ||= @default_date_format
         
     | 
| 
      
 1648 
     | 
    
         
            +
                opt[:only_timed] ||= false
         
     | 
| 
       1551 
1649 
     | 
    
         
             
                opt[:order] ||= 'desc'
         
     | 
| 
       1552 
     | 
    
         
            -
                opt[: 
     | 
| 
      
 1650 
     | 
    
         
            +
                opt[:search] ||= false
         
     | 
| 
      
 1651 
     | 
    
         
            +
                opt[:section] ||= nil
         
     | 
| 
      
 1652 
     | 
    
         
            +
                opt[:sort_tags] ||= false
         
     | 
| 
       1553 
1653 
     | 
    
         
             
                opt[:tag_filter] ||= false
         
     | 
| 
      
 1654 
     | 
    
         
            +
                opt[:tag_order] ||= 'asc'
         
     | 
| 
       1554 
1655 
     | 
    
         
             
                opt[:tags_color] ||= false
         
     | 
| 
      
 1656 
     | 
    
         
            +
                opt[:template] ||= @default_template
         
     | 
| 
       1555 
1657 
     | 
    
         
             
                opt[:times] ||= false
         
     | 
| 
      
 1658 
     | 
    
         
            +
                opt[:today] ||= false
         
     | 
| 
       1556 
1659 
     | 
    
         
             
                opt[:totals] ||= false
         
     | 
| 
       1557 
     | 
    
         
            -
                opt[:sort_tags] ||= false
         
     | 
| 
       1558 
     | 
    
         
            -
                opt[:search] ||= false
         
     | 
| 
       1559 
     | 
    
         
            -
                opt[:only_timed] ||= false
         
     | 
| 
       1560 
     | 
    
         
            -
                opt[:date_filter] ||= []
         
     | 
| 
       1561 
1660 
     | 
    
         | 
| 
       1562 
1661 
     | 
    
         
             
                # opt[:highlight] ||= true
         
     | 
| 
       1563 
1662 
     | 
    
         
             
                section = ''
         
     | 
| 
         @@ -1610,7 +1709,7 @@ class WWID 
     | 
|
| 
       1610 
1709 
     | 
    
         | 
| 
       1611 
1710 
     | 
    
         
             
                if opt[:only_timed]
         
     | 
| 
       1612 
1711 
     | 
    
         
             
                  items.delete_if do |item|
         
     | 
| 
       1613 
     | 
    
         
            -
                    get_interval(item) == false
         
     | 
| 
      
 1712 
     | 
    
         
            +
                    get_interval(item, record: false) == false
         
     | 
| 
       1614 
1713 
     | 
    
         
             
                  end
         
     | 
| 
       1615 
1714 
     | 
    
         
             
                end
         
     | 
| 
       1616 
1715 
     | 
    
         | 
| 
         @@ -1645,7 +1744,7 @@ class WWID 
     | 
|
| 
       1645 
1744 
     | 
    
         
             
                      arr = i['note'].map { |line| line.strip }.delete_if { |e| e =~ /^\s*$/ }
         
     | 
| 
       1646 
1745 
     | 
    
         
             
                      note = arr.join("\n") unless arr.nil?
         
     | 
| 
       1647 
1746 
     | 
    
         
             
                    end
         
     | 
| 
       1648 
     | 
    
         
            -
                    interval = get_interval(i, false) if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
         
     | 
| 
      
 1747 
     | 
    
         
            +
                    interval = get_interval(i, formatted: false) if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
         
     | 
| 
       1649 
1748 
     | 
    
         
             
                    interval ||= 0
         
     | 
| 
       1650 
1749 
     | 
    
         
             
                    output.push(CSV.generate_line([i['date'], i['title'], note, interval, i['section']]))
         
     | 
| 
       1651 
1750 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1664,7 +1763,7 @@ class WWID 
     | 
|
| 
       1664 
1763 
     | 
    
         
             
                    end
         
     | 
| 
       1665 
1764 
     | 
    
         
             
                    if i['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
         
     | 
| 
       1666 
1765 
     | 
    
         
             
                      end_date = Time.parse(Regexp.last_match(1))
         
     | 
| 
       1667 
     | 
    
         
            -
                      interval = get_interval(i, false)
         
     | 
| 
      
 1766 
     | 
    
         
            +
                      interval = get_interval(i, formatted: false)
         
     | 
| 
       1668 
1767 
     | 
    
         
             
                    end
         
     | 
| 
       1669 
1768 
     | 
    
         
             
                    end_date ||= ''
         
     | 
| 
       1670 
1769 
     | 
    
         
             
                    interval ||= 0
         
     | 
| 
         @@ -1713,7 +1812,7 @@ class WWID 
     | 
|
| 
       1713 
1812 
     | 
    
         
             
                    out = {
         
     | 
| 
       1714 
1813 
     | 
    
         
             
                      'section' => section,
         
     | 
| 
       1715 
1814 
     | 
    
         
             
                      'items' => items_out,
         
     | 
| 
       1716 
     | 
    
         
            -
                      'timers' => tag_times('json', opt[:sort_tags])
         
     | 
| 
      
 1815 
     | 
    
         
            +
                      'timers' => tag_times(format: 'json', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order])
         
     | 
| 
       1717 
1816 
     | 
    
         
             
                    }.to_json
         
     | 
| 
       1718 
1817 
     | 
    
         
             
                  elsif opt[:output] == 'timeline'
         
     | 
| 
       1719 
1818 
     | 
    
         
             
                    template = <<~EOTEMPLATE
         
     | 
| 
         @@ -1794,7 +1893,7 @@ class WWID 
     | 
|
| 
       1794 
1893 
     | 
    
         
             
                            css_template
         
     | 
| 
       1795 
1894 
     | 
    
         
             
                          end
         
     | 
| 
       1796 
1895 
     | 
    
         | 
| 
       1797 
     | 
    
         
            -
                  totals = opt[:totals] ? tag_times('html', opt[:sort_tags]) : ''
         
     | 
| 
      
 1896 
     | 
    
         
            +
                  totals = opt[:totals] ? tag_times(format: 'html', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
         
     | 
| 
       1798 
1897 
     | 
    
         
             
                  engine = Haml::Engine.new(template)
         
     | 
| 
       1799 
1898 
     | 
    
         
             
                  out = engine.render(Object.new,
         
     | 
| 
       1800 
1899 
     | 
    
         
             
                                     { :@items => items_out, :@page_title => page_title, :@style => style, :@totals => totals })
         
     | 
| 
         @@ -1835,7 +1934,7 @@ class WWID 
     | 
|
| 
       1835 
1934 
     | 
    
         | 
| 
       1836 
1935 
     | 
    
         
             
                    output.sub!(/%date/, item['date'].strftime(opt[:format]))
         
     | 
| 
       1837 
1936 
     | 
    
         | 
| 
       1838 
     | 
    
         
            -
                    interval = get_interval(item) if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
         
     | 
| 
      
 1937 
     | 
    
         
            +
                    interval = get_interval(item, record: true) if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
         
     | 
| 
       1839 
1938 
     | 
    
         
             
                    interval ||= ''
         
     | 
| 
       1840 
1939 
     | 
    
         
             
                    output.sub!(/%interval/, interval)
         
     | 
| 
       1841 
1940 
     | 
    
         | 
| 
         @@ -1885,7 +1984,8 @@ class WWID 
     | 
|
| 
       1885 
1984 
     | 
    
         | 
| 
       1886 
1985 
     | 
    
         
             
                    out += "#{output}\n"
         
     | 
| 
       1887 
1986 
     | 
    
         
             
                  end
         
     | 
| 
       1888 
     | 
    
         
            -
             
     | 
| 
      
 1987 
     | 
    
         
            +
             
     | 
| 
      
 1988 
     | 
    
         
            +
                  out += tag_times(format: 'text', sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) if opt[:totals]
         
     | 
| 
       1889 
1989 
     | 
    
         
             
                end
         
     | 
| 
       1890 
1990 
     | 
    
         
             
                out
         
     | 
| 
       1891 
1991 
     | 
    
         
             
              end
         
     | 
| 
         @@ -1897,7 +1997,7 @@ class WWID 
     | 
|
| 
       1897 
1997 
     | 
    
         
             
              ## @param      section      (String) The source section
         
     | 
| 
       1898 
1998 
     | 
    
         
             
              ## @param      options      (Hash) Options
         
     | 
| 
       1899 
1999 
     | 
    
         
             
              ##
         
     | 
| 
       1900 
     | 
    
         
            -
              def archive(section =  
     | 
| 
      
 2000 
     | 
    
         
            +
              def archive(section = @current_section, options = {})
         
     | 
| 
       1901 
2001 
     | 
    
         
             
                count       = options[:keep] || 0
         
     | 
| 
       1902 
2002 
     | 
    
         
             
                destination = options[:destination] || 'Archive'
         
     | 
| 
       1903 
2003 
     | 
    
         
             
                tags        = options[:tags] || []
         
     | 
| 
         @@ -1956,7 +2056,7 @@ class WWID 
     | 
|
| 
       1956 
2056 
     | 
    
         
             
                      end
         
     | 
| 
       1957 
2057 
     | 
    
         
             
                    end
         
     | 
| 
       1958 
2058 
     | 
    
         
             
                    moved_items.each do |item|
         
     | 
| 
       1959 
     | 
    
         
            -
                      if label && section !=  
     | 
| 
      
 2059 
     | 
    
         
            +
                      if label && section != @current_section
         
     | 
| 
       1960 
2060 
     | 
    
         
             
                        item['title'] =
         
     | 
| 
       1961 
2061 
     | 
    
         
             
                          item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
         
     | 
| 
       1962 
2062 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -1969,7 +2069,7 @@ class WWID 
     | 
|
| 
       1969 
2069 
     | 
    
         
             
                    count = items.length if items.length < count
         
     | 
| 
       1970 
2070 
     | 
    
         | 
| 
       1971 
2071 
     | 
    
         
             
                    items.map! do |item|
         
     | 
| 
       1972 
     | 
    
         
            -
                      if label && section !=  
     | 
| 
      
 2072 
     | 
    
         
            +
                      if label && section != @current_section
         
     | 
| 
       1973 
2073 
     | 
    
         
             
                        item['title'] =
         
     | 
| 
       1974 
2074 
     | 
    
         
             
                          item['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{section})")
         
     | 
| 
       1975 
2075 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -2148,11 +2248,15 @@ class WWID 
     | 
|
| 
       2148 
2248 
     | 
    
         
             
              end
         
     | 
| 
       2149 
2249 
     | 
    
         | 
| 
       2150 
2250 
     | 
    
         
             
              ##
         
     | 
| 
       2151 
     | 
    
         
            -
              ## @brief      Get total elapsed time for all tags in 
     | 
| 
      
 2251 
     | 
    
         
            +
              ## @brief      Get total elapsed time for all tags in
         
     | 
| 
      
 2252 
     | 
    
         
            +
              ##             selection
         
     | 
| 
       2152 
2253 
     | 
    
         
             
              ##
         
     | 
| 
       2153 
     | 
    
         
            -
              ## @param      format 
     | 
| 
      
 2254 
     | 
    
         
            +
              ## @param      format        (String) return format (html,
         
     | 
| 
      
 2255 
     | 
    
         
            +
              ##                           json, or text)
         
     | 
| 
      
 2256 
     | 
    
         
            +
              ## @param      sort_by_name  (Boolean) Sort by name if true, otherwise by time
         
     | 
| 
      
 2257 
     | 
    
         
            +
              ## @param      sort_order    (String) The sort order (asc or desc)
         
     | 
| 
       2154 
2258 
     | 
    
         
             
              ##
         
     | 
| 
       2155 
     | 
    
         
            -
              def tag_times(format  
     | 
| 
      
 2259 
     | 
    
         
            +
              def tag_times(format: 'text', sort_by_name: false, sort_order: 'asc')
         
     | 
| 
       2156 
2260 
     | 
    
         
             
                return '' if @timers.empty?
         
     | 
| 
       2157 
2261 
     | 
    
         | 
| 
       2158 
2262 
     | 
    
         
             
                max = @timers.keys.sort_by { |k| k.length }.reverse[0].length + 1
         
     | 
| 
         @@ -2161,11 +2265,13 @@ class WWID 
     | 
|
| 
       2161 
2265 
     | 
    
         | 
| 
       2162 
2266 
     | 
    
         
             
                tags_data = @timers.delete_if { |_k, v| v == 0 }
         
     | 
| 
       2163 
2267 
     | 
    
         
             
                sorted_tags_data = if sort_by_name
         
     | 
| 
       2164 
     | 
    
         
            -
                                     tags_data.sort_by { |k, _v| k } 
     | 
| 
      
 2268 
     | 
    
         
            +
                                     tags_data.sort_by { |k, _v| k }
         
     | 
| 
       2165 
2269 
     | 
    
         
             
                                   else
         
     | 
| 
       2166 
2270 
     | 
    
         
             
                                     tags_data.sort_by { |_k, v| v }
         
     | 
| 
       2167 
2271 
     | 
    
         
             
                                   end
         
     | 
| 
       2168 
2272 
     | 
    
         | 
| 
      
 2273 
     | 
    
         
            +
                sorted_tags_data.reverse! if sort_order =~ /^asc/i
         
     | 
| 
      
 2274 
     | 
    
         
            +
             
     | 
| 
       2169 
2275 
     | 
    
         
             
                if format == 'html'
         
     | 
| 
       2170 
2276 
     | 
    
         
             
                  output = <<EOS
         
     | 
| 
       2171 
2277 
     | 
    
         
             
                    <table>
         
     | 
| 
         @@ -2299,19 +2405,20 @@ EOS 
     | 
|
| 
       2299 
2405 
     | 
    
         
             
              ## @param      item       (Hash) The entry
         
     | 
| 
       2300 
2406 
     | 
    
         
             
              ## @param      formatted  (Bool) Return human readable time (default seconds)
         
     | 
| 
       2301 
2407 
     | 
    
         
             
              ##
         
     | 
| 
       2302 
     | 
    
         
            -
              def get_interval(item, formatted  
     | 
| 
      
 2408 
     | 
    
         
            +
              def get_interval(item, formatted: true, record: true)
         
     | 
| 
       2303 
2409 
     | 
    
         
             
                done = nil
         
     | 
| 
       2304 
2410 
     | 
    
         
             
                start = nil
         
     | 
| 
       2305 
2411 
     | 
    
         | 
| 
       2306 
2412 
     | 
    
         
             
                if @interval_cache.keys.include? item['title']
         
     | 
| 
       2307 
2413 
     | 
    
         
             
                  seconds = @interval_cache[item['title']]
         
     | 
| 
      
 2414 
     | 
    
         
            +
                  record_tag_times(item, seconds) if record
         
     | 
| 
       2308 
2415 
     | 
    
         
             
                  return seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
         
     | 
| 
       2309 
2416 
     | 
    
         
             
                end
         
     | 
| 
       2310 
2417 
     | 
    
         | 
| 
       2311 
2418 
     | 
    
         
             
                if item['title'] =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
         
     | 
| 
       2312 
2419 
     | 
    
         
             
                  done = Time.parse(Regexp.last_match(1))
         
     | 
| 
       2313 
2420 
     | 
    
         
             
                else
         
     | 
| 
       2314 
     | 
    
         
            -
                  return  
     | 
| 
      
 2421 
     | 
    
         
            +
                  return false
         
     | 
| 
       2315 
2422 
     | 
    
         
             
                end
         
     | 
| 
       2316 
2423 
     | 
    
         | 
| 
       2317 
2424 
     | 
    
         
             
                start = if item['title'] =~ /@start\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
         
     | 
| 
         @@ -2322,20 +2429,34 @@ EOS 
     | 
|
| 
       2322 
2429 
     | 
    
         | 
| 
       2323 
2430 
     | 
    
         
             
                seconds = (done - start).to_i
         
     | 
| 
       2324 
2431 
     | 
    
         | 
| 
      
 2432 
     | 
    
         
            +
                if record
         
     | 
| 
      
 2433 
     | 
    
         
            +
                  record_tag_times(item, seconds)
         
     | 
| 
      
 2434 
     | 
    
         
            +
                end
         
     | 
| 
      
 2435 
     | 
    
         
            +
             
     | 
| 
      
 2436 
     | 
    
         
            +
                @interval_cache[item['title']] = seconds
         
     | 
| 
      
 2437 
     | 
    
         
            +
             
     | 
| 
      
 2438 
     | 
    
         
            +
                return seconds > 0 ? seconds : false unless formatted
         
     | 
| 
      
 2439 
     | 
    
         
            +
             
     | 
| 
      
 2440 
     | 
    
         
            +
                seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
         
     | 
| 
      
 2441 
     | 
    
         
            +
              end
         
     | 
| 
      
 2442 
     | 
    
         
            +
             
     | 
| 
      
 2443 
     | 
    
         
            +
              ##
         
     | 
| 
      
 2444 
     | 
    
         
            +
              ## @brief      Record times for item tags
         
     | 
| 
      
 2445 
     | 
    
         
            +
              ##
         
     | 
| 
      
 2446 
     | 
    
         
            +
              ## @param      item  The item
         
     | 
| 
      
 2447 
     | 
    
         
            +
              ##
         
     | 
| 
      
 2448 
     | 
    
         
            +
              def record_tag_times(item, seconds)
         
     | 
| 
      
 2449 
     | 
    
         
            +
                return if @recorded_items.include?(item)
         
     | 
| 
      
 2450 
     | 
    
         
            +
             
     | 
| 
       2325 
2451 
     | 
    
         
             
                item['title'].scan(/(?mi)@(\S+?)(\(.*\))?(?=\s|$)/).each do |m|
         
     | 
| 
       2326 
2452 
     | 
    
         
             
                  k = m[0] == 'done' ? 'All' : m[0].downcase
         
     | 
| 
       2327 
     | 
    
         
            -
                  if @timers. 
     | 
| 
      
 2453 
     | 
    
         
            +
                  if @timers.key?(k)
         
     | 
| 
       2328 
2454 
     | 
    
         
             
                    @timers[k] += seconds
         
     | 
| 
       2329 
2455 
     | 
    
         
             
                  else
         
     | 
| 
       2330 
2456 
     | 
    
         
             
                    @timers[k] = seconds
         
     | 
| 
       2331 
2457 
     | 
    
         
             
                  end
         
     | 
| 
      
 2458 
     | 
    
         
            +
                  @recorded_items.push(item)
         
     | 
| 
       2332 
2459 
     | 
    
         
             
                end
         
     | 
| 
       2333 
     | 
    
         
            -
             
     | 
| 
       2334 
     | 
    
         
            -
                @interval_cache[item['title']] = seconds
         
     | 
| 
       2335 
     | 
    
         
            -
             
     | 
| 
       2336 
     | 
    
         
            -
                return seconds unless formatted
         
     | 
| 
       2337 
     | 
    
         
            -
             
     | 
| 
       2338 
     | 
    
         
            -
                seconds > 0 ? '%02d:%02d:%02d' % fmt_time(seconds) : false
         
     | 
| 
       2339 
2460 
     | 
    
         
             
              end
         
     | 
| 
       2340 
2461 
     | 
    
         | 
| 
       2341 
2462 
     | 
    
         
             
              ##
         
     | 
    
        data/lib/doing.rb
    CHANGED
    
    
    
        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- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-10-14 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake
         
     |