hcl 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/HACKING.markdown +21 -0
- data/README.markdown +18 -6
- data/VERSION +1 -1
- data/bin/hcl +0 -1
- data/hcl.gemspec +26 -34
- data/lib/hcl/app.rb +8 -5
- data/lib/hcl/commands.rb +19 -4
- data/lib/hcl/day_entry.rb +5 -1
- data/lib/hcl/task.rb +14 -3
- metadata +27 -13
- data/.gitignore +0 -5
data/CHANGELOG
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
= Recent Changes in HCl
|
2
2
|
|
3
|
+
== v0.3.1
|
4
|
+
|
5
|
+
* use STDERR instead of STDOUT for error reporting
|
6
|
+
* sort tasks before viewing tasks (brian@madebyrocket.com)
|
7
|
+
* resume command to resume the most recently active timer (brian@madebyrocket.com)
|
8
|
+
* show current time when on 'start', 'stop', and 'show' commands (scharfie@gmail.com)
|
9
|
+
* include client name in tasks list (scharfie@gmail.com)
|
10
|
+
|
11
|
+
== v0.3.0 Fri Apr 2 10:42:20 2010 -0700
|
12
|
+
|
13
|
+
* added support for free accounts
|
14
|
+
|
3
15
|
== v0.2.3 Sun Aug 23 21:39:34 2009 -0700
|
4
16
|
|
5
17
|
* Allow decimal time offset without a dot, closes #29.
|
data/HACKING.markdown
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Hacking HCl
|
2
|
+
|
3
|
+
## Rubygems
|
4
|
+
|
5
|
+
They're useful so we use them to install our gems. However there's no need to
|
6
|
+
explicitly include rubygems in the app. That's up the system to decide. Don't
|
7
|
+
require rubygems in the code.
|
8
|
+
|
9
|
+
We require rubygems in the test as a developer convenience.
|
10
|
+
|
11
|
+
## Running HCl in place
|
12
|
+
|
13
|
+
This is common and supported:
|
14
|
+
|
15
|
+
ruby -rubygems -Ilib bin/hcl
|
16
|
+
|
17
|
+
Don't add dir(__FILE__)/lib to the load path in the binary. Bad manners.
|
18
|
+
|
19
|
+
## That's it
|
20
|
+
|
21
|
+
That's it. I mostly wrote this to explain why I rolled back certain changes.
|
data/README.markdown
CHANGED
@@ -7,18 +7,22 @@ HCl is a command-line tool for interacting with Harvest time sheets using the
|
|
7
7
|
|
8
8
|
## Quick Start
|
9
9
|
|
10
|
-
You can install hcl from
|
10
|
+
You can install hcl directly from rubygems.org:
|
11
11
|
|
12
12
|
$ gem install hcl
|
13
13
|
$ hcl show [date]
|
14
14
|
|
15
|
+
or you can install from source using jeweler:
|
16
|
+
|
17
|
+
$ gem install jeweler
|
18
|
+
$ rake install
|
19
|
+
|
15
20
|
### Prerequisites
|
16
21
|
|
17
22
|
* Ruby (tested with 1.8.7)
|
18
23
|
* Ruby OpenSSL support (in debian/ubuntu: apt-get install libopenssl-ruby)
|
19
24
|
* Ruby extension building support (in debian/ubuntu: apt-get install ruby-dev)
|
20
25
|
* RubyGems 1.3.3
|
21
|
-
* Gemcutter (gem install gemcutter; gem tumble)
|
22
26
|
* Trollop option-parsing library (gem install trollop)
|
23
27
|
* Chronic date-parsing library (gem install chronic)
|
24
28
|
* HighLine console input library (gem install highline)
|
@@ -32,7 +36,9 @@ You can install hcl from Gemcutter:
|
|
32
36
|
hcl unset <key>
|
33
37
|
hcl start (<task_alias> | <project_id> <task_id>) [+time] [msg ...]
|
34
38
|
hcl note <msg ...>
|
35
|
-
hcl
|
39
|
+
hcl aliases
|
40
|
+
hcl stop [msg]
|
41
|
+
hcl resume
|
36
42
|
|
37
43
|
### Starting a Timer
|
38
44
|
|
@@ -95,10 +101,16 @@ commands show the timesheet for the specified day:
|
|
95
101
|
|
96
102
|
## Author
|
97
103
|
|
98
|
-
[Zack Hobson][zgh]
|
104
|
+
HCl was designed and implemented by [Zack Hobson][zgh].
|
105
|
+
|
106
|
+
* Non-SSL support by [Michael Bleigh][mbleigh].
|
107
|
+
* Resume command by [Brian Cooke][bricooke].
|
108
|
+
* UI improvements by [Chris Scharf][scharfie].
|
99
109
|
|
100
110
|
See LICENSE for copyright details.
|
101
111
|
|
102
|
-
[zgh]:
|
103
|
-
[
|
112
|
+
[zgh]: http://github.com/zenhob
|
113
|
+
[mbleigh]: http://github.com/mbleigh
|
114
|
+
[bricooke]: http://github.com/bricooke
|
115
|
+
[scharfie]: http://github.com/scharfie
|
104
116
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/bin/hcl
CHANGED
data/hcl.gemspec
CHANGED
@@ -1,63 +1,55 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hcl}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Zack Hobson"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-07-13}
|
13
13
|
s.default_executable = %q{hcl}
|
14
14
|
s.description = %q{HCl is a command-line client for manipulating Harvest time sheets.}
|
15
15
|
s.email = %q{zack@opensourcery.com}
|
16
16
|
s.executables = ["hcl"]
|
17
17
|
s.extra_rdoc_files = [
|
18
18
|
"LICENSE",
|
19
|
-
|
19
|
+
"README.markdown"
|
20
20
|
]
|
21
21
|
s.files = [
|
22
22
|
".document",
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
23
|
+
"CHANGELOG",
|
24
|
+
"HACKING.markdown",
|
25
|
+
"LICENSE",
|
26
|
+
"README.markdown",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/hcl",
|
30
|
+
"deps.rip",
|
31
|
+
"hcl.gemspec",
|
32
|
+
"lib/hcl/app.rb",
|
33
|
+
"lib/hcl/commands.rb",
|
34
|
+
"lib/hcl/day_entry.rb",
|
35
|
+
"lib/hcl/project.rb",
|
36
|
+
"lib/hcl/task.rb",
|
37
|
+
"lib/hcl/timesheet_resource.rb",
|
38
|
+
"lib/hcl/utility.rb",
|
39
|
+
"test/app_test.rb",
|
40
|
+
"test/day_entry_test.rb",
|
41
|
+
"test/test_helper.rb",
|
42
|
+
"test/utility_test.rb"
|
43
43
|
]
|
44
44
|
s.homepage = %q{http://github.com/zenhob/hcl}
|
45
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
46
45
|
s.require_paths = ["lib"]
|
47
|
-
s.rubygems_version = %q{1.
|
46
|
+
s.rubygems_version = %q{1.4.1}
|
48
47
|
s.summary = %q{Harvest timesheets from the command-line}
|
49
|
-
s.test_files = [
|
50
|
-
"test/app_test.rb",
|
51
|
-
"test/day_entry_test.rb",
|
52
|
-
"test/test_helper.rb",
|
53
|
-
"test/utility_test.rb"
|
54
|
-
]
|
55
48
|
|
56
49
|
if s.respond_to? :specification_version then
|
57
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
58
50
|
s.specification_version = 3
|
59
51
|
|
60
|
-
if Gem::Version.new(Gem::
|
52
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
53
|
s.add_runtime_dependency(%q<termios>, [">= 0"])
|
62
54
|
s.add_runtime_dependency(%q<trollop>, [">= 1.10.2"])
|
63
55
|
s.add_runtime_dependency(%q<chronic>, [">= 0.2.3"])
|
data/lib/hcl/app.rb
CHANGED
@@ -30,7 +30,7 @@ class Net::HTTP
|
|
30
30
|
end
|
31
31
|
|
32
32
|
module HCl
|
33
|
-
VERSION = "0.
|
33
|
+
VERSION = "0.3.1"
|
34
34
|
|
35
35
|
class App
|
36
36
|
include HCl::Utility
|
@@ -39,8 +39,6 @@ module HCl
|
|
39
39
|
SETTINGS_FILE = "#{ENV['HOME']}/.hcl_settings"
|
40
40
|
CONFIG_FILE = "#{ENV['HOME']}/.hcl_config"
|
41
41
|
|
42
|
-
class UnknownCommand < StandardError; end
|
43
|
-
|
44
42
|
def initialize
|
45
43
|
read_config
|
46
44
|
read_settings
|
@@ -73,13 +71,17 @@ module HCl
|
|
73
71
|
end
|
74
72
|
end
|
75
73
|
else
|
76
|
-
|
74
|
+
STDERR.puts "unrecognized command `#{@command}'"
|
75
|
+
exit 1
|
77
76
|
end
|
78
77
|
else
|
79
78
|
show
|
80
79
|
end
|
80
|
+
rescue RuntimeError => e
|
81
|
+
STDERR.puts "Error: #{e}"
|
82
|
+
exit 1
|
81
83
|
rescue TimesheetResource::Failure => e
|
82
|
-
puts "Internal failure. #{e}"
|
84
|
+
STDERR.puts "Internal failure. #{e}"
|
83
85
|
exit 1
|
84
86
|
end
|
85
87
|
end
|
@@ -99,6 +101,7 @@ Commands:
|
|
99
101
|
hcl unset <key>
|
100
102
|
hcl start <task> [msg]
|
101
103
|
hcl stop [msg]
|
104
|
+
hcl resume
|
102
105
|
hcl note <msg>
|
103
106
|
|
104
107
|
Examples:
|
data/lib/hcl/commands.rb
CHANGED
@@ -51,14 +51,14 @@ module HCl
|
|
51
51
|
exit 1
|
52
52
|
end
|
53
53
|
timer = task.start(:starting_time => starting_time, :note => args.join(' '))
|
54
|
-
puts "Started timer for #{timer}
|
54
|
+
puts "Started timer for #{timer} (at #{current_time})"
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def stop
|
58
58
|
entry = DayEntry.with_timer
|
59
59
|
if entry
|
60
60
|
entry.toggle
|
61
|
-
puts "Stopped #{entry}
|
61
|
+
puts "Stopped #{entry} (at #{current_time})"
|
62
62
|
else
|
63
63
|
puts "No running timers found."
|
64
64
|
end
|
@@ -84,7 +84,22 @@ module HCl
|
|
84
84
|
total_hours = total_hours + day.hours.to_f
|
85
85
|
end
|
86
86
|
puts "\t" + '-' * 13
|
87
|
-
puts "\t#{as_hours total_hours}\ttotal"
|
87
|
+
puts "\t#{as_hours total_hours}\ttotal (as of #{current_time})"
|
88
|
+
end
|
89
|
+
|
90
|
+
def resume
|
91
|
+
entry = DayEntry.last
|
92
|
+
if entry
|
93
|
+
puts "Resumed #{entry} (at #{current_time})"
|
94
|
+
entry.toggle
|
95
|
+
else
|
96
|
+
puts "No timers found"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def current_time
|
102
|
+
Time.now.strftime('%I:%M %p').downcase
|
88
103
|
end
|
89
104
|
end
|
90
105
|
end
|
data/lib/hcl/day_entry.rb
CHANGED
@@ -11,7 +11,7 @@ module HCl
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_s
|
14
|
-
"#{client} #{project} #{task} (#{formatted_hours})"
|
14
|
+
"#{client} - #{project} - #{task} (#{formatted_hours})"
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.from_xml xml
|
@@ -42,6 +42,10 @@ module HCl
|
|
42
42
|
def self.with_timer
|
43
43
|
all.detect {|t| t.running? }
|
44
44
|
end
|
45
|
+
|
46
|
+
def self.last
|
47
|
+
all.sort {|a,b| a.updated_at<=>b.updated_at}[-1]
|
48
|
+
end
|
45
49
|
|
46
50
|
def running?
|
47
51
|
!@data[:timer_started_at].nil? && !@data[:timer_started_at].empty?
|
data/lib/hcl/task.rb
CHANGED
@@ -9,14 +9,25 @@ module HCl
|
|
9
9
|
end)
|
10
10
|
end
|
11
11
|
unless tasks.empty?
|
12
|
-
File.open(
|
12
|
+
File.open(cache_file, 'w') do |f|
|
13
13
|
f.write tasks.uniq.to_yaml
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
def self.cache_file
|
19
|
+
File.join(ENV['HOME'],'.hcl_tasks')
|
20
|
+
end
|
17
21
|
|
18
22
|
def self.all
|
19
|
-
YAML.load
|
23
|
+
tasks = File.exists?(cache_file) ? YAML.load(File.read(cache_file)) : []
|
24
|
+
tasks = tasks.sort do |a,b|
|
25
|
+
r = a.project.client <=> b.project.client
|
26
|
+
r = a.project.name <=> b.project.name if r == 0
|
27
|
+
r = a.name <=> b.name if r == 0
|
28
|
+
r
|
29
|
+
end
|
30
|
+
tasks
|
20
31
|
end
|
21
32
|
|
22
33
|
def self.find project_id, id
|
@@ -26,7 +37,7 @@ module HCl
|
|
26
37
|
end
|
27
38
|
|
28
39
|
def to_s
|
29
|
-
"#{project.name} #{name}"
|
40
|
+
"#{project.client} - #{project.name} - #{name}"
|
30
41
|
end
|
31
42
|
|
32
43
|
def add opts
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hcl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 17
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
9
|
+
- 1
|
10
|
+
version: 0.3.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Zack Hobson
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-07-13 00:00:00 -07:00
|
18
19
|
default_executable: hcl
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: termios
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
27
30
|
segments:
|
28
31
|
- 0
|
29
32
|
version: "0"
|
@@ -33,9 +36,11 @@ dependencies:
|
|
33
36
|
name: trollop
|
34
37
|
prerelease: false
|
35
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
36
40
|
requirements:
|
37
41
|
- - ">="
|
38
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 59
|
39
44
|
segments:
|
40
45
|
- 1
|
41
46
|
- 10
|
@@ -47,9 +52,11 @@ dependencies:
|
|
47
52
|
name: chronic
|
48
53
|
prerelease: false
|
49
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
50
56
|
requirements:
|
51
57
|
- - ">="
|
52
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 17
|
53
60
|
segments:
|
54
61
|
- 0
|
55
62
|
- 2
|
@@ -61,9 +68,11 @@ dependencies:
|
|
61
68
|
name: highline
|
62
69
|
prerelease: false
|
63
70
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
64
72
|
requirements:
|
65
73
|
- - ">="
|
66
74
|
- !ruby/object:Gem::Version
|
75
|
+
hash: 1
|
67
76
|
segments:
|
68
77
|
- 1
|
69
78
|
- 5
|
@@ -75,9 +84,11 @@ dependencies:
|
|
75
84
|
name: shoulda
|
76
85
|
prerelease: false
|
77
86
|
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
78
88
|
requirements:
|
79
89
|
- - ">="
|
80
90
|
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
81
92
|
segments:
|
82
93
|
- 0
|
83
94
|
version: "0"
|
@@ -87,9 +98,11 @@ dependencies:
|
|
87
98
|
name: mocha
|
88
99
|
prerelease: false
|
89
100
|
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
90
102
|
requirements:
|
91
103
|
- - ">="
|
92
104
|
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
93
106
|
segments:
|
94
107
|
- 0
|
95
108
|
version: "0"
|
@@ -106,8 +119,8 @@ extra_rdoc_files:
|
|
106
119
|
- README.markdown
|
107
120
|
files:
|
108
121
|
- .document
|
109
|
-
- .gitignore
|
110
122
|
- CHANGELOG
|
123
|
+
- HACKING.markdown
|
111
124
|
- LICENSE
|
112
125
|
- README.markdown
|
113
126
|
- Rakefile
|
@@ -131,33 +144,34 @@ homepage: http://github.com/zenhob/hcl
|
|
131
144
|
licenses: []
|
132
145
|
|
133
146
|
post_install_message:
|
134
|
-
rdoc_options:
|
135
|
-
|
147
|
+
rdoc_options: []
|
148
|
+
|
136
149
|
require_paths:
|
137
150
|
- lib
|
138
151
|
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
139
153
|
requirements:
|
140
154
|
- - ">="
|
141
155
|
- !ruby/object:Gem::Version
|
156
|
+
hash: 3
|
142
157
|
segments:
|
143
158
|
- 0
|
144
159
|
version: "0"
|
145
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
146
162
|
requirements:
|
147
163
|
- - ">="
|
148
164
|
- !ruby/object:Gem::Version
|
165
|
+
hash: 3
|
149
166
|
segments:
|
150
167
|
- 0
|
151
168
|
version: "0"
|
152
169
|
requirements: []
|
153
170
|
|
154
171
|
rubyforge_project:
|
155
|
-
rubygems_version: 1.
|
172
|
+
rubygems_version: 1.4.1
|
156
173
|
signing_key:
|
157
174
|
specification_version: 3
|
158
175
|
summary: Harvest timesheets from the command-line
|
159
|
-
test_files:
|
160
|
-
|
161
|
-
- test/day_entry_test.rb
|
162
|
-
- test/test_helper.rb
|
163
|
-
- test/utility_test.rb
|
176
|
+
test_files: []
|
177
|
+
|