samg-timetrap 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -8
- data/VERSION.yml +2 -2
- data/lib/timetrap/cli.rb +8 -13
- data/lib/timetrap/formatters/csv.rb +19 -0
- data/spec/timetrap_spec.rb +61 -22
- metadata +3 -2
data/README.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
Timetrap
|
2
2
|
========
|
3
3
|
|
4
|
-
Timetrap is a
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
Timetrap is a utility which provides an easy to use command line interface for
|
5
|
+
tracking what you spend your time on. It is a ruby port of Trevor Caira's
|
6
|
+
Timebook, a small python utility. It contains several enhancement over
|
7
|
+
Timebook notably the ability to parse natural language time strings. This
|
8
|
+
makes commands such as ``t in --at "30 minutes ago"`` possible. Timetrap is
|
9
|
+
also able to export entries to several formats (e.g. ical, csv) and is designed
|
10
|
+
to be easily extended to support additional export formats.
|
11
|
+
Timetrap maintains its state in a sqlite3 database.
|
9
12
|
|
10
13
|
To install:
|
11
14
|
|
@@ -45,7 +48,7 @@ timesheet ``foo`` was desired).
|
|
45
48
|
Usage
|
46
49
|
-----
|
47
50
|
|
48
|
-
The basic usage is as follows
|
51
|
+
The basic usage is as follows:
|
49
52
|
|
50
53
|
$ t switch writing
|
51
54
|
$ t in document timetrap --at "10 minutes ago"
|
@@ -88,7 +91,7 @@ last row, the total time tracked in the timesheet is shown.
|
|
88
91
|
Commands
|
89
92
|
--------
|
90
93
|
**archives**
|
91
|
-
Archives the selected entries (by moving them to a sheet called _
|
94
|
+
Archives the selected entries (by moving them to a sheet called ``_[SHEET]``)
|
92
95
|
usage: ``t archive [--start DATE] [--end DATE] [SHEET]``
|
93
96
|
|
94
97
|
**backend**
|
@@ -105,7 +108,7 @@ Commands
|
|
105
108
|
|
106
109
|
Display is designed to support a variety of export formats that can be
|
107
110
|
specified by passing the ``--format`` flag. This currently defaults to
|
108
|
-
text. iCal output
|
111
|
+
text. iCal and csv output are also supported.
|
109
112
|
|
110
113
|
usage: ``t display [--ids] [--start DATE] [--end DATE] [--format FMT] [SHEET | all]``
|
111
114
|
|
@@ -117,6 +120,7 @@ Commands
|
|
117
120
|
usage: ``t edit [--id ID] [--start TIME] [--end TIME] [NOTES]``
|
118
121
|
|
119
122
|
**format**
|
123
|
+
Deprecated
|
120
124
|
Alias for display
|
121
125
|
|
122
126
|
**in**
|
data/VERSION.yml
CHANGED
data/lib/timetrap/cli.rb
CHANGED
@@ -24,14 +24,14 @@ where COMMAND is one of:
|
|
24
24
|
-v, --ids Print database ids (for use with edit)
|
25
25
|
-s, --start <date:qs> Include entries that start on this date or later
|
26
26
|
-e, --end <date:qs> Include entries that start on this date or earlier
|
27
|
-
-f, --format <format> The output format. Currently supports ical and
|
27
|
+
-f, --format <format> The output format. Currently supports ical, csv, and
|
28
28
|
text (default).
|
29
29
|
* edit - alter an entry's note, start, or end time. Defaults to the active entry
|
30
30
|
usage: t edit [--id ID] [--start TIME] [--end TIME] [NOTES]
|
31
31
|
-i, --id <id:i> Alter entry with id <id> instead of the running entry
|
32
32
|
-s, --start <time:qs> Change the start time to <time>
|
33
33
|
-e, --end <time:qs> Change the end time to <time>
|
34
|
-
* format - alias for display
|
34
|
+
* format - deprecated: alias for display
|
35
35
|
* in - start the timer for the current timesheet
|
36
36
|
usage: t in [--at TIME] [NOTES]
|
37
37
|
-a, --at <time:qs> Use this time instead of now
|
@@ -77,7 +77,10 @@ where COMMAND is one of:
|
|
77
77
|
case (valid = commands.select{|name| name =~ %r|^#{command}|}).size
|
78
78
|
when 0 then say "Invalid command: #{command}"
|
79
79
|
when 1 then send valid[0]
|
80
|
-
else
|
80
|
+
else
|
81
|
+
say "Ambiguous command: #{command}" if command
|
82
|
+
say(USAGE)
|
83
|
+
end
|
81
84
|
end
|
82
85
|
|
83
86
|
def archive
|
@@ -152,17 +155,8 @@ where COMMAND is one of:
|
|
152
155
|
end
|
153
156
|
say Timetrap.format(fmt_klass, selected_entries.order(:start).all)
|
154
157
|
end
|
158
|
+
alias_method :format, :display
|
155
159
|
|
156
|
-
# TODO: Consolidate display and format
|
157
|
-
def format
|
158
|
-
begin
|
159
|
-
fmt_klass = Timetrap::Formatters.const_get("#{args['-f'].classify}")
|
160
|
-
rescue
|
161
|
-
say "Invalid format specified `#{args['-f']}'"
|
162
|
-
return
|
163
|
-
end
|
164
|
-
say Timetrap.format(fmt_klass, selected_entries.order(:start).all)
|
165
|
-
end
|
166
160
|
|
167
161
|
def switch
|
168
162
|
sheet = unused_args
|
@@ -182,6 +176,7 @@ where COMMAND is one of:
|
|
182
176
|
m
|
183
177
|
end
|
184
178
|
end
|
179
|
+
if sheets.empty? then say "No sheets found"; return end
|
185
180
|
width = sheets.sort_by{|h|h[:name].length }.last[:name].length + 4
|
186
181
|
say " %-#{width}s%-12s%-12s%s" % ["Timesheet", "Running", "Today", "Total Time"]
|
187
182
|
sheets.each do |sheet|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Timetrap
|
2
|
+
module Formatters
|
3
|
+
class Csv
|
4
|
+
attr_reader :output
|
5
|
+
|
6
|
+
def initialize entries
|
7
|
+
@output = entries.inject("start,end,note\n") do |out, e|
|
8
|
+
next(out) unless e.end
|
9
|
+
out << %|"#{e.start.strftime(time_format)}","#{e.end.strftime(time_format)}","#{e.note}"\n|
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def time_format
|
15
|
+
"%Y-%m-%d %H:%M:%S"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/spec/timetrap_spec.rb
CHANGED
@@ -188,12 +188,42 @@ Grand Total 10:00:00
|
|
188
188
|
end
|
189
189
|
|
190
190
|
describe "format" do
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
191
|
+
before do
|
192
|
+
create_entry(:start => '2008-10-03 12:00:00', :end => '2008-10-03 14:00:00')
|
193
|
+
create_entry(:start => '2008-10-05 12:00:00', :end => '2008-10-05 14:00:00')
|
194
|
+
end
|
195
|
+
describe 'csv' do
|
196
|
+
|
197
|
+
it "should not export running items" do
|
198
|
+
invoke 'in'
|
199
|
+
invoke 'format --format csv'
|
200
|
+
$stdout.string.should == <<-EOF
|
201
|
+
start,end,note
|
202
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
203
|
+
"2008-10-05 12:00:00","2008-10-05 14:00:00","note"
|
204
|
+
EOF
|
195
205
|
end
|
196
206
|
|
207
|
+
it "should filter events by the passed dates" do
|
208
|
+
invoke 'format --format csv --start 2008-10-03 --end 2008-10-03'
|
209
|
+
$stdout.string.should == <<-EOF
|
210
|
+
start,end,note
|
211
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
212
|
+
EOF
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should not filter events by date when none are passed" do
|
216
|
+
invoke 'format --format csv'
|
217
|
+
$stdout.string.should == <<-EOF
|
218
|
+
start,end,note
|
219
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
220
|
+
"2008-10-05 12:00:00","2008-10-05 14:00:00","note"
|
221
|
+
EOF
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe 'ical' do
|
226
|
+
|
197
227
|
it "should not export running items" do
|
198
228
|
invoke 'in'
|
199
229
|
invoke 'format --format ical'
|
@@ -294,27 +324,36 @@ END:VCALENDAR
|
|
294
324
|
end
|
295
325
|
|
296
326
|
describe "list" do
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
327
|
+
describe "with no sheets defined" do
|
328
|
+
it "should say that there are no sheets" do
|
329
|
+
invoke 'list'
|
330
|
+
$stdout.string.chomp.should == 'No sheets found'
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
describe "with sheets defined" do
|
335
|
+
before do
|
336
|
+
Time.stub!(:now).and_return Time.parse("Oct 5 18:00:00 -0700 2008")
|
337
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-03 12:00:00',
|
338
|
+
:end => '2008-10-03 14:00:00')
|
339
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-03 12:00:00',
|
340
|
+
:end => '2008-10-03 14:00:00')
|
341
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-05 12:00:00',
|
342
|
+
:end => '2008-10-05 14:00:00')
|
343
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-05 14:00:00',
|
344
|
+
:end => nil)
|
345
|
+
create_entry( :sheet => 'Sheet 1', :start => '2008-10-03 16:00:00',
|
346
|
+
:end => '2008-10-03 18:00:00')
|
347
|
+
Timetrap.current_sheet = 'A Longly Named Sheet 2'
|
348
|
+
end
|
349
|
+
it "should list available timesheets" do
|
350
|
+
invoke 'list'
|
351
|
+
$stdout.string.should == <<-OUTPUT
|
314
352
|
Timesheet Running Today Total Time
|
315
353
|
*A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
316
354
|
Sheet 1 0:00:00 0:00:00 2:00:00
|
317
|
-
|
355
|
+
OUTPUT
|
356
|
+
end
|
318
357
|
end
|
319
358
|
end
|
320
359
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: samg-timetrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Goldstein
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-16 00:00:00 -07:00
|
13
13
|
default_executable: t
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- bin/t
|
91
91
|
- lib/timetrap.rb
|
92
92
|
- lib/timetrap/cli.rb
|
93
|
+
- lib/timetrap/formatters/csv.rb
|
93
94
|
- lib/timetrap/formatters/ical.rb
|
94
95
|
- lib/timetrap/formatters/text.rb
|
95
96
|
- lib/timetrap/helpers.rb
|