worked 0.1.0 → 0.2.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.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/Manifest.txt +6 -0
- data/README.rdoc +6 -2
- data/Rakefile +1 -0
- data/bin/worked +2 -2
- data/lib/worked.rb +1 -1
- data/lib/worked/cli.rb +51 -20
- data/lib/worked/graph.rb +37 -0
- data/lib/worked/inputgrammar.rb +741 -0
- data/lib/worked/inputparser.rb +29 -17
- data/lib/worked/reader.rb +74 -0
- data/tasks/parser_generate.rake +4 -0
- data/test/test_grammar.rb +23 -29
- data/test/test_reader.rb +101 -0
- data/test/test_worked_cli.rb +22 -3
- data/website/index.html +120 -0
- metadata +35 -7
- metadata.gz.sig +0 -0
data/lib/worked/inputparser.rb
CHANGED
@@ -4,24 +4,14 @@ require 'worked/inputgrammar'
|
|
4
4
|
|
5
5
|
class Treetop::Runtime::SyntaxNode
|
6
6
|
|
7
|
+
attr_reader :from, :to, :total
|
8
|
+
|
7
9
|
# Remove all clutter ('hour', ':', etc) from the
|
8
10
|
# time and turn into an integer
|
9
11
|
def to_i
|
10
12
|
text_value.gsub(/\D/, '').to_i
|
11
13
|
end
|
12
14
|
|
13
|
-
def from
|
14
|
-
time_to_seconds_from_day(DateTime.now - total)
|
15
|
-
end
|
16
|
-
|
17
|
-
def to
|
18
|
-
time_to_seconds_from_day(DateTime.now)
|
19
|
-
end
|
20
|
-
|
21
|
-
def time_to_seconds_from_day t
|
22
|
-
t.hour.hours + t.min.minutes
|
23
|
-
end
|
24
|
-
|
25
15
|
# Default value so we don't have to care whether
|
26
16
|
# there really is a minute component
|
27
17
|
def minutes
|
@@ -29,22 +19,44 @@ class Treetop::Runtime::SyntaxNode
|
|
29
19
|
end
|
30
20
|
end
|
31
21
|
|
22
|
+
class InputGrammarParser
|
23
|
+
def initialize
|
24
|
+
@root = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class CannotParse < Exception ; end
|
29
|
+
|
32
30
|
class InputParser
|
33
31
|
|
34
|
-
def self.parse
|
32
|
+
def self.parse(source, now = DateTime.now)
|
35
33
|
|
36
|
-
|
34
|
+
from, to, total, activity = parse_input source
|
37
35
|
|
38
|
-
from
|
36
|
+
from ||= time_in_seconds_from_day(now - total)
|
37
|
+
to ||= time_in_seconds_from_day(now)
|
39
38
|
|
40
39
|
if from > to
|
41
40
|
from -= 24.hours
|
42
41
|
end
|
43
42
|
|
44
|
-
now = DateTime.now
|
45
43
|
midnight = DateTime.new(now.year, now.month, now.day)
|
46
44
|
|
47
|
-
[midnight + from.seconds, midnight + to.seconds,
|
45
|
+
[midnight + from.seconds, midnight + to.seconds, activity]
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def self.parse_input source
|
51
|
+
root = InputGrammarParser.new.parse(source)
|
52
|
+
|
53
|
+
raise CannotParse unless root
|
54
|
+
|
55
|
+
[root.time.from, root.time.to, root.time.total, root.activity.text_value]
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.time_in_seconds_from_day t
|
59
|
+
t.hour.hours + t.min.minutes
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'worked/inputparser'
|
2
|
+
|
3
|
+
class Date
|
4
|
+
def week_of_year
|
5
|
+
strftime("%U").to_i + 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Worked
|
10
|
+
|
11
|
+
class Entry < Struct.new(:hours, :date)
|
12
|
+
def week_of_year
|
13
|
+
date.week_of_year
|
14
|
+
end
|
15
|
+
|
16
|
+
def <=> other
|
17
|
+
self.date <=> other.date
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Reader
|
22
|
+
|
23
|
+
def self.by_week data
|
24
|
+
sort create_entries merge_by_week read_all_entries data
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.read data
|
28
|
+
sort create_entries merge_by_day read_all_entries data
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.extract_times line
|
34
|
+
from, to, rest = line.split
|
35
|
+
|
36
|
+
[DateTime.parse(from), DateTime.parse(to)]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.read_all_entries data
|
40
|
+
data.to_a.collect do |line|
|
41
|
+
from, to = extract_times line
|
42
|
+
Entry.new((to - from) * 24, from.to_date)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.merge_by_week entries
|
47
|
+
merge_entries(entries) {|e| e.week_of_year}
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.merge_by_day entries
|
51
|
+
merge_entries(entries) {|e| e.date}
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.merge_entries entries
|
55
|
+
merged = Hash.new(0)
|
56
|
+
|
57
|
+
entries.each do |entry|
|
58
|
+
merged[yield(entry)] += entry.hours
|
59
|
+
end
|
60
|
+
|
61
|
+
merged
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.create_entries entries
|
65
|
+
entries.collect do |date, hours|
|
66
|
+
Entry.new(hours, date)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.sort entries
|
71
|
+
entries.sort
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/test/test_grammar.rb
CHANGED
@@ -3,34 +3,34 @@ require File.dirname(__FILE__) + '/test_helper.rb'
|
|
3
3
|
class TestGrammar < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_hours
|
6
|
-
assert_equal 5, hours("5 hours")
|
7
|
-
assert_equal 5, hours("5hours")
|
8
|
-
assert_equal 5, hours("5 h")
|
9
|
-
assert_equal 5, hours("5h")
|
10
|
-
assert_equal 5, hours("5")
|
6
|
+
assert_equal 5.hours, hours("5 hours")
|
7
|
+
assert_equal 5.hours, hours("5hours")
|
8
|
+
assert_equal 5.hours, hours("5 h")
|
9
|
+
assert_equal 5.hours, hours("5h")
|
10
|
+
assert_equal 5.hours, hours("5")
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_minutes
|
14
|
-
assert_equal 10, minutes("5 h 10 minutes")
|
15
|
-
assert_equal 10, minutes("5 h 10 m")
|
16
|
-
assert_equal 10, minutes("5 h 10m")
|
17
|
-
assert_equal 10, minutes("5h10m")
|
18
|
-
assert_equal 10, minutes("5:10")
|
14
|
+
assert_equal 10.minutes, minutes("5 h 10 minutes")
|
15
|
+
assert_equal 10.minutes, minutes("5 h 10 m")
|
16
|
+
assert_equal 10.minutes, minutes("5 h 10m")
|
17
|
+
assert_equal 10.minutes, minutes("5h10m")
|
18
|
+
assert_equal 10.minutes, minutes("5:10")
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_hour_ranges
|
22
|
-
assert_equal 4.hours,
|
23
|
-
assert_equal 4.hours,
|
24
|
-
assert_equal 4.hours,
|
25
|
-
assert_equal 4.hours,
|
26
|
-
assert_equal 16.hours,
|
27
|
-
assert_equal 2.hours,
|
28
|
-
assert_equal 2.hours,
|
22
|
+
assert_equal 4.hours, hours("13 to 17")
|
23
|
+
assert_equal 4.hours, hours("1 to 5")
|
24
|
+
assert_equal 4.hours, hours("1pm to 5pm")
|
25
|
+
assert_equal 4.hours, hours("1 pm to 5 pm")
|
26
|
+
assert_equal 16.hours, hours("1 am to 5 pm")
|
27
|
+
assert_equal 2.hours, hours("11 to 1pm")
|
28
|
+
assert_equal 2.hours, hours("11pm to 1am")
|
29
29
|
end
|
30
30
|
|
31
31
|
def test_hour_minute_ranges
|
32
|
-
assert_equal 4.hours + 30.minutes,
|
33
|
-
assert_equal 4.hours + 10.minutes,
|
32
|
+
assert_equal 4.hours + 30.minutes, hours("1 to 5:30")
|
33
|
+
assert_equal 4.hours + 10.minutes, hours("13:30 to 17:40")
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_with_activity
|
@@ -39,30 +39,24 @@ class TestGrammar < Test::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_from_time
|
42
|
-
assert_in_delta 2.hours,
|
42
|
+
assert_in_delta 2.hours, hours("from #{DateTime.now.hour - 2}:#{DateTime.now.min}"), 10.seconds #of delta
|
43
43
|
end
|
44
44
|
|
45
45
|
def activity source
|
46
46
|
parse(source).last
|
47
47
|
end
|
48
48
|
|
49
|
-
def range source
|
50
|
-
res = parse("#{source} on X")
|
51
|
-
((res[1] - res[0]) * 24).hours
|
52
|
-
end
|
53
|
-
|
54
49
|
def hours source
|
55
50
|
res = parse("#{source} on X")
|
56
|
-
res[1]
|
51
|
+
((res[1] - res[0]) * 24).hours
|
57
52
|
end
|
58
53
|
|
59
54
|
def minutes source
|
60
|
-
|
61
|
-
res[1].min - res[0].min
|
55
|
+
hours(source) % 1.hour
|
62
56
|
end
|
63
57
|
|
64
58
|
def parse source
|
65
|
-
InputParser.parse(source)
|
59
|
+
InputParser.parse(source, DateTime.now )
|
66
60
|
end
|
67
61
|
|
68
62
|
end
|
data/test/test_reader.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
require 'worked/reader'
|
3
|
+
require 'mathn'
|
4
|
+
|
5
|
+
class TestReader < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_single_day
|
8
|
+
data = <<-EOS
|
9
|
+
2009-04-21T21:26:00+00:00 2009-04-21T22:26:00+00:00 fixed bugs
|
10
|
+
EOS
|
11
|
+
|
12
|
+
recorded = Worked::Reader.read(data)
|
13
|
+
|
14
|
+
assert_equal 17, recorded[0].week_of_year
|
15
|
+
assert_equal 1, recorded[0].hours
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_single_day_two_records
|
19
|
+
data = <<-EOS
|
20
|
+
2009-04-21T21:26:00+00:00 2009-04-21T22:26:00+00:00 fixed bugs
|
21
|
+
2009-04-21T23:26:00+00:00 2009-04-21T23:46:00+00:00 fixed bugs
|
22
|
+
EOS
|
23
|
+
|
24
|
+
recorded = Worked::Reader.read(data)
|
25
|
+
|
26
|
+
assert_equal 4/3, recorded[0].hours
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_multiple_days
|
30
|
+
data = <<-EOS
|
31
|
+
2009-04-21T21:00:00+00:00 2009-04-21T22:30:00+00:00 fixed bugs
|
32
|
+
2009-04-24T17:00:00+00:00 2009-04-24T23:30:00+00:00 fixed bugs
|
33
|
+
EOS
|
34
|
+
|
35
|
+
recorded = Worked::Reader.read(data)
|
36
|
+
|
37
|
+
assert_equal 3/2, recorded[0].hours
|
38
|
+
assert_equal 13/2, recorded[1].hours
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_multiple_weeks
|
42
|
+
data = <<-EOS
|
43
|
+
2009-04-21T21:00:00+00:00 2009-04-21T22:30:00+00:00 fixed bugs
|
44
|
+
2009-05-24T17:00:00+00:00 2009-05-24T23:30:00+00:00 fixed bugs
|
45
|
+
EOS
|
46
|
+
|
47
|
+
recorded = Worked::Reader.read(data)
|
48
|
+
|
49
|
+
assert_equal 17, recorded[0].week_of_year
|
50
|
+
assert_equal 22, recorded[1].week_of_year
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_januar_first
|
54
|
+
data = <<-EOS
|
55
|
+
2009-01-01T00:00:00+00:00 2009-01-1T22:00:00+00:00 fixed bugs
|
56
|
+
EOS
|
57
|
+
|
58
|
+
recorded = Worked::Reader.read(data)
|
59
|
+
|
60
|
+
assert_equal 1, recorded[0].week_of_year
|
61
|
+
assert_equal 22, recorded[0].hours
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_worked_over_midnight
|
65
|
+
data = <<-EOS
|
66
|
+
2009-01-01T23:00:00+00:00 2009-01-02T02:00:00+00:00 fixed bugs
|
67
|
+
EOS
|
68
|
+
|
69
|
+
recorded = Worked::Reader.read(data)
|
70
|
+
|
71
|
+
assert_equal 3, recorded[0].hours
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_multiple_weeks_2
|
75
|
+
data = <<-EOS
|
76
|
+
2009-04-21T21:00:00+00:00 2009-04-21T22:30:00+00:00 fixed bugs
|
77
|
+
2009-06-21T21:00:00+00:00 2009-06-21T22:30:00+00:00 fixed bugs
|
78
|
+
2009-05-24T17:00:00+00:00 2009-05-24T23:30:00+00:00 fixed bugs
|
79
|
+
EOS
|
80
|
+
|
81
|
+
recorded = Worked::Reader.read(data)
|
82
|
+
|
83
|
+
assert_equal 17, recorded[0].week_of_year
|
84
|
+
assert_equal 22, recorded[1].week_of_year
|
85
|
+
assert_equal 26, recorded[2].week_of_year
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_merge_by_week
|
89
|
+
data = <<-EOS
|
90
|
+
2009-04-21T21:00:00+00:00 2009-04-21T22:00:00+00:00 fixed bugs
|
91
|
+
2009-04-22T21:00:00+00:00 2009-04-22T22:00:00+00:00 fixed bugs
|
92
|
+
2009-05-23T21:00:00+00:00 2009-05-23T22:00:00+00:00 fixed bugs
|
93
|
+
2009-05-23T21:00:00+00:00 2009-05-23T22:00:00+00:00 fixed bugs
|
94
|
+
EOS
|
95
|
+
|
96
|
+
recorded = Worked::Reader.by_week(data)
|
97
|
+
|
98
|
+
assert_equal 2, recorded[0].hours
|
99
|
+
assert_equal 2, recorded[1].hours
|
100
|
+
end
|
101
|
+
end
|
data/test/test_worked_cli.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "test_helper.rb")
|
2
2
|
require 'tempfile'
|
3
|
+
require 'fileutils'
|
3
4
|
require 'enumerator'
|
4
5
|
require 'active_support'
|
5
6
|
require 'worked/cli'
|
@@ -14,12 +15,16 @@ class TestWorkedCli < Test::Unit::TestCase
|
|
14
15
|
reset_stdout
|
15
16
|
end
|
16
17
|
|
18
|
+
def teardown
|
19
|
+
@file.unlink
|
20
|
+
end
|
21
|
+
|
17
22
|
def reset_stdout
|
18
23
|
@stdout_io = StringIO.new
|
19
24
|
end
|
20
25
|
|
21
26
|
def run_with argument
|
22
|
-
Worked::CLI.execute(@stdout_io, argument, @file)
|
27
|
+
Worked::CLI.execute(@stdout_io, argument.split, @file)
|
23
28
|
@file.flush
|
24
29
|
end
|
25
30
|
|
@@ -29,6 +34,20 @@ class TestWorkedCli < Test::Unit::TestCase
|
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
37
|
+
def stdio
|
38
|
+
@stdout_io.string
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_graph
|
42
|
+
graph_file = Tempfile.new("graph").path + ".png"
|
43
|
+
|
44
|
+
run_with " -g #{graph_file}"
|
45
|
+
|
46
|
+
assert_equal "Graph saved to #{graph_file}.\n", stdio
|
47
|
+
|
48
|
+
FileUtils::remove graph_file
|
49
|
+
end
|
50
|
+
|
32
51
|
def test_with_new_file
|
33
52
|
@file.open
|
34
53
|
run_with "5 hours on coding"
|
@@ -42,7 +61,7 @@ class TestWorkedCli < Test::Unit::TestCase
|
|
42
61
|
assert "coding", first[1]
|
43
62
|
assert "documentation and refactoring", second[1]
|
44
63
|
|
45
|
-
assert_equal "",
|
64
|
+
assert_equal "", stdio
|
46
65
|
|
47
66
|
reset_stdout
|
48
67
|
|
@@ -54,6 +73,6 @@ class TestWorkedCli < Test::Unit::TestCase
|
|
54
73
|
assert 1.hours, third[0]
|
55
74
|
assert "refactoring", third[1]
|
56
75
|
|
57
|
-
assert_equal "",
|
76
|
+
assert_equal "", stdio
|
58
77
|
end
|
59
78
|
end
|
data/website/index.html
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>
|
8
|
+
Worked
|
9
|
+
</title>
|
10
|
+
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
|
+
<style>
|
12
|
+
|
13
|
+
</style>
|
14
|
+
<script type="text/javascript">
|
15
|
+
window.onload = function() {
|
16
|
+
settings = {
|
17
|
+
tl: { radius: 10 },
|
18
|
+
tr: { radius: 10 },
|
19
|
+
bl: { radius: 10 },
|
20
|
+
br: { radius: 10 },
|
21
|
+
antiAlias: true,
|
22
|
+
autoPad: true,
|
23
|
+
validTags: ["div"]
|
24
|
+
}
|
25
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
26
|
+
versionBox.applyCornersToAll();
|
27
|
+
}
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="main">
|
32
|
+
|
33
|
+
<h1>Worked</h1>
|
34
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/worked"; return false'>
|
35
|
+
<p>Get Version</p>
|
36
|
+
<a href="http://rubyforge.org/projects/worked" class="numbers">0.2.0</a>
|
37
|
+
</div>
|
38
|
+
<ul>
|
39
|
+
<li>http://worked.rubyforge.org/</li>
|
40
|
+
</ul>
|
41
|
+
<p>The easiest time recording application imagineable.</p>
|
42
|
+
<h2><span class="caps">DESCRIPTION</span>:</h2>
|
43
|
+
<p>Worked is really the simplest time recording (or tracking, whatever term you<br />
|
44
|
+
prefer) application that does all you need and nothing more (only `date >> file` is easier).</p>
|
45
|
+
<p>It simply takes a time or a time range and an activity and appends it to a<br />
|
46
|
+
hidden file in the current directory. The use case is, that you have ‘.worked’<br />
|
47
|
+
files in the root directories of your projects, and before you finish your<br />
|
48
|
+
current work period, you probably commit something and you also record your time.</p>
|
49
|
+
<p>Right now, the times are just recorded, no report generation yet.</p>
|
50
|
+
<h2><span class="caps">FEATURES</span>:</h2>
|
51
|
+
<ul>
|
52
|
+
<li>Appends a time range and an activity to a file.</li>
|
53
|
+
<li>Create a graph from the collected data, showing hours/week.</li>
|
54
|
+
</ul>
|
55
|
+
<h2><span class="caps">SYNOPSIS</span>:</h2>
|
56
|
+
<p>The syntax is quite flexible, and if you’d like to have it extended, just drop<br />
|
57
|
+
me an email. The input consists of: <time> on <activity>. So for example, you<br />
|
58
|
+
can write ‘5 hours on documentation’. The following formats for the <time> part<br />
|
59
|
+
are recognized:</p>
|
60
|
+
<ul>
|
61
|
+
<li>5 hours</li>
|
62
|
+
<li>5h</li>
|
63
|
+
<li>or simply ‘5’</li>
|
64
|
+
</ul>
|
65
|
+
<p>Minutes can be added or standing alone as well:</p>
|
66
|
+
<ul>
|
67
|
+
<li>5 h 10 minutes</li>
|
68
|
+
<li>5 hours 10 m</li>
|
69
|
+
<li>30 minutes</li>
|
70
|
+
<li>or simply ‘5:10’</li>
|
71
|
+
</ul>
|
72
|
+
<p>Stored is not the absolute time, but the point <time> hours ago and the current<br />
|
73
|
+
time.</p>
|
74
|
+
<p>Of course you can also specify both start- and end time of an activity with the<br />
|
75
|
+
following syntax:</p>
|
76
|
+
<ul>
|
77
|
+
<li>13 to 17</li>
|
78
|
+
<li>1 pm to 5 pm</li>
|
79
|
+
<li>13:30 to 17:40</li>
|
80
|
+
</ul>
|
81
|
+
<p>If you just want to record an activity from a certain point upto now, you can<br />
|
82
|
+
write:</p>
|
83
|
+
<ul>
|
84
|
+
<li>from 5pm</li>
|
85
|
+
<li>from 11:30</li>
|
86
|
+
</ul>
|
87
|
+
<p>Specifying dates is not supported right now, but you can of course edit the file<br />
|
88
|
+
directly if necessary.</p>
|
89
|
+
<p>Since version 0.2, worked also has the ability to generate a graph from the<br />
|
90
|
+
collected data, using the -g argument. [<span class="caps">TODO</span>: Add image here.]</p>
|
91
|
+
<h2><span class="caps">STORY</span>:</h2>
|
92
|
+
<p>The week before my new semester started, I promised to myself to do better (or,<br />
|
93
|
+
to do it at all) time recording to get a better feeling for how much I actually<br />
|
94
|
+
worked. I used to write my time into a wiki, but that was still too tedious to<br />
|
95
|
+
do so I often neglected it and had to record it from memory some days later. So I<br />
|
96
|
+
needed a tool and a few hours later, ‘worked’ was born.</p>
|
97
|
+
<h2><span class="caps">REQUIREMENTS</span>:</h2>
|
98
|
+
<ul>
|
99
|
+
<li>Uses the really great Treetop for the input parser.</li>
|
100
|
+
</ul>
|
101
|
+
<h2><span class="caps">INSTALL</span>:</h2>
|
102
|
+
<ul>
|
103
|
+
<li>sudo gem install worked</li>
|
104
|
+
</ul>
|
105
|
+
<h2><span class="caps">TODO</span>:</h2>
|
106
|
+
<ul>
|
107
|
+
<li>Simple report generation.</li>
|
108
|
+
<li>Investigate if it can be used together with git (e.g. with hooks), so I can, for example, use the last line in a commit message to make my ‘worked’ statement.</li>
|
109
|
+
</ul>
|
110
|
+
<p class="coda">
|
111
|
+
<a href="me@misto.ch">Mirko Stocker</a>, 12th June 2009<br>
|
112
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>,
|
113
|
+
by Daniel Cadenas via <a href="http://depgraph.rubyforge.org/">DepGraph</a>
|
114
|
+
</p>
|
115
|
+
</div>
|
116
|
+
|
117
|
+
<!-- insert site tracking codes here, like Google Urchin -->
|
118
|
+
|
119
|
+
</body>
|
120
|
+
</html>
|