francois-tt 0.0.1

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.
Files changed (6) hide show
  1. data/LICENSE +20 -0
  2. data/README +24 -0
  3. data/Rakefile +24 -0
  4. data/TODO +1 -0
  5. data/lib/tt.rb +118 -0
  6. metadata +67 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 François Beausoleil
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,24 @@
1
+ TT - Time Tracker
2
+ ================
3
+
4
+ Track your time locally, offline.
5
+
6
+ Usage
7
+ =====
8
+
9
+ $ pi # punch in, stores current working directory, date, time (UTC)
10
+ $ po # punch out: stops current task
11
+ $ cd my-project
12
+ $ pi
13
+ $ # code furiously
14
+ $ cd ../my-other-project
15
+ $ pi talking about stuff # stops first instance, records new CWD, and comment
16
+ $ po did this and that # stops tracking time, appends comment to time entry
17
+ $ tt list # lists your time entries in a nice format
18
+ $ tt drop # drops your last time entry
19
+ $ tt clear # DESTROYS all time entries, no turning back, nor is there any confirmation
20
+
21
+ Data
22
+ ====
23
+
24
+ The time tracker database is stored as ~/.tt/entries.csv
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ load File.dirname(__FILE__) + "/clitt.gemspec"
4
+
5
+ Rake::GemPackageTask.new($spec) do |pkg|
6
+ pkg.gem_spec = $spec
7
+ end
8
+
9
+ task :install => [:package] do
10
+ sh %{sudo gem install --no-rdoc --no-ri pkg/#{GEM}-#{VERSION}}
11
+ end
12
+
13
+ begin
14
+ require "spec/rake/spectask"
15
+ rescue LoadError
16
+ raise "rspec ~> 1.1.3 required to spec this gem, but it is not available."
17
+ end
18
+
19
+ Spec::Rake::SpecTask.new do |t|
20
+ t.spec_opts = ["--format", "progress", "--color"]
21
+ t.warning = false
22
+ end
23
+
24
+ task :default => :spec
data/TODO ADDED
@@ -0,0 +1 @@
1
+ TODO:
data/lib/tt.rb ADDED
@@ -0,0 +1,118 @@
1
+ require "fastercsv"
2
+ require "pathname"
3
+ require "time"
4
+
5
+ module Tt
6
+ FORMAT = "%Y-%m-%dT%H:%MZ"
7
+ SCREEN_FORMAT = "%Y-%m-%d %H:%M"
8
+
9
+ def self.tt_dir
10
+ Pathname.new(ENV["HOME"]) + ".tt"
11
+ end
12
+
13
+ def self.tt_path
14
+ tt_dir + "entries.csv"
15
+ end
16
+
17
+ def self.punch_in(cwd, comment=nil)
18
+ tt_dir.mkdir unless tt_dir.directory?
19
+ FasterCSV.open(tt_path, "ab") do |io|
20
+ io << ["in", cwd, Time.now.utc.strftime(FORMAT), comment]
21
+ end
22
+ end
23
+
24
+ def self.punch_out(cwd, comment=nil)
25
+ tt_dir.mkdir unless tt_dir.directory?
26
+ FasterCSV.open(tt_path, "ab") do |io|
27
+ io << ["out", cwd, Time.now.utc.strftime(FORMAT), comment]
28
+ end
29
+ end
30
+
31
+ def self.report_line(dir, intime, outtime, comment)
32
+ ltime = Time.now
33
+ intime = intime + ltime.utc_offset if intime
34
+ outtime = outtime + ltime.utc_offset if outtime
35
+
36
+ if outtime then
37
+ duration_in_seconds = outtime - intime
38
+ duration_in_minutes = duration_in_seconds / 60
39
+ duration_as_human_string = "%02d:%02d" % [duration_in_minutes / 60, duration_in_minutes % 60]
40
+
41
+ print "%-40s %16s %16s %5s" % [dir, intime.strftime(SCREEN_FORMAT), outtime.strftime(SCREEN_FORMAT), duration_as_human_string]
42
+ print " - %s" % comment if comment && !comment.empty?
43
+ puts
44
+ else
45
+ print "%-40s %16s %16s %5s" % [dir, intime.strftime(SCREEN_FORMAT), "", ""]
46
+ print " - %s" % comment if comment && !comment.empty?
47
+ puts
48
+ end
49
+ end
50
+
51
+ def self.report
52
+ tt_dir.mkdir unless tt_dir.directory?
53
+ line, state, dir, intime, outtime, comment = 0, :out, nil, nil, nil, nil
54
+
55
+ FasterCSV.foreach(tt_path) do |row|
56
+ line += 1
57
+
58
+ case row[0]
59
+ when "in"
60
+ case state
61
+ when :out # punch in
62
+ dir = row[1]
63
+ intime = Time.parse(row[2])
64
+ outtime = nil
65
+ comment = row[3]
66
+ state = :in
67
+ when :in # switch task
68
+ outtime = Time.parse(row[2])
69
+ report_line(dir, intime, outtime, [comment, row[3]].compact.join("; "))
70
+
71
+ dir = row[1]
72
+ intime = Time.parse(row[2])
73
+ outtime = nil
74
+ comment = nil
75
+ else
76
+ raise ArgumentError, "Unknown processing state: #{state}, expected one of in/out"
77
+ end
78
+ when "out"
79
+ case state
80
+ when :in # punch out
81
+ outtime = Time.parse(row[2])
82
+ report_line(dir, intime, outtime, [comment, row[3]].compact.join("; "))
83
+
84
+ dir, intime, outtime, comment = nil
85
+ state = :out
86
+ when :out
87
+ $stderr.puts "WARNING: out when already out on line #{line}"
88
+ else
89
+ raise ArgumentError, "Unknown processing state: #{state}, expected one of in/out"
90
+ end
91
+ else
92
+ raise SyntaxError, "Error on line \##{line} of #{tt_path}: unknown reference in column 0: #{row[0]}"
93
+ end
94
+ end if tt_path.file?
95
+
96
+ case state
97
+ when :in
98
+ report_line(dir, intime, nil, comment)
99
+ end
100
+ end
101
+
102
+ def self.drop
103
+ FasterCSV.open(tt_path.to_s + ".new", "wb") do |io|
104
+ lastrow = nil
105
+ FasterCSV.foreach(tt_path, "rb") do |row|
106
+ io << lastrow if lastrow
107
+ lastrow = row
108
+ end
109
+ end
110
+
111
+ tt_path.unlink
112
+ File.rename(tt_path.to_s + ".new", tt_path)
113
+ end
114
+
115
+ def self.clear
116
+ tt_path.unlink
117
+ end
118
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: francois-tt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - "Fran\xC3\xA7ois Beausoleil"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-14 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fastercsv
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.3
23
+ version:
24
+ description: Track your time locally, offline, using this simple tool.
25
+ email: francois@teksol.info
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README
32
+ - LICENSE
33
+ - TODO
34
+ files:
35
+ - LICENSE
36
+ - README
37
+ - Rakefile
38
+ - TODO
39
+ - lib/tt.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/francois/tt
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.0.1
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Track your time locally, offline, using this simple tool.
66
+ test_files: []
67
+