timetrap 1.15.1 → 1.15.4
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 +5 -5
 - data/.github/pull_request_template.md +29 -0
 - data/.github/workflows/rspec.yml +16 -0
 - data/.gitignore +1 -0
 - data/.rspec +1 -2
 - data/.travis.yml +6 -3
 - data/CONTRIBUTORS +1 -0
 - data/README.md +39 -6
 - data/completions/bash/timetrap-autocomplete.bash +2 -1
 - data/lib/timetrap/cli.rb +24 -5
 - data/lib/timetrap/formatters/csv.rb +5 -1
 - data/lib/timetrap/formatters/ical.rb +8 -16
 - data/lib/timetrap/formatters/json.rb +6 -1
 - data/lib/timetrap/helpers.rb +6 -6
 - data/lib/timetrap/models.rb +1 -20
 - data/lib/timetrap/schema.rb +47 -0
 - data/lib/timetrap/version.rb +1 -1
 - data/lib/timetrap.rb +6 -2
 - data/spec/spec_helper.rb +40 -0
 - data/spec/support/local_time.rb +7 -0
 - data/spec/support/with_rounding_on.rb +9 -0
 - data/spec/support/with_stubbed_config.rb +7 -0
 - data/spec/timetrap_spec.rb +318 -300
 - data/timetrap.gemspec +9 -9
 - metadata +58 -47
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5c87342eeaac646bc3e628a35549cb078a8aa5ad2e469dc14afe4bca7051bfe2
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 9041a05cc7f251e4bcbff0dcf7335bdc613c1ab0a49103bd1068cca432823d22
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 9b5e45261a137be9e44e07f127e60a21849517208df71dfabbe1a14483e4819aceec31892f02b4c2f0bf245674084a895e6398cc1c6e3c55910479e7763b26d7
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c92729865ec97ff09633a2d5a195584eee9b94ae9168cde285b8df83c832a23d75b19741de86fda8f9aeb3fd225f2a7a53f84d225212d27adb5931559c8501f3
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <!--- Provide a general summary of your changes in the Title above -->
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## Description
         
     | 
| 
      
 4 
     | 
    
         
            +
            <!--- Describe your changes in detail -->
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ## Motivation and Context
         
     | 
| 
      
 7 
     | 
    
         
            +
            <!--- Why is this change required? What problem does it solve? -->
         
     | 
| 
      
 8 
     | 
    
         
            +
            <!--- If it fixes an open issue, please link to the issue here. -->
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            ## How Has This Been Tested?
         
     | 
| 
      
 11 
     | 
    
         
            +
            <!--- Please describe in detail how you tested your changes. -->
         
     | 
| 
      
 12 
     | 
    
         
            +
            <!--- Include details of your testing environment, and the tests you ran to -->
         
     | 
| 
      
 13 
     | 
    
         
            +
            <!--- see how your change affects other areas of the code, etc. -->
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ## Screenshots (if appropriate):
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            ## Types of changes
         
     | 
| 
      
 18 
     | 
    
         
            +
            <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
         
     | 
| 
      
 19 
     | 
    
         
            +
            - [ ] Bug fix (non-breaking change which fixes an issue)
         
     | 
| 
      
 20 
     | 
    
         
            +
            - [ ] New feature (non-breaking change which adds functionality)
         
     | 
| 
      
 21 
     | 
    
         
            +
            - [ ] Breaking change (fix or feature that would cause existing functionality to change)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ## Checklist:
         
     | 
| 
      
 24 
     | 
    
         
            +
            <!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
         
     | 
| 
      
 25 
     | 
    
         
            +
            <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
         
     | 
| 
      
 26 
     | 
    
         
            +
            - [ ] My code follows the code style of this project.
         
     | 
| 
      
 27 
     | 
    
         
            +
            - [ ] I have updated the documentation accordingly.
         
     | 
| 
      
 28 
     | 
    
         
            +
            - [ ] I have added tests to cover my changes.
         
     | 
| 
      
 29 
     | 
    
         
            +
            - [ ] All new and existing tests passed.
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            name: rspec
         
     | 
| 
      
 2 
     | 
    
         
            +
            on:
         
     | 
| 
      
 3 
     | 
    
         
            +
              - push
         
     | 
| 
      
 4 
     | 
    
         
            +
              - pull_request
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            jobs:
         
     | 
| 
      
 7 
     | 
    
         
            +
              test:
         
     | 
| 
      
 8 
     | 
    
         
            +
                name: Run Rspec
         
     | 
| 
      
 9 
     | 
    
         
            +
                runs-on: ubuntu-latest
         
     | 
| 
      
 10 
     | 
    
         
            +
                steps:
         
     | 
| 
      
 11 
     | 
    
         
            +
                  - uses: actions/checkout@v2
         
     | 
| 
      
 12 
     | 
    
         
            +
                  - uses: ruby/setup-ruby@v1
         
     | 
| 
      
 13 
     | 
    
         
            +
                    with:
         
     | 
| 
      
 14 
     | 
    
         
            +
                      ruby-version: '2.7'
         
     | 
| 
      
 15 
     | 
    
         
            +
                  - run: bundle install
         
     | 
| 
      
 16 
     | 
    
         
            +
                  - run: rspec spec
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rspec
    CHANGED
    
    | 
         @@ -1,2 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            -- 
     | 
| 
       2 
     | 
    
         
            -
            --profile
         
     | 
| 
      
 1 
     | 
    
         
            +
            --require spec_helper
         
     | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CONTRIBUTORS
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -13,6 +13,15 @@ To install: 
     | 
|
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            This will place a ``t`` executable in your path.
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
            ***UPDATE***: The current gem release seems to be having issues installing and the gem ownership on RubyGems.org is currently in the process of being transferred.  Meanwhile, here is how to build the latest master from source:
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                $ git clone https://github.com/samg/timetrap
         
     | 
| 
      
 19 
     | 
    
         
            +
                $ cd timetrap
         
     | 
| 
      
 20 
     | 
    
         
            +
                $ gem build timetrap
         
     | 
| 
      
 21 
     | 
    
         
            +
                $ gem install timetrap_X.X.X.gem
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            If you have errors while parsing the documentation, use `--no-document` option when installing the gem, or other option is to `gem install rdoc` before installing the `timetrap`. This is a known issue from [rdoc](https://github.com/ruby/rdoc/commit/5f9603f35d8e520c761015810c005e4a5beb97c3)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
       16 
25 
     | 
    
         
             
            ### Basic Usage
         
     | 
| 
       17 
26 
     | 
    
         | 
| 
       18 
27 
     | 
    
         
             
                $ # get help
         
     | 
| 
         @@ -64,7 +73,7 @@ If you make a mistake use the `edit` command. 
     | 
|
| 
       64 
73 
     | 
    
         
             
            You check out with the `out` command.
         
     | 
| 
       65 
74 
     | 
    
         | 
| 
       66 
75 
     | 
    
         
             
                $ t out
         
     | 
| 
       67 
     | 
    
         
            -
                Checked out of sheet "coding"
         
     | 
| 
      
 76 
     | 
    
         
            +
                Checked out of entry "document timetrap" in sheet "coding"
         
     | 
| 
       68 
77 
     | 
    
         | 
| 
       69 
78 
     | 
    
         
             
            Running `edit` when you're checked out will edit the last entry you checked out
         
     | 
| 
       70 
79 
     | 
    
         
             
            of.
         
     | 
| 
         @@ -113,7 +122,7 @@ Command line flags also have short versions. 
     | 
|
| 
       113 
122 
     | 
    
         
             
                $ # equivalent to the command above
         
     | 
| 
       114 
123 
     | 
    
         
             
                $ t i -a "5 minutes ago"
         
     | 
| 
       115 
124 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
            You can consult the Chronic gem ( 
     | 
| 
      
 125 
     | 
    
         
            +
            You can consult the Chronic gem (https://github.com/mojombo/chronic) for a full
         
     | 
| 
       117 
126 
     | 
    
         
             
            list of parsable time formats, but all of these should work.
         
     | 
| 
       118 
127 
     | 
    
         | 
| 
       119 
128 
     | 
    
         
             
                $ t out --at "in 30 minutes"
         
     | 
| 
         @@ -308,7 +317,7 @@ Commands 
     | 
|
| 
       308 
317 
     | 
    
         
             
            --------
         
     | 
| 
       309 
318 
     | 
    
         | 
| 
       310 
319 
     | 
    
         
             
            **archive**
         
     | 
| 
       311 
     | 
    
         
            -
               
     | 
| 
      
 320 
     | 
    
         
            +
              Archive the selected entries (by moving them to a sheet called ``_[SHEET]``)
         
     | 
| 
       312 
321 
     | 
    
         
             
              These entries can be seen by running ``t display _[SHEET]``.
         
     | 
| 
       313 
322 
     | 
    
         | 
| 
       314 
323 
     | 
    
         
             
              usage: ``t archive [--start DATE] [--end DATE] [--grep REGEX] [SHEET]``
         
     | 
| 
         @@ -320,8 +329,8 @@ Commands 
     | 
|
| 
       320 
329 
     | 
    
         
             
              usage: ``t backend``
         
     | 
| 
       321 
330 
     | 
    
         | 
| 
       322 
331 
     | 
    
         
             
            **configure**
         
     | 
| 
       323 
     | 
    
         
            -
               
     | 
| 
       324 
     | 
    
         
            -
              one doesn't exist.  If one does exist  
     | 
| 
      
 332 
     | 
    
         
            +
              Create a config file at  ``~/.timetrap.yml`` or ``ENV['TIMETRAP_CONFIG_FILE']`` if
         
     | 
| 
      
 333 
     | 
    
         
            +
              one doesn't exist.  If one does exist, update it with new
         
     | 
| 
       325 
334 
     | 
    
         
             
              configuration options preserving any user overrides. Prints path to config
         
     | 
| 
       326 
335 
     | 
    
         
             
              file.  This file may contain ERB.
         
     | 
| 
       327 
336 
     | 
    
         | 
| 
         @@ -344,7 +353,7 @@ Commands 
     | 
|
| 
       344 
353 
     | 
    
         
             
              usage: ``t display [--ids] [--round] [--start DATE] [--end DATE] [--format FMT] [--grep REGEX] [SHEET | all | full]``
         
     | 
| 
       345 
354 
     | 
    
         | 
| 
       346 
355 
     | 
    
         
             
            **edit**
         
     | 
| 
       347 
     | 
    
         
            -
               
     | 
| 
      
 356 
     | 
    
         
            +
              Insert a note associated with the an entry in the timesheet, or edit the
         
     | 
| 
       348 
357 
     | 
    
         
             
              start or end times.  Defaults to the current entry, or previously running
         
     | 
| 
       349 
358 
     | 
    
         
             
              entry. An ``--id`` flag can be passed with the entry's id (see display.)
         
     | 
| 
       350 
359 
     | 
    
         | 
| 
         @@ -512,6 +521,7 @@ fpath=(/path/to/timetrap-1.x.y/gem/completions/zsh $fpath) 
     | 
|
| 
       512 
521 
     | 
    
         
             
            ```
         
     | 
| 
       513 
522 
     | 
    
         | 
| 
       514 
523 
     | 
    
         
             
            #### Notes editing
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
       515 
525 
     | 
    
         
             
            If you use the note_editor setting, then it is possible to use
         
     | 
| 
       516 
526 
     | 
    
         
             
            an editor for writing your notes. If you use a non terminal based
         
     | 
| 
       517 
527 
     | 
    
         
             
            editor (like atom, sublime etc.) then you will need to make timetrap
         
     | 
| 
         @@ -522,6 +532,29 @@ As of when this command was added, for atom you would use `atom --wait` 
     | 
|
| 
       522 
532 
     | 
    
         
             
            and for sublime `subl -w`. If you use a console based editor (vim, emacs,
         
     | 
| 
       523 
533 
     | 
    
         
             
            nano) then it should just work.
         
     | 
| 
       524 
534 
     | 
    
         | 
| 
      
 535 
     | 
    
         
            +
            Development
         
     | 
| 
      
 536 
     | 
    
         
            +
            -----------
         
     | 
| 
      
 537 
     | 
    
         
            +
             
     | 
| 
      
 538 
     | 
    
         
            +
            Get `bundler` in case you don't have it:
         
     | 
| 
      
 539 
     | 
    
         
            +
             
     | 
| 
      
 540 
     | 
    
         
            +
                gem install bundler
         
     | 
| 
      
 541 
     | 
    
         
            +
             
     | 
| 
      
 542 
     | 
    
         
            +
            Set a local path for the project's dependencies:
         
     | 
| 
      
 543 
     | 
    
         
            +
             
     | 
| 
      
 544 
     | 
    
         
            +
                bundle config set --local path 'vendor/bundle'
         
     | 
| 
      
 545 
     | 
    
         
            +
             
     | 
| 
      
 546 
     | 
    
         
            +
            Install timetrap's dependencies:
         
     | 
| 
      
 547 
     | 
    
         
            +
             
     | 
| 
      
 548 
     | 
    
         
            +
                bundle install
         
     | 
| 
      
 549 
     | 
    
         
            +
             
     | 
| 
      
 550 
     | 
    
         
            +
            Now you can run your local timetrap installation:
         
     | 
| 
      
 551 
     | 
    
         
            +
             
     | 
| 
      
 552 
     | 
    
         
            +
                bundle exec t
         
     | 
| 
      
 553 
     | 
    
         
            +
             
     | 
| 
      
 554 
     | 
    
         
            +
            Or run the test suite:
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
      
 556 
     | 
    
         
            +
                bundle exec rspec
         
     | 
| 
      
 557 
     | 
    
         
            +
             
     | 
| 
       525 
558 
     | 
    
         
             
            Special Thanks
         
     | 
| 
       526 
559 
     | 
    
         
             
            --------------
         
     | 
| 
       527 
560 
     | 
    
         | 
| 
         @@ -3,8 +3,9 @@ _timetrap () 
     | 
|
| 
       3 
3 
     | 
    
         
             
            {
         
     | 
| 
       4 
4 
     | 
    
         
             
              cur="${COMP_WORDS[COMP_CWORD]}"
         
     | 
| 
       5 
5 
     | 
    
         
             
              cmd="${COMP_WORDS[1]}"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       6 
7 
     | 
    
         
             
              if [[ ( $cmd = s* || $cmd = d* ) && "$COMP_CWORD" = 2 ]]; then
         
     | 
| 
       7 
     | 
    
         
            -
                COMPREPLY=($(compgen -W "$(echo "select distinct sheet from entries where sheet not like '\_%';" |  
     | 
| 
      
 8 
     | 
    
         
            +
                COMPREPLY=($(compgen -W "$(echo "select distinct sheet from entries where sheet not like '\_%';" | t b)" $cur))
         
     | 
| 
       8 
9 
     | 
    
         
             
                return
         
     | 
| 
       9 
10 
     | 
    
         
             
              elif [[ "$COMP_CWORD" = 1 ]]; then
         
     | 
| 
       10 
11 
     | 
    
         
             
                CMDS="archive backend configure display edit in kill list now out resume sheet week month"
         
     | 
    
        data/lib/timetrap/cli.rb
    CHANGED
    
    | 
         @@ -71,6 +71,7 @@ COMMAND is one of: 
     | 
|
| 
       71 
71 
     | 
    
         
             
                -z, --append              Append to the current note instead of replacing it
         
     | 
| 
       72 
72 
     | 
    
         
             
                                            the delimiter between appended notes is
         
     | 
| 
       73 
73 
     | 
    
         
             
                                            configurable (see configure)
         
     | 
| 
      
 74 
     | 
    
         
            +
                -c, --clear               Allow an empty note, can be used to clear existing notes
         
     | 
| 
       74 
75 
     | 
    
         
             
                -m, --move <sheet>        Move to another sheet
         
     | 
| 
       75 
76 
     | 
    
         | 
| 
       76 
77 
     | 
    
         
             
              * in - Start the timer for the current timesheet.
         
     | 
| 
         @@ -247,14 +248,18 @@ COMMAND is one of: 
     | 
|
| 
       247 
248 
     | 
    
         
             
                  end
         
     | 
| 
       248 
249 
     | 
    
         | 
| 
       249 
250 
     | 
    
         
             
                  if Config['note_editor']
         
     | 
| 
       250 
     | 
    
         
            -
                    if args['- 
     | 
| 
      
 251 
     | 
    
         
            +
                    if args['-c']
         
     | 
| 
      
 252 
     | 
    
         
            +
                      entry.update :note => ''
         
     | 
| 
      
 253 
     | 
    
         
            +
                    elsif args['-z']
         
     | 
| 
       251 
254 
     | 
    
         
             
                      note = [entry.note, get_note_from_external_editor].join(Config['append_notes_delimiter'])
         
     | 
| 
       252 
255 
     | 
    
         
             
                      entry.update :note => note
         
     | 
| 
       253 
256 
     | 
    
         
             
                    elsif editing_a_note?
         
     | 
| 
       254 
257 
     | 
    
         
             
                      entry.update :note => get_note_from_external_editor(entry.note)
         
     | 
| 
       255 
258 
     | 
    
         
             
                    end
         
     | 
| 
       256 
259 
     | 
    
         
             
                  else
         
     | 
| 
       257 
     | 
    
         
            -
                    if  
     | 
| 
      
 260 
     | 
    
         
            +
                    if args['-c']
         
     | 
| 
      
 261 
     | 
    
         
            +
                      entry.update :note => ''
         
     | 
| 
      
 262 
     | 
    
         
            +
                    elsif unused_args =~ /.+/
         
     | 
| 
       258 
263 
     | 
    
         
             
                      note = unused_args
         
     | 
| 
       259 
264 
     | 
    
         
             
                      if args['-z']
         
     | 
| 
       260 
265 
     | 
    
         
             
                        note = [entry.note, note].join(Config['append_notes_delimiter'])
         
     | 
| 
         @@ -324,7 +329,9 @@ COMMAND is one of: 
     | 
|
| 
       324 
329 
     | 
    
         
             
                def out
         
     | 
| 
       325 
330 
     | 
    
         
             
                  if Config['auto_checkout']
         
     | 
| 
       326 
331 
     | 
    
         
             
                    stopped = Timer.stop_all(args['-a']).each do |checked_out_of|
         
     | 
| 
       327 
     | 
    
         
            -
                       
     | 
| 
      
 332 
     | 
    
         
            +
                      note = Timer.last_checkout.note
         
     | 
| 
      
 333 
     | 
    
         
            +
                      entry = note_blank?(note) ? Timer.last_checkout.id : note.inspect
         
     | 
| 
      
 334 
     | 
    
         
            +
                      warn "Checked out of entry #{entry} in sheet #{checked_out_of.sheet.inspect}."
         
     | 
| 
       328 
335 
     | 
    
         
             
                    end
         
     | 
| 
       329 
336 
     | 
    
         
             
                    if stopped.empty?
         
     | 
| 
       330 
337 
     | 
    
         
             
                      warn "No running entries to stop."
         
     | 
| 
         @@ -332,7 +339,9 @@ COMMAND is one of: 
     | 
|
| 
       332 
339 
     | 
    
         
             
                  else
         
     | 
| 
       333 
340 
     | 
    
         
             
                    sheet = sheet_name_from_string(unused_args)
         
     | 
| 
       334 
341 
     | 
    
         
             
                    if Timer.stop sheet, args['-a']
         
     | 
| 
       335 
     | 
    
         
            -
                       
     | 
| 
      
 342 
     | 
    
         
            +
                      note = Timer.last_checkout.note
         
     | 
| 
      
 343 
     | 
    
         
            +
                      entry = note_blank?(note) ? Timer.last_checkout.id : note.inspect
         
     | 
| 
      
 344 
     | 
    
         
            +
                      warn "Checked out of entry #{entry} in sheet #{sheet.inspect}."
         
     | 
| 
       336 
345 
     | 
    
         
             
                    else
         
     | 
| 
       337 
346 
     | 
    
         
             
                      warn "No running entry on sheet #{sheet.inspect}."
         
     | 
| 
       338 
347 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -388,7 +397,13 @@ COMMAND is one of: 
     | 
|
| 
       388 
397 
     | 
    
         
             
                  end
         
     | 
| 
       389 
398 
     | 
    
         | 
| 
       390 
399 
     | 
    
         
             
                  Timer.current_sheet = sheet
         
     | 
| 
       391 
     | 
    
         
            -
                   
     | 
| 
      
 400 
     | 
    
         
            +
                  if Timer.last_sheet == sheet
         
     | 
| 
      
 401 
     | 
    
         
            +
                    warn "Already on sheet #{sheet.inspect}"
         
     | 
| 
      
 402 
     | 
    
         
            +
                  elsif Entry.sheets.include?(sheet)
         
     | 
| 
      
 403 
     | 
    
         
            +
                    warn "Switching to sheet #{sheet.inspect}"
         
     | 
| 
      
 404 
     | 
    
         
            +
                  else
         
     | 
| 
      
 405 
     | 
    
         
            +
                    warn "Switching to sheet #{sheet.inspect} (new sheet)"
         
     | 
| 
      
 406 
     | 
    
         
            +
                  end
         
     | 
| 
       392 
407 
     | 
    
         
             
                end
         
     | 
| 
       393 
408 
     | 
    
         | 
| 
       394 
409 
     | 
    
         
             
                def list
         
     | 
| 
         @@ -473,6 +488,10 @@ COMMAND is one of: 
     | 
|
| 
       473 
488 
     | 
    
         | 
| 
       474 
489 
     | 
    
         
             
                private
         
     | 
| 
       475 
490 
     | 
    
         | 
| 
      
 491 
     | 
    
         
            +
                def note_blank?(note)
         
     | 
| 
      
 492 
     | 
    
         
            +
                  note.inspect.to_s.gsub('"', '').strip.size.zero?
         
     | 
| 
      
 493 
     | 
    
         
            +
                end
         
     | 
| 
      
 494 
     | 
    
         
            +
             
     | 
| 
       476 
495 
     | 
    
         
             
                def unused_args
         
     | 
| 
       477 
496 
     | 
    
         
             
                  args.unused.join(' ')
         
     | 
| 
       478 
497 
     | 
    
         
             
                end
         
     | 
| 
         @@ -6,7 +6,7 @@ module Timetrap 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  def initialize entries
         
     | 
| 
       7 
7 
     | 
    
         
             
                    @output = entries.inject("start,end,note,sheet\n") do |out, e|
         
     | 
| 
       8 
8 
     | 
    
         
             
                      next(out) unless e.end
         
     | 
| 
       9 
     | 
    
         
            -
                      out << %|"#{e.start.strftime(time_format)}","#{e.end.strftime(time_format)}","#{e.note}","#{e.sheet}"\n|
         
     | 
| 
      
 9 
     | 
    
         
            +
                      out << %|"#{e.start.strftime(time_format)}","#{e.end.strftime(time_format)}","#{escape(e.note)}","#{e.sheet}"\n|
         
     | 
| 
       10 
10 
     | 
    
         
             
                    end
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
         @@ -14,6 +14,10 @@ module Timetrap 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  def time_format
         
     | 
| 
       15 
15 
     | 
    
         
             
                    "%Y-%m-%d %H:%M:%S"
         
     | 
| 
       16 
16 
     | 
    
         
             
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def escape(note)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    note.gsub %q{"}, %q{""}
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
       17 
21 
     | 
    
         
             
                end
         
     | 
| 
       18 
22 
     | 
    
         
             
              end
         
     | 
| 
       19 
23 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,7 +4,7 @@ rescue LoadError 
     | 
|
| 
       4 
4 
     | 
    
         
             
              raise <<-ERR
         
     | 
| 
       5 
5 
     | 
    
         
             
            The icalendar gem must be installed for ical output.
         
     | 
| 
       6 
6 
     | 
    
         
             
            To install it:
         
     | 
| 
       7 
     | 
    
         
            -
            $ [sudo] gem install icalendar 
     | 
| 
      
 7 
     | 
    
         
            +
            $ [sudo] gem install icalendar
         
     | 
| 
       8 
8 
     | 
    
         
             
              ERR
         
     | 
| 
       9 
9 
     | 
    
         
             
            end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -22,21 +22,13 @@ module Timetrap 
     | 
|
| 
       22 
22 
     | 
    
         
             
                  end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                  def initialize entries
         
     | 
| 
       25 
     | 
    
         
            -
                    entries.each do | 
     | 
| 
       26 
     | 
    
         
            -
                      next unless  
     | 
| 
       27 
     | 
    
         
            -
                      calendar.event do
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                         
     | 
| 
       30 
     | 
    
         
            -
                         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                            dtstart > other.dtstart ? 1 : 0
         
     | 
| 
       33 
     | 
    
         
            -
                          end
         
     | 
| 
       34 
     | 
    
         
            -
                        end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                        dtstart DateTime.parse(e.start.to_s)
         
     | 
| 
       37 
     | 
    
         
            -
                        dtend DateTime.parse(e.end.to_s)
         
     | 
| 
       38 
     | 
    
         
            -
                        summary e.note
         
     | 
| 
       39 
     | 
    
         
            -
                        description e.note
         
     | 
| 
      
 25 
     | 
    
         
            +
                    entries.each do |entry|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      next unless entry.end
         
     | 
| 
      
 27 
     | 
    
         
            +
                      calendar.event do |e|
         
     | 
| 
      
 28 
     | 
    
         
            +
                        e.dtstart = DateTime.parse(entry.start.to_s)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        e.dtend = DateTime.parse(entry.end.to_s)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        e.summary = entry.note
         
     | 
| 
      
 31 
     | 
    
         
            +
                        e.description = entry.note
         
     | 
| 
       40 
32 
     | 
    
         
             
                      end
         
     | 
| 
       41 
33 
     | 
    
         
             
                    end
         
     | 
| 
       42 
34 
     | 
    
         
             
                    calendar.publish
         
     | 
| 
         @@ -16,7 +16,12 @@ module Timetrap 
     | 
|
| 
       16 
16 
     | 
    
         
             
                  def initialize entries
         
     | 
| 
       17 
17 
     | 
    
         
             
                    @output = entries.map do |e|
         
     | 
| 
       18 
18 
     | 
    
         
             
                      next unless e.end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                      e.values.inject({}) do |h, (k,v)|
         
     | 
| 
      
 21 
     | 
    
         
            +
                        h[k] = v
         
     | 
| 
      
 22 
     | 
    
         
            +
                        h[k] = e.public_send(k) if %i[end start].include?(k)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        h
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
       20 
25 
     | 
    
         
             
                    end.compact.to_json
         
     | 
| 
       21 
26 
     | 
    
         
             
                  end
         
     | 
| 
       22 
27 
     | 
    
         
             
                end
         
     | 
    
        data/lib/timetrap/helpers.rb
    CHANGED
    
    | 
         @@ -40,16 +40,16 @@ module Timetrap 
     | 
|
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                def selected_entries
         
     | 
| 
       42 
42 
     | 
    
         
             
                  ee = if (sheet = sheet_name_from_string(unused_args)) == 'all'
         
     | 
| 
       43 
     | 
    
         
            -
                    Timetrap::Entry. 
     | 
| 
      
 43 
     | 
    
         
            +
                    Timetrap::Entry.where(Sequel.lit('sheet not like ? escape "!"', '!_%'))
         
     | 
| 
       44 
44 
     | 
    
         
             
                  elsif (sheet = sheet_name_from_string(unused_args)) == 'full'
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 45 
     | 
    
         
            +
                    Timetrap::Entry.where()
         
     | 
| 
       46 
46 
     | 
    
         
             
                  elsif sheet =~ /.+/
         
     | 
| 
       47 
     | 
    
         
            -
                    Timetrap::Entry. 
     | 
| 
      
 47 
     | 
    
         
            +
                    Timetrap::Entry.where(sheet: sheet)
         
     | 
| 
       48 
48 
     | 
    
         
             
                  else
         
     | 
| 
       49 
     | 
    
         
            -
                    Timetrap::Entry. 
     | 
| 
      
 49 
     | 
    
         
            +
                    Timetrap::Entry.where(sheet: Timer.current_sheet)
         
     | 
| 
       50 
50 
     | 
    
         
             
                  end
         
     | 
| 
       51 
     | 
    
         
            -
                  ee = ee.filter('start >= ?', Date.parse(Timer.process_time(args['-s']).to_s)) if args['-s']
         
     | 
| 
       52 
     | 
    
         
            -
                  ee = ee.filter('start <= ?', Date.parse(Timer.process_time(args['-e']).to_s) + 1) if args['-e']
         
     | 
| 
      
 51 
     | 
    
         
            +
                  ee = ee.filter(Sequel.lit('start >= ?', Date.parse(Timer.process_time(args['-s']).to_s))) if args['-s']
         
     | 
| 
      
 52 
     | 
    
         
            +
                  ee = ee.filter(Sequel.lit('start <= ?', Date.parse(Timer.process_time(args['-e']).to_s) + 1)) if args['-e']
         
     | 
| 
       53 
53 
     | 
    
         
             
                  ee = ee.order(:start)
         
     | 
| 
       54 
54 
     | 
    
         
             
                  if args['-g']
         
     | 
| 
       55 
55 
     | 
    
         
             
                    re = Regexp::new(args['-g'])
         
     | 
    
        data/lib/timetrap/models.rb
    CHANGED
    
    | 
         @@ -1,7 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Timetrap
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Entry < Sequel::Model
         
     | 
| 
       3 
     | 
    
         
            -
                plugin :schema
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
3 
     | 
    
         
             
                class << self
         
     | 
| 
       6 
4 
     | 
    
         
             
                # a class level instance variable that controls whether or not all entries
         
     | 
| 
       7 
5 
     | 
    
         
             
                # should respond to #start and #end with times rounded to 15 minute
         
     | 
| 
         @@ -68,27 +66,10 @@ module Timetrap 
     | 
|
| 
       68 
66 
     | 
    
         
             
                end
         
     | 
| 
       69 
67 
     | 
    
         | 
| 
       70 
68 
     | 
    
         
             
                private
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                set_schema do
         
     | 
| 
       73 
     | 
    
         
            -
                  primary_key :id
         
     | 
| 
       74 
     | 
    
         
            -
                  column :note, String
         
     | 
| 
       75 
     | 
    
         
            -
                  column :start, DateTime
         
     | 
| 
       76 
     | 
    
         
            -
                  column :end, DateTime
         
     | 
| 
       77 
     | 
    
         
            -
                  column :sheet, String
         
     | 
| 
       78 
     | 
    
         
            -
                end
         
     | 
| 
       79 
     | 
    
         
            -
                create_table unless table_exists?
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       80 
70 
     | 
    
         
             
              end
         
     | 
| 
       81 
71 
     | 
    
         | 
| 
       82 
72 
     | 
    
         
             
              class Meta < Sequel::Model(:meta)
         
     | 
| 
       83 
     | 
    
         
            -
                plugin :schema
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
                set_schema do
         
     | 
| 
       86 
     | 
    
         
            -
                  primary_key :id
         
     | 
| 
       87 
     | 
    
         
            -
                  column :key, String
         
     | 
| 
       88 
     | 
    
         
            -
                  column :value, String
         
     | 
| 
       89 
     | 
    
         
            -
                end
         
     | 
| 
       90 
     | 
    
         
            -
                create_table unless table_exists?
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
73 
     | 
    
         
             
                def value
         
     | 
| 
       93 
74 
     | 
    
         
             
                  self[:value].to_s
         
     | 
| 
       94 
75 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Defines the table schemas. Acts as migration.
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Npte the executing below the classes. These create the tables
         
     | 
| 
      
 4 
     | 
    
         
            +
            module Timetrap
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Schema
         
     | 
| 
      
 6 
     | 
    
         
            +
                def self.create_table!
         
     | 
| 
      
 7 
     | 
    
         
            +
                  DB.drop_table(self::TABLE)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  create_table
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def self.create_table
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self.new.create_table
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def self.try_create_table
         
     | 
| 
      
 16 
     | 
    
         
            +
                  create_table unless DB.table_exists?(self::TABLE)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              class EntrySchema < Schema
         
     | 
| 
      
 21 
     | 
    
         
            +
                TABLE = :entries
         
     | 
| 
      
 22 
     | 
    
         
            +
                def create_table
         
     | 
| 
      
 23 
     | 
    
         
            +
                  DB.create_table(TABLE) do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    primary_key :id
         
     | 
| 
      
 25 
     | 
    
         
            +
                    column :note, String
         
     | 
| 
      
 26 
     | 
    
         
            +
                    column :start, DateTime
         
     | 
| 
      
 27 
     | 
    
         
            +
                    column :end, DateTime
         
     | 
| 
      
 28 
     | 
    
         
            +
                    column :sheet, String
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              class MetaSchema < Schema
         
     | 
| 
      
 34 
     | 
    
         
            +
                TABLE = :meta
         
     | 
| 
      
 35 
     | 
    
         
            +
                def create_table
         
     | 
| 
      
 36 
     | 
    
         
            +
                  DB.create_table(TABLE) do
         
     | 
| 
      
 37 
     | 
    
         
            +
                    primary_key :id
         
     | 
| 
      
 38 
     | 
    
         
            +
                    column :key, String
         
     | 
| 
      
 39 
     | 
    
         
            +
                    column :value, String
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              ## Executes the schema, acting as a small migration
         
     | 
| 
      
 45 
     | 
    
         
            +
              EntrySchema.try_create_table
         
     | 
| 
      
 46 
     | 
    
         
            +
              MetaSchema.try_create_table
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/timetrap/version.rb
    CHANGED
    
    
    
        data/lib/timetrap.rb
    CHANGED
    
    | 
         @@ -18,8 +18,12 @@ module Timetrap 
     | 
|
| 
       18 
18 
     | 
    
         
             
              DB_NAME = defined?(TEST_MODE) ? nil : Timetrap::Config['database_file']
         
     | 
| 
       19 
19 
     | 
    
         
             
              # connect to database.  This will create one if it doesn't exist
         
     | 
| 
       20 
20 
     | 
    
         
             
              DB = Sequel.sqlite DB_NAME
         
     | 
| 
       21 
     | 
    
         
            -
               
     | 
| 
      
 21 
     | 
    
         
            +
              # only declare cli options when run as standalone
         
     | 
| 
      
 22 
     | 
    
         
            +
              if %w[dev_t t timetrap].include?(File.basename($PROGRAM_NAME)) || defined?(TEST_MODE)
         
     | 
| 
      
 23 
     | 
    
         
            +
                CLI.args = Getopt::Declare.new(<<-EOF)
         
     | 
| 
       22 
24 
     | 
    
         
             
                #{CLI::USAGE}
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
                EOF
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
       24 
27 
     | 
    
         
             
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
            require File.expand_path(File.join(File.dirname(__FILE__), 'timetrap', 'schema'))
         
     | 
| 
       25 
29 
     | 
    
         
             
            require File.expand_path(File.join(File.dirname(__FILE__), 'timetrap', 'models'))
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Constants
         
     | 
| 
      
 2 
     | 
    
         
            +
            TEST_MODE = true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # Vendors
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'fakefs/safe'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Load support files from the spec/support directory
         
     | 
| 
      
 8 
     | 
    
         
            +
            Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            # timetrap
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'timetrap'))
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # Config
         
     | 
| 
      
 14 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 15 
     | 
    
         
            +
              # Use color in STDOUT
         
     | 
| 
      
 16 
     | 
    
         
            +
              config.color = true
         
     | 
| 
      
 17 
     | 
    
         
            +
              # Use color not only in STDOUT but also in pagers and files
         
     | 
| 
      
 18 
     | 
    
         
            +
              config.tty = true
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              # Display 10 slowest tests after a test run
         
     | 
| 
      
 21 
     | 
    
         
            +
              config.profile_examples = false
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # Use the specified formatter
         
     | 
| 
      
 24 
     | 
    
         
            +
              # :documentation, :progress, :html, :json, CustomFormatterClass
         
     | 
| 
      
 25 
     | 
    
         
            +
              config.formatter = :progress
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              # Specify order for spec to be run in
         
     | 
| 
      
 28 
     | 
    
         
            +
              # TODO: make sure all specs pass when set to :rand
         
     | 
| 
      
 29 
     | 
    
         
            +
              # config.order = :rand
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # We are stubbing stderr and stdout, if you want to capture
         
     | 
| 
      
 32 
     | 
    
         
            +
              # any of your output in tests, simply add :write_stdout_stderr => true
         
     | 
| 
      
 33 
     | 
    
         
            +
              # as metadata to the end of your test
         
     | 
| 
      
 34 
     | 
    
         
            +
              config.after(:each, write_stdout_stderr: true) do
         
     | 
| 
      
 35 
     | 
    
         
            +
                $stderr.rewind
         
     | 
| 
      
 36 
     | 
    
         
            +
                $stdout.rewind
         
     | 
| 
      
 37 
     | 
    
         
            +
                File.write("stderr.txt", $stderr.read)
         
     | 
| 
      
 38 
     | 
    
         
            +
                File.write("stdout.txt", $stdout.read)
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     |