timetrap 1.8.13 → 1.8.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4d18f6060d9238cea925da011e99bc4c41afb503
4
- data.tar.gz: f683279029600c23ae088dcd3160dfd9ae1a5e12
3
+ metadata.gz: e382d25aad4d86af2c0adbafca7ac08214e12bc9
4
+ data.tar.gz: 4ef80db091acde2505f029a7028bdfc76747e7b2
5
5
  SHA512:
6
- metadata.gz: a234bafa3c03b01b3b81942ef5e3e7c6216b835dcc51a62811d47da81a595d301ac376f7e6b0cb4cf1a4a77deb52447162e8be9f03bda4eb1741c5f346df1b1f
7
- data.tar.gz: 550652a4832b0050803c8187b62f9eb42880e7fdffe97d0eefa87a63fb964b3dfeb1fd2f97bdd9cd5f71f7ccb31f076c5ff6ec90d4531f0069f7e0cbe836116c
6
+ metadata.gz: 7cfdf04d7086a4a8ba73bb1c6b51348e01d141a2461301b9bb85f8293df6800998f7b9c8fc3b8251ee936780cc5d31155efafc0301f55f2430d00e04b9571f49
7
+ data.tar.gz: 0a5220b5e22404849e583e7dd3d63a359b03cd6011e90e29bf67cf45ac982f7c5d45d38db87e60305361461c4055ad62ffd91be26f47bbbe2cf905ab0ea1dd4e
data/CONTRIBUTORS CHANGED
@@ -9,3 +9,5 @@
9
9
  * Steven Ghyselbrecht
10
10
  * Matthew M. Keeler
11
11
  * Toby Foster
12
+ * Michael Moen
13
+ * Miles Matthias
data/README.md CHANGED
@@ -237,6 +237,53 @@ Timetrap Formatters Repository
237
237
  A community focused repository of custom formatters is available at
238
238
  https://github.com/samg/timetrap_formatters.
239
239
 
240
+ ## AutoSheets
241
+
242
+ Timetrap has a feature called auto sheets that allows you to automatically
243
+ select which timesheet to check into.
244
+
245
+ Timetrap ships with a couple auto sheets. The default auto sheet is called
246
+ `dotfiles` and will read the sheetname to check into from a `.timetrap-sheet`
247
+ file in the current directory.
248
+
249
+ [Here are all the included auto sheets](lib/timetrap/auto_sheets)
250
+
251
+ You can specify which auto sheet logic you want to use in `~/.timetrap.yml` by
252
+ changing the `auto_sheet` value.
253
+
254
+ #### Custom AutoSheets
255
+
256
+ It's also easy to write your own auto sheet logic that matches your personal
257
+ workflow. You're encouraged to submit these back to timetrap for inclusion in
258
+ a future version.
259
+
260
+ To create a custom auto sheet module you create a ruby class and implement one
261
+ method on it `#sheet`.
262
+
263
+ All timetrap auto sheets live under the namespace `Timetrap::AutoSheets`
264
+
265
+ To ensure that timetrap can find your auto sheet put it in
266
+ `~/.timetrap/auto_sheets/`. The filename should be the same as the
267
+ string you will set in the configuration (for example
268
+ `~/.timetrap/auto_sheets/dotfiles.rb`. If you want to put your auto sheet in a
269
+ different place you can run `t configure` and edit the
270
+ `auto sheet_search_paths` option.
271
+
272
+ As an example here's the dotfiles auto sheet
273
+
274
+ ```ruby
275
+ module Timetrap
276
+ module AutoSheets
277
+ class Dotfiles
278
+ def sheet
279
+ dotfile = File.join(Dir.pwd, '.timetrap-sheet')
280
+ File.read(dotfile).chomp if File.exist?(dotfile)
281
+ end
282
+ end
283
+ end
284
+ end
285
+ ```
286
+
240
287
  Commands
241
288
  --------
242
289
  **archive**
@@ -326,6 +373,17 @@ Commands
326
373
 
327
374
  usage: ``t sheet [TIMESHEET]``
328
375
 
376
+ **today**
377
+ Shortcut for display with start date as the current day
378
+
379
+ usage: ``t today [--ids] [--format FMT] [SHEET | all]``
380
+
381
+ **yesterday**
382
+ Shortcut for display with start and end dates as the day before the current
383
+ day
384
+
385
+ usage: ``t yesterday [--ids] [--format FMT] [SHEET | all]``
386
+
329
387
  **week**
330
388
  Shortcut for display with start date set to monday of this week
331
389
 
@@ -382,6 +440,8 @@ See ``t configure`` for details. Currently supported options are:
382
440
 
383
441
  **require_note**: Prompt for a note if one isn't provided when checking in
384
442
 
443
+ **auto_sheet**: Which auto sheet module to use.
444
+
385
445
  Autocomplete
386
446
  ------------
387
447
 
@@ -409,10 +469,16 @@ source /path/to/timetrap-1.x.y/gem/completions/bash/timetrap-autocomplete.bash
409
469
 
410
470
  ### zsh
411
471
 
412
- You need to add timetrap's zsh completions directory to your `$fpath`,
413
- so add the following to your `.zshrc`:
472
+ If it isn't already, add the following to your `.zshrc`:
414
473
 
415
- ```zsh
474
+ ```bash
475
+ autoload -U compinit
476
+ compinit
477
+ ```
478
+
479
+ Then add this to source the completions:
480
+
481
+ ```bash
416
482
  fpath=(/path/to/timetrap-1.x.y/gem/completions/zsh $fpath)
417
483
  ```
418
484
 
data/lib/timetrap.rb CHANGED
@@ -12,6 +12,7 @@ require File.join(File.dirname(__FILE__), 'timetrap', 'helpers')
12
12
  require File.join(File.dirname(__FILE__), 'timetrap', 'cli')
13
13
  require File.join(File.dirname(__FILE__), 'timetrap', 'timer')
14
14
  require File.join(File.dirname(__FILE__), 'timetrap', 'formatters')
15
+ require File.join(File.dirname(__FILE__), 'timetrap', 'auto_sheets')
15
16
  module Timetrap
16
17
  DB_NAME = defined?(TEST_MODE) ? nil : Timetrap::Config['database_file']
17
18
  # connect to database. This will create one if it doesn't exist
@@ -0,0 +1,5 @@
1
+ # Namespace for auto_sheet classes
2
+ module Timetrap
3
+ module AutoSheets
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ module Timetrap
2
+ module AutoSheets
3
+ class Dotfiles
4
+ def sheet
5
+ dotfile = File.join(Dir.pwd, '.timetrap-sheet')
6
+ File.read(dotfile).chomp if File.exist?(dotfile)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ module Timetrap
2
+ module AutoSheets
3
+ ### auto_sheet_paths
4
+ #
5
+ # Specify which sheet to automatically use in which directories in with the
6
+ # following format in timetrap.yml:
7
+ #
8
+ # auto_sheet_paths:
9
+ # Sheet name: /path/to/directory
10
+ # More specific sheet: /path/to/directory/that/is/nested
11
+ # Other sheet:
12
+ # - /path/to/first/directory
13
+ # - /path/to/second/directory
14
+ #
15
+ # **Note** Timetrap will always use the sheet specified in the config file
16
+ # if you are in that directory (or in its tree). To use a different sheet,
17
+ # you must be in a different directory.
18
+ #
19
+ class YamlCwd
20
+ def sheet
21
+ auto_sheet = nil
22
+ cwd = "#{Dir.getwd}/"
23
+ most_specific = 0
24
+ Array(Timetrap::Config['auto_sheet_paths']).each do |sheet, dirs|
25
+ Array(dirs).each do |dir|
26
+ if cwd.start_with?(dir) && dir.length > most_specific
27
+ most_specific = dir.length
28
+ auto_sheet = sheet
29
+ end
30
+ end
31
+ end
32
+ auto_sheet
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/timetrap/cli.rb CHANGED
@@ -97,6 +97,9 @@ COMMAND is one of:
97
97
  * today - Shortcut for display with start date as the current day
98
98
  usage: t today [--ids] [--format FMT] [SHEET | all]
99
99
 
100
+ * yesterday - Shortcut for display with start and end dates as the day before the current day
101
+ usage: t yesterday [--ids] [--format FMT] [SHEET | all]
102
+
100
103
  * week - Shortcut for display with start date set to monday of this week.
101
104
  usage: t week [--ids] [--end DATE] [--format FMT] [SHEET | all]
102
105
 
@@ -395,6 +398,13 @@ COMMAND is one of:
395
398
  display
396
399
  end
397
400
 
401
+ def yesterday
402
+ yesterday = (Date.today - 1).to_s
403
+ args['-s'] = yesterday
404
+ args['-e'] = yesterday
405
+ display
406
+ end
407
+
398
408
  def week
399
409
  args['-s'] = Date.today.wday == 1 ? Date.today.to_s : Date.parse(Chronic.parse(%q(last monday)).to_s).to_s
400
410
  display
@@ -430,6 +440,7 @@ COMMAND is one of:
430
440
  $stdin.gets =~ /\Aye?s?\Z/i
431
441
  end
432
442
 
443
+ extend Helpers::AutoLoad
433
444
  def format_entries(entries)
434
445
  load_formatter(args['-f'] || Config['default_formatter']).new(Array(entries)).output
435
446
  end
@@ -23,6 +23,12 @@ module Timetrap
23
23
  ],
24
24
  # formatter to use when display is invoked without a --format option
25
25
  'default_formatter' => 'text',
26
+ # the auto_sheet to use
27
+ 'auto_sheet' => 'dotfiles',
28
+ # an array of directories to search for user defined auto_sheet classes
29
+ 'auto_sheet_search_paths' => [
30
+ "#{ENV['HOME']}/.timetrap/auto_sheets"
31
+ ],
26
32
  # the default command to when you run `t`. default to printing usage.
27
33
  'default_command' => nil,
28
34
  # only allow one running entry at a time.
@@ -1,30 +1,40 @@
1
1
  module Timetrap
2
2
  module Helpers
3
+ module AutoLoad
4
+ def load_formatter(formatter)
5
+ auto_load(formatter, 'formatter')
6
+ end
7
+
8
+ def load_auto_sheet(auto_sheet)
9
+ auto_load(auto_sheet, 'auto_sheet')
10
+ end
3
11
 
4
- def load_formatter(formatter)
5
- err_msg = "Can't load #{formatter.inspect} formatter."
6
- begin
7
- paths = (
8
- Array(Config['formatter_search_paths']) +
9
- [ File.join( File.dirname(__FILE__), 'formatters') ]
10
- )
11
- if paths.detect do |path|
12
- begin
13
- fp = File.join(path, formatter)
14
- require File.join(path, formatter)
15
- true
16
- rescue LoadError
17
- nil
18
- end
19
- end
20
- else
21
- raise LoadError, "Couldn't find #{formatter}.rb in #{paths.inspect}"
22
- end
23
- Timetrap::Formatters.const_get(formatter.camelize)
24
- rescue LoadError, NameError => e
25
- err = e.class.new("#{err_msg} (#{e.message})")
26
- err.set_backtrace(e.backtrace)
27
- raise err
12
+ def auto_load(name, type)
13
+ err_msg = "Can't load #{name.inspect} #{type}."
14
+ begin
15
+ paths = (
16
+ Array(Config["#{type}_search_paths"]) +
17
+ [ File.join( File.dirname(__FILE__), type.pluralize) ]
18
+ )
19
+ if paths.detect do |path|
20
+ begin
21
+ fp = File.join(path, name)
22
+ require File.join(path, name)
23
+ true
24
+ rescue LoadError
25
+ nil
26
+ end
27
+ end
28
+ else
29
+ raise LoadError, "Couldn't find #{name}.rb in #{paths.inspect}"
30
+ end
31
+ namespace = Timetrap.const_get(type.pluralize.camelize)
32
+ namespace.const_get(name.camelize)
33
+ rescue LoadError, NameError => e
34
+ err = e.class.new("#{err_msg} (#{e.message})")
35
+ err.set_backtrace(e.backtrace)
36
+ raise err
37
+ end
28
38
  end
29
39
  end
30
40
 
@@ -1,5 +1,7 @@
1
1
  module Timetrap
2
2
  module Timer
3
+ extend Helpers::AutoLoad
4
+
3
5
  class AlreadyRunning < StandardError
4
6
  def message
5
7
  "Timetrap is already running"
@@ -63,7 +65,16 @@ module Timetrap
63
65
  unless Meta.find(:key => 'current_sheet')
64
66
  Meta.create(:key => 'current_sheet', :value => 'default')
65
67
  end
66
- Meta.find(:key => 'current_sheet').value
68
+
69
+ if the_auto_sheet = auto_sheet
70
+ unless @auto_sheet_warned
71
+ warn "Sheet #{the_auto_sheet.inspect} selected by Timetrap::AutoSheets::#{::Timetrap::Config['auto_sheet'].capitalize}"
72
+ @auto_sheet_warned = true
73
+ end
74
+ the_auto_sheet
75
+ else
76
+ Meta.find(:key => 'current_sheet').value
77
+ end
67
78
  end
68
79
 
69
80
  def last_sheet
@@ -122,5 +133,10 @@ module Timetrap
122
133
  Entry.create(:sheet => Timer.current_sheet, :note => note, :start => time).save
123
134
  end
124
135
 
136
+ def auto_sheet
137
+ if Timetrap::Config['auto_sheet']
138
+ load_auto_sheet(Config['auto_sheet']).new.sheet
139
+ end
140
+ end
125
141
  end
126
142
  end
@@ -1,3 +1,3 @@
1
1
  module Timetrap
2
- VERSION = '1.8.13'
2
+ VERSION = '1.8.14'
3
3
  end
@@ -0,0 +1 @@
1
+ dotfile-sheet
@@ -219,6 +219,66 @@ describe Timetrap do
219
219
  end
220
220
  end
221
221
 
222
+ describe 'auto_sheet' do
223
+ describe "using dotfiles auto_sheet" do
224
+ describe 'with a .timetrap-sheet in cwd' do
225
+ it 'should use sheet defined in dorfile' do
226
+ Dir.chdir('spec/dotfile') do
227
+ with_stubbed_config('auto_sheet' => 'dotfiles')
228
+ Timetrap::Timer.current_sheet.should == 'dotfile-sheet'
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+ describe "using YamlCwd autosheet" do
235
+ describe 'with cwd in auto_sheet_paths' do
236
+ it 'should use sheet defined in config' do
237
+ with_stubbed_config(
238
+ 'auto_sheet_paths' => {
239
+ 'a sheet' => ['/not/cwd/', Dir.getwd]
240
+ }, 'auto_sheet' => 'yaml_cwd')
241
+ Timetrap::Timer.current_sheet.should == 'a sheet'
242
+ end
243
+ end
244
+
245
+ describe 'with ancestor of cwd in auto_sheet_paths' do
246
+ it 'should use sheet defined in config' do
247
+ with_stubbed_config(
248
+ 'auto_sheet_paths' => {'a sheet' => '/'},
249
+ 'auto_sheet' => 'yaml_cwd'
250
+ )
251
+ Timetrap::Timer.current_sheet.should == 'a sheet'
252
+ end
253
+ end
254
+
255
+ describe 'with cwd not in auto_sheet_paths' do
256
+ it 'should not use sheet defined in config' do
257
+ with_stubbed_config(
258
+ 'auto_sheet_paths' => {
259
+ 'a sheet' => '/not/the/current/working/directory/'
260
+ },'auto_sheet' => 'yaml_cwd')
261
+ Timetrap::Timer.current_sheet.should == 'default'
262
+ end
263
+ end
264
+
265
+ describe 'with cwd and ancestor in auto_sheet_paths' do
266
+ it 'should use the most specific config' do
267
+ with_stubbed_config(
268
+ 'auto_sheet_paths' => {
269
+ 'general sheet' => '/', 'more specific sheet' => Dir.getwd
270
+ }, 'auto_sheet' => 'yaml_cwd')
271
+ Timetrap::Timer.current_sheet.should == 'more specific sheet'
272
+ with_stubbed_config(
273
+ 'auto_sheet_paths' => {
274
+ 'more specific sheet' => Dir.getwd, 'general sheet' => '/'
275
+ }, 'auto_sheet' => 'yaml_cwd')
276
+ Timetrap::Timer.current_sheet.should == 'more specific sheet'
277
+ end
278
+ end
279
+ end
280
+ end
281
+
222
282
  describe "backend" do
223
283
  it "should open an sqlite console to the db" do
224
284
  Timetrap::CLI.should_receive(:exec).with("sqlite3 #{Timetrap::DB_NAME}")
@@ -406,7 +466,7 @@ Grand Total 10:00:00
406
466
  )
407
467
  invoke 'd SpecSheet'
408
468
  # check it doesn't error and produces valid looking output
409
- $stdout.string.should include('Timesheet: SpecSheet')
469
+ $stdout.string.should include('Timesheet: SpecSheet')
410
470
  end
411
471
  end
412
472
 
@@ -682,6 +742,20 @@ END:VCALENDAR
682
742
  end
683
743
  end
684
744
 
745
+ describe "yesterday" do
746
+ it "should only show entries for yesterday" do
747
+ yesterday = Time.now - (24 * 60 * 60)
748
+ create_entry(
749
+ :start => yesterday,
750
+ :end => yesterday
751
+ )
752
+ create_entry
753
+ invoke 'yesterday'
754
+ $stdout.string.should include yesterday.strftime('%a %b %d, %Y')
755
+ $stdout.string.should_not include Time.now.strftime('%a %b %d, %Y')
756
+ end
757
+ end
758
+
685
759
  describe "week" do
686
760
  it "should only show entries from this week" do
687
761
  create_entry(
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timetrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.13
4
+ version: 1.8.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Goldstein
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-12 00:00:00.000000000 Z
11
+ date: 2014-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -162,6 +162,9 @@ files:
162
162
  - lib/Getopt/Declare.rb
163
163
  - lib/Getopt/DelimScanner.rb
164
164
  - lib/timetrap.rb
165
+ - lib/timetrap/auto_sheets.rb
166
+ - lib/timetrap/auto_sheets/dotfiles.rb
167
+ - lib/timetrap/auto_sheets/yaml_cwd.rb
165
168
  - lib/timetrap/cli.rb
166
169
  - lib/timetrap/config.rb
167
170
  - lib/timetrap/formatters.rb
@@ -175,6 +178,7 @@ files:
175
178
  - lib/timetrap/models.rb
176
179
  - lib/timetrap/timer.rb
177
180
  - lib/timetrap/version.rb
181
+ - spec/dotfile/.timetrap-sheet
178
182
  - spec/timetrap_spec.rb
179
183
  - timetrap.gemspec
180
184
  homepage: https://github.com/samg/timetrap
@@ -202,4 +206,5 @@ signing_key:
202
206
  specification_version: 4
203
207
  summary: Command line time tracker
204
208
  test_files:
209
+ - spec/dotfile/.timetrap-sheet
205
210
  - spec/timetrap_spec.rb