samg-timetrap 1.0.3 → 1.1.0
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.
- 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
|