mm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/bin/mm ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "#{File.dirname(__FILE__)}/../lib/turbine"
5
+
6
+ Turbine::Application.new.run(ARGV.map { |e| e.dup })
@@ -0,0 +1,9 @@
1
+ Dir["#{Turbine::Application.config_dir}/commands/standard/*.rb"].each do |extension|
2
+ require extension
3
+ end
4
+
5
+ Dir["#{Turbine::Application.config_dir}/commands/custom/*.rb"].each do |extension|
6
+ require extension
7
+ end
8
+
9
+ Turbine::Application.api_key = "<%= key %>"
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require "turbine/timer"
4
+ require "turbine/queue"
5
+ require "turbine/commands/init"
6
+ require "turbine/command_runner"
7
+ require "turbine/application"
@@ -0,0 +1,85 @@
1
+ require "pathname"
2
+ require "highline"
3
+ require "restclient"
4
+ require "json"
5
+
6
+ module Turbine
7
+ class Application
8
+
9
+ class << self
10
+ def config_dir(dir = Pathname.new("."))
11
+ turbine_dir = dir + ".turbine"
12
+ if dir.children.include?(turbine_dir)
13
+ turbine_dir.expand_path
14
+ else
15
+ return nil if dir.expand_path.root?
16
+ config_dir(dir.parent)
17
+ end
18
+ end
19
+
20
+ def extensions
21
+ @extensions ||= []
22
+ end
23
+
24
+ def extension(&block)
25
+ extensions << Module.new(&block)
26
+ end
27
+
28
+ def current_project
29
+ File.read("#{config_dir}/current_project").chomp
30
+ end
31
+
32
+ def current_project=(project)
33
+ File.open("#{config_dir}/current_project", "w") { |f| f << project }
34
+ end
35
+
36
+ def current_project_url
37
+ projects[current_project]
38
+ end
39
+
40
+ def projects
41
+ JSON.parse(File.read("#{config_dir}/projects.json"))
42
+ end
43
+
44
+ attr_accessor :api_key
45
+ end
46
+
47
+ def initialize
48
+ @params = {}
49
+ @prompt = HighLine.new
50
+ @option_parser = OptionParser.new
51
+ @turbine_dir = nil
52
+ end
53
+
54
+ def read_file(name)
55
+ File.read("#{self.class.config_dir}/#{name}")
56
+ end
57
+
58
+ def write_file(name, mode="w")
59
+ File.open("#{self.class.config_dir}/#{name}", mode) { |f| yield(f) }
60
+ end
61
+
62
+ def delete_file(name)
63
+ rm_f "#{self.class.config_dir}/#{name}"
64
+ end
65
+
66
+ def service
67
+ RestClient::Resource.new(self.class.current_project_url, self.class.api_key, "")
68
+ end
69
+
70
+ def load_log_data
71
+ JSON.parse(File.read("#{self.class.config_dir}/log/#{self.class.api_key}.json"))
72
+ end
73
+
74
+ def clear_log_data
75
+ write_file("log/#{self.class.api_key}.json") do |f|
76
+ f << [].to_json
77
+ end
78
+ end
79
+
80
+ attr_accessor :params, :prompt, :option_parser, :command
81
+
82
+ include ::Turbine::CommandRunner
83
+ include ::Turbine::StandardCommands
84
+ end
85
+ end
@@ -0,0 +1,63 @@
1
+ module Turbine
2
+ module CommandRunner
3
+ def setup
4
+ end
5
+
6
+ def run(argv)
7
+ init_and_exit(*argv) if argv[0] == "init"
8
+
9
+ unless self.class.config_dir
10
+ prompt.say "Cannot find config file. Did you forget to run turbine init?"
11
+ return
12
+ end
13
+
14
+ require "#{self.class.config_dir}/config"
15
+
16
+ self.class.extensions.each do |extension|
17
+ extend(extension)
18
+ end
19
+
20
+ setup
21
+ parse_options(*argv)
22
+
23
+ if respond_to?(command)
24
+ send(command)
25
+ else
26
+ prompt.say("Unknown command: #{command}")
27
+ end
28
+
29
+ teardown
30
+ end
31
+
32
+ def init_and_exit(*argv)
33
+ setup
34
+ parse_options(*argv)
35
+ init
36
+ teardown
37
+ exit
38
+ end
39
+
40
+ def teardown
41
+ end
42
+
43
+ def parse_options(*argv)
44
+ option_parser.on("-t", "=HOURS", Float) do |hours|
45
+ params[:hours] = hours
46
+ end
47
+
48
+ option_parser.on("-m", "=MSG", String) do |msg|
49
+ params[:message] = msg
50
+ end
51
+
52
+ option_parser.on("-k", "=KEY", String) do |msg|
53
+ params[:api_key] = msg
54
+ end
55
+
56
+ command, *arguments = option_parser.parse(*argv)
57
+
58
+ self.command = command
59
+ params[:arguments] = arguments
60
+ end
61
+ end
62
+ end
63
+
@@ -0,0 +1,42 @@
1
+ require "json"
2
+ require "erb"
3
+ require "fileutils"
4
+
5
+ module Turbine
6
+ module StandardCommands
7
+ include FileUtils
8
+
9
+ def init
10
+ mkdir_p(".turbine")
11
+ mkdir_p(".turbine/log")
12
+ mkdir_p(".turbine/commands")
13
+ mkdir_p(".turbine/commands/custom")
14
+
15
+ key = params[:api_key] || ENV['TURBINE_API_KEY']
16
+ url = params[:arguments][0]
17
+ project_name = params[:arguments][1] || "default"
18
+
19
+ raise if key.nil?
20
+
21
+ current_dir = File.dirname(__FILE__)
22
+
23
+ write_file("log/#{key}.json") { |f| f << [].to_json }
24
+
25
+ write_file("config.rb") do |f|
26
+ template = File.read("#{current_dir}/../../../data/config.rb.erb")
27
+ f << ERB.new(template).result(binding)
28
+ end
29
+
30
+ write_file("current_project") do |f|
31
+ f << project_name
32
+ end
33
+
34
+ write_file("projects.json") do |f|
35
+ f << { project_name => url }.to_json
36
+ end
37
+
38
+ cp_r("#{current_dir}/standard",
39
+ "#{self.class.config_dir}/commands/")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ Turbine::Application.extension do
2
+ def add
3
+ hours = params[:arguments].first
4
+
5
+ queue = Turbine::Queue.new(self.class.config_dir)
6
+ queue << hours
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ Turbine::Application.extension do
2
+ def commit
3
+ if message = params[:message]
4
+ queue = Turbine::Queue.new
5
+ duration = queue.sum.to_s
6
+ timestamp = Time.now.utc.to_s
7
+
8
+ if queue.empty?
9
+ prompt.say "ERROR: No entries!"
10
+ exit
11
+ end
12
+
13
+ log_data = load_log_data
14
+
15
+ log_data << { :description => message,
16
+ :recorded_timestamp => timestamp,
17
+ :recorded_date => Date.today.to_s,
18
+ :hours => duration }
19
+
20
+ write_file("log/#{self.class.api_key}.json") { |f| f << log_data.to_json }
21
+
22
+ prompt.say "Committed time entry totaling #{duration} hrs"
23
+
24
+ queue.clear
25
+ else
26
+ prompt.say "You need to supply a message"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ Turbine::Application.extension do
2
+ def drop
3
+ log_data = load_log_data
4
+
5
+ log_data.delete_at(params[:arguments].first.to_i)
6
+
7
+ write_file("log/#{self.class.api_key}.json") { |f| f << log_data.to_json }
8
+ end
9
+ end
@@ -0,0 +1,66 @@
1
+ Turbine::Application.extension do
2
+
3
+ def project
4
+ _list_projects || _manage_projects
5
+ end
6
+
7
+ private
8
+
9
+ def _list_projects
10
+ return false unless params[:arguments].empty?
11
+
12
+ prompt.say("\n")
13
+
14
+ self.class.projects.each do |name, url|
15
+ prompt.say(name == self.class.current_project ? " > " : " ")
16
+ prompt.say("#{name} : #{url}")
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def _manage_projects
23
+ command, project, *args = *params[:arguments]
24
+ case command
25
+ when "add"
26
+ url = args.shift
27
+
28
+ raise "Not enough arguments" unless url
29
+
30
+ prompt.say "adding project: #{project}"
31
+ projects = self.class.projects
32
+ write_file("projects.json") do |f|
33
+ f << projects.merge(project => url).to_json
34
+ end
35
+ when "rm"
36
+ projects = self.class.projects
37
+
38
+ unless projects.keys.include?(project)
39
+ prompt.say("No such project: #{project}")
40
+ return
41
+ end
42
+
43
+ prompt.say "removing project: #{project}"
44
+
45
+ projects.delete(project)
46
+
47
+ write_file("projects.json") do |f|
48
+ f << projects.to_json
49
+ end
50
+ when "select"
51
+ projects = self.class.projects
52
+
53
+ unless projects.keys.include?(project)
54
+ prompt.say("No such project: #{project}")
55
+ return
56
+ end
57
+
58
+ prompt.say "selecting project: #{project}"
59
+
60
+ self.class.current_project = project
61
+ else
62
+ prompt.say "Unknown command: project #{command}"
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,11 @@
1
+ Turbine::Application.extension do
2
+ def push
3
+ log_data = load_log_data
4
+
5
+ log_data.each do |record|
6
+ service["/time_entries"].post("time_entry" => record)
7
+ end
8
+
9
+ clear_log_data
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ Turbine::Application.extension do
2
+ def reset
3
+ delete_file("queue")
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ Turbine::Application.extension do
2
+ def rewind
3
+ delete_file("timestamp")
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ Turbine::Application.extension do
2
+ def staged
3
+ log_data = load_log_data
4
+
5
+ prompt.say "These entries will be created upon push:\n\n"
6
+
7
+ log_data.each_with_index do |record, i|
8
+ prompt.say " [#{i}] #{record["description"]} (#{record["hours"]} hrs)"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ Turbine::Application.extension do
2
+ def start
3
+ timer = Turbine::Timer.new
4
+ if timer.running?
5
+ prompt.say "Timer already started, please stop or rewind first"
6
+ else
7
+ timer.write_timestamp
8
+ prompt.say "Timer started at #{Time.now}"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ Turbine::Application.extension do
2
+ def status
3
+ queue = Turbine::Queue.new
4
+
5
+ if queue.empty?
6
+ prompt.say "No entries for this commit yet\n\n"
7
+ else
8
+ entries = queue.entries.join(", ")
9
+ sum = queue.entries.inject {|sum, n| sum + n }
10
+ prompt.say "Entries for this commit: ( #{entries} )"
11
+ prompt.say "Total for this commit: #{sum}\n\n"
12
+ end
13
+
14
+ timer = Turbine::Timer.new
15
+ if timer.running?
16
+ prompt.say("Current timer started at #{timer.timestamp}")
17
+ prompt.say("Elapsed time: #{'%0.2f' % timer.elapsed_time} hrs")
18
+ else
19
+ prompt.say("Timer is not presently running")
20
+ end
21
+
22
+ prompt.say("\n")
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ Turbine::Application.extension do
2
+ def stop
3
+ timer = Turbine::Timer.new
4
+ if timer.running?
5
+ begin
6
+ duration = prompt.ask("Time to enter (CTRL-C to cancel): ", Float) do |q|
7
+ q.default = ("%0.2f" % timer.elapsed_time).to_f
8
+ end
9
+
10
+ queue = Turbine::Queue.new
11
+ queue << duration
12
+
13
+ timer.clear_timestamp
14
+ rescue Interrupt
15
+ prompt.say("\n")
16
+ end
17
+ else
18
+ prompt.say "ERROR: Timer was not running."
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,40 @@
1
+ module Turbine
2
+ class Queue
3
+ include Enumerable
4
+
5
+ def initialize(dir=Turbine::Application.config_dir)
6
+ @file = "#{dir}/queue"
7
+ end
8
+
9
+ def <<(duration)
10
+ File.open(@file, "a") { |f| f.puts(duration.to_s)}
11
+ self
12
+ end
13
+
14
+ def empty?
15
+ !File.exist?(@file)
16
+ end
17
+
18
+ def entries
19
+ return [] if empty?
20
+
21
+ File.read(@file).split("\n").map { |e| e.to_f }
22
+ end
23
+
24
+ def each
25
+ entries.each { |e| yield(e) }
26
+ end
27
+
28
+ def sum
29
+ return 0 if empty?
30
+
31
+ File.foreach(@file).inject(0) do |sum, line|
32
+ sum + line.to_f
33
+ end
34
+ end
35
+
36
+ def clear
37
+ FileUtils.rm_f(@file)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ require "fileutils"
2
+ require "time"
3
+ require "date"
4
+
5
+ module Turbine
6
+ class Timer
7
+ MissingTimestampError = Class.new(StandardError)
8
+
9
+ def initialize(dir=Turbine::Application.config_dir)
10
+ @file = "#{dir}/timestamp"
11
+ end
12
+
13
+ def write_timestamp
14
+ File.open(@file, "w") { |f| f << Time.now.utc.to_s }
15
+ end
16
+
17
+ def timestamp
18
+ raise MissingTimestampError unless running?
19
+ Time.parse(File.read(@file)).localtime
20
+ end
21
+
22
+ def elapsed_time
23
+ (Time.now.utc - timestamp.utc) / 60.0 / 60.0
24
+ end
25
+
26
+ def clear_timestamp
27
+ FileUtils.rm_f(@file)
28
+ end
29
+
30
+ def running?
31
+ File.exist?(@file)
32
+ end
33
+ end
34
+ end
35
+
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mm
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Gregory Brown
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-10 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: " Seeekrit\n"
23
+ email: " gregory.t.brown@gmail.com"
24
+ executables:
25
+ - mm
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/turbine/application.rb
32
+ - lib/turbine/command_runner.rb
33
+ - lib/turbine/timer.rb
34
+ - lib/turbine/queue.rb
35
+ - lib/turbine/commands/standard/staged.rb
36
+ - lib/turbine/commands/standard/start.rb
37
+ - lib/turbine/commands/standard/add.rb
38
+ - lib/turbine/commands/standard/reset.rb
39
+ - lib/turbine/commands/standard/drop.rb
40
+ - lib/turbine/commands/standard/status.rb
41
+ - lib/turbine/commands/standard/push.rb
42
+ - lib/turbine/commands/standard/rewind.rb
43
+ - lib/turbine/commands/standard/project.rb
44
+ - lib/turbine/commands/standard/commit.rb
45
+ - lib/turbine/commands/standard/stop.rb
46
+ - lib/turbine/commands/init.rb
47
+ - lib/turbine.rb
48
+ - data/config.rb.erb
49
+ - bin/mm
50
+ - Rakefile
51
+ has_rdoc: true
52
+ homepage: http://pixelpowerhouse.com
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.7
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: A seecret
85
+ test_files: []
86
+