timekeeper 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/tk CHANGED
@@ -1,68 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- # == Synopsis
3
- #
4
- # Timekeeper. Keeping track of your time.
5
- #
6
- # == Usage
7
- #
8
- # tk [OPTIONS]
9
- #
10
- # -h, --help:
11
- # show help
12
- #
13
- # --config [file]
14
- # Location of your configuration file
15
- #
16
- # --title [title], -t [title]:
17
- # What do you want to register
18
- #
19
- # --target [target], -c [target]:
20
- # Who is going to pay?
21
- #
22
- # --time [time], -s [time]:
23
- # How long did it take?
24
- #
25
- # --description [description], -m [description]
26
- # More? You want to be more specific?
27
- #
28
- # --date [date], -d [date]
29
- # When exactly did it happen?
30
- #
31
- # --remove [id]
32
- # Remove a record.
33
- #
34
- require File.expand_path(File.dirname(__FILE__) + "/../lib/timekeeper")
2
+ require 'rubygems'
35
3
 
36
- require "getoptlong"
37
- require "rdoc/usage"
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'timekeeper'
38
6
 
39
- opts = GetoptLong.new(
40
- [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
41
- [ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
42
- [ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
43
- [ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
44
- [ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
45
- [ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
46
- [ "--remove" , GetoptLong::REQUIRED_ARGUMENT ],
47
- [ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
48
- )
49
-
50
- if ARGV.length == 0
51
- puts "Please provide some options, type --help"
52
- exit 0
53
- end
54
-
55
- tk = Timekeeper.new
56
-
57
- attributes = {}
58
- opts.each do |opt, arg|
59
- case opt
60
- when "--help": RDoc::usage
61
- when "--config": tk.config arg
62
- when "--remove": tk.delete(arg); exit 0
63
- else
64
- attributes.store(opt.gsub("-",""), arg)
65
- end
66
- end
67
-
68
- tk.store(attributes)
7
+ Timekeeper::Runner.tk(ARGV)
data/bin/tv CHANGED
@@ -1,74 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- # == Synopsis
3
- #
4
- # Timeviewer. Keeping an eye on your tracked time.
5
- #
6
- # == Usage
7
- #
8
- # tv [OPTIONS]
9
- #
10
- # -h, --help:
11
- # show help
12
- #
13
- # --config [file]
14
- # Location of your configuration file
15
- #
16
- # --name [name], -n [name]:
17
- # Query by name
18
- #
19
- # --title [title], -t [title]:
20
- # Query by title
21
- #
22
- # --target [target], -c [target]:
23
- # Query by target
24
- #
25
- # --description [description], -m [description]
26
- # Query by description
27
- #
28
- # --date [date], -d [date]
29
- # Query by date
30
- #
31
- require File.dirname(__FILE__) + '/../lib/timekeeper'
32
-
33
- require "getoptlong"
34
- require "rdoc/usage"
35
- require "fastercsv"
2
+ require 'rubygems'
36
3
 
37
- opts = GetoptLong.new(
38
- [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
39
- [ "--csv" , GetoptLong::NO_ARGUMENT ],
40
- [ "--all" , GetoptLong::NO_ARGUMENT ],
41
- [ "--name", "-n", GetoptLong::REQUIRED_ARGUMENT ],
42
- [ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
43
- [ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
44
- [ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
45
- [ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
46
- [ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
47
- [ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
48
- )
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'timekeeper'
49
6
 
50
- if ARGV.length == 0
51
- puts "Please provide some options, type --help"
52
- exit 0
53
- end
54
-
55
- tv = Timeviewer.new
56
- output = nil
57
-
58
- attributes = {}
59
- opts.each do |opt, arg|
60
- case opt
61
- when "--help": RDoc::usage
62
- when "--csv" : output = :csv
63
- when "--config": tv.config arg
64
- else
65
- attributes.store(opt.gsub("-",""), arg)
66
- end
67
- end
68
-
69
- records = tv.all
70
- if output
71
- Timeviewer.export(records, "export", output)
72
- else
73
- puts records.collect{|r| Keep.new(r) }
74
- end
7
+ Timekeeper::Runner.tv(ARGV)
@@ -1,6 +1,10 @@
1
- require "rubygems"
2
1
  require "rufus/tokyo"
2
+ require "fastercsv"
3
+ require "optparse"
3
4
 
4
- require File.dirname(__FILE__) + "/timekeeper/keep"
5
- require File.dirname(__FILE__) + "/timekeeper/timekeeper"
6
- require File.dirname(__FILE__) + "/timekeeper/timeviewer"
5
+ require "timekeeper/keep"
6
+ require "timekeeper/keeper"
7
+ require "timekeeper/viewer"
8
+ require "timekeeper/runner"
9
+ require "timekeeper/keeper_options"
10
+ require "timekeeper/viewer_options"
@@ -1,72 +1,65 @@
1
- class Keep
2
- YES = ["YES", "Y", "y", "yes", "true", true]
3
- NO = ["NO", "N", "n", "no", "false", false, nil]
1
+ module Timekeeper
2
+
3
+ class Keep
4
4
 
5
- attr_accessor :name, :time, :title, :description, :target, :date, :pk, :track
5
+ attr_accessor :name, :time, :title, :description, :target, :date, :pk
6
6
 
7
- def initialize(attributes)
8
- set_attributes(attributes)
9
- end
7
+ def initialize(attributes)
8
+ set_attributes(attributes)
9
+ end
10
10
 
11
- def update(attributes)
12
- set_attributes(attributes)
13
- end
11
+ def update(attributes)
12
+ set_attributes(attributes)
13
+ end
14
14
 
15
- def date=(value)
16
- if value
17
- if value.is_a?(Date)
18
- @date = value
19
- else
20
- @date = parse_date(value.to_s)
15
+ def date=(value)
16
+ if value
17
+ if value.is_a?(Date)
18
+ @date = value
19
+ else
20
+ @date = parse_date(value.to_s)
21
+ end
21
22
  end
22
23
  end
23
- end
24
+
25
+ def validate
26
+ mandatory(%w(name target title date time))
27
+ end
24
28
 
25
- def track=(value)
26
- if YES.include?(value)
27
- @track = true
28
- elsif NO.include?(value)
29
- @track = false
29
+ def to_hash
30
+ {:name => name, :time => time, :title => title, :description => description,
31
+ :target => target, :date => date}
30
32
  end
31
- end
32
-
33
- def validate
34
- mandatory(%w(name target title date time))
35
- end
36
-
37
- def to_hash
38
- {:name => name, :time => time, :title => title, :description => description,
39
- :target => target, :date => date, :track => track}
40
- end
41
33
 
42
- def to_s
43
- "#{pk}|#{name}|#{target}|#{title}|#{description}|#{date}|#{time}|#{track}"
44
- end
34
+ def to_s
35
+ "#{pk}|#{name}|#{target}|#{title}|#{description}|#{date}|#{time}"
36
+ end
45
37
 
46
- private
38
+ private
47
39
 
48
- def set_attributes(attributes)
49
- attributes.each do |key, value|
50
- respond_to?("#{key}=") ? send("#{key}=", value) : raise(StandardError, "unknown attribute: #{key}")
40
+ def set_attributes(attributes)
41
+ attributes.each do |key, value|
42
+ respond_to?("#{key}=") ? send("#{key}=", value) : raise(StandardError, "unknown attribute: #{key}")
43
+ end
44
+ validate
45
+ self
51
46
  end
52
- validate
53
- self
54
- end
55
47
 
56
- def parse_date(value)
57
- case value
58
- when "today" : Date.today
59
- when "yesterday": Date.today - 1
60
- when "tomorrow" : Date.today + 1
61
- else
62
- Date.parse(value)
48
+ def parse_date(value)
49
+ case value
50
+ when "today" : Date.today
51
+ when "yesterday": Date.today - 1
52
+ when "tomorrow" : Date.today + 1
53
+ else
54
+ Date.parse(value)
55
+ end
63
56
  end
64
- end
65
57
 
66
- def mandatory(attributes)
67
- attributes.each do |attribute|
68
- raise(StandardError, "#{attribute} is mandatory") unless send(attribute)
58
+ def mandatory(attributes)
59
+ attributes.each do |attribute|
60
+ raise(StandardError, "#{attribute} is mandatory") unless send(attribute)
61
+ end
69
62
  end
70
- end
71
63
 
72
- end
64
+ end
65
+ end
@@ -0,0 +1,50 @@
1
+ module Timekeeper
2
+
3
+ class Keeper
4
+
5
+ def config(file="timekeeper.yml")
6
+ @config ||= YAML.load_file(file)
7
+ end
8
+
9
+ def delete(id)
10
+ table.delete(id)
11
+ end
12
+
13
+ def delete_all
14
+ table.clear
15
+ end
16
+
17
+ def close
18
+ table.close
19
+ end
20
+
21
+ def count
22
+ table.count
23
+ end
24
+
25
+ def store(attributes)
26
+ attributes.store("name", config["name"])
27
+ attributes.store("date", Date.today) unless attributes["date"]
28
+ table[table.genuid] = Keep.new(attributes).to_hash
29
+ end
30
+
31
+ def get(id)
32
+ if attributes = table.lget(id.to_s).values.first
33
+ Keep.new(attributes)
34
+ end
35
+ end
36
+
37
+ def update(id, attributes_to_update)
38
+ if attributes = table.lget(id.to_s).values.first
39
+ table[id] = Keep.new(attributes).update(attributes_to_update).to_hash
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def table
46
+ @table ||= Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{config["name"]}-time.tct"))
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ module Timekeeper
2
+
3
+ class KeeperOptions < Hash
4
+ attr_reader :opts
5
+
6
+ def initialize(args)
7
+ super()
8
+
9
+ @opts = OptionParser.new do |o|
10
+ o.banner = "Usage: #{File.basename($0)} [options]"
11
+
12
+ o.on("--config FILE", "location of your configuration file - default is ./timekeeper.yml") do |file|
13
+ self[:config] = file
14
+ end
15
+
16
+ o.on('-t', '--title TITLE', 'What do you want to register?') do |title|
17
+ self[:title] = title
18
+ end
19
+
20
+ o.on('-c', '--target TARGET', 'Who is going to pay?') do |target|
21
+ self[:target] = target
22
+ end
23
+
24
+ o.on('-s', '--time TIME', 'How long did it take?') do |time|
25
+ self[:time] = time
26
+ end
27
+
28
+ o.on('-m', '--description DESCRIPTION', 'More? You want to be more specific?') do |description|
29
+ self[:description] = description
30
+ end
31
+
32
+ o.on('-d', '--date DATE', 'When exactly did it happen?') do |date|
33
+ self[:date] = date
34
+ end
35
+
36
+ o.on('--remove ID', 'Remove a record.') do |id|
37
+ self[:remove] = id
38
+ end
39
+
40
+ o.on('--update ID', 'Remove a record.') do |id|
41
+ self[:update] = id
42
+ end
43
+
44
+ o.on_tail('-h', '--help', 'Display this help and exit') do
45
+ puts @opts
46
+ exit
47
+ end
48
+
49
+ end
50
+
51
+ begin
52
+ @opts.parse!(args)
53
+ rescue OptionParser::InvalidOption => e
54
+ self[:invalid_argument] = e.message
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ module Timekeeper
2
+
3
+ class Runner
4
+
5
+ def self.tk(args)
6
+ options = KeeperOptions.new(args)
7
+ if options.any?
8
+ tk = Keeper.new
9
+ tk.config(options.delete(:config)) if options[:config]
10
+
11
+ if id = options[:remove]
12
+ tk.delete(id)
13
+ elsif id = options.delete(:update)
14
+ tk.update(id, options)
15
+ else
16
+ tk.store(options)
17
+ end
18
+ else
19
+ puts options.opts
20
+ end
21
+ end
22
+
23
+ def self.tv(args)
24
+ options = ViewerOptions.new(args)
25
+ tv = Viewer.new
26
+ tv.config(options.delete(:config)) if options[:config]
27
+ records = tv.all
28
+ if output = options.delete(:output)
29
+ Viewer.export(records, output[0], output[1])
30
+ else
31
+ puts records
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,38 @@
1
+ module Timekeeper
2
+
3
+ class Viewer
4
+
5
+ def config(file="timekeeper.yml")
6
+ @config ||= YAML.load_file(file)
7
+ end
8
+
9
+ def all
10
+ tables.collect{|table| table.query.collect{|attrs| Keep.new(attrs)}}.flatten!
11
+ end
12
+
13
+ def close
14
+ tables.each {|table| table.close}
15
+ end
16
+
17
+ def self.export(records, name="timekeeper", type= :csv)
18
+ if records.any?
19
+ case type.to_s
20
+ when "csv"
21
+ FasterCSV.open("#{name}.#{type}", "w") do |csv|
22
+ csv << records[0].keys
23
+ records.each do |record|
24
+ csv << record.values
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def tables
34
+ @tables ||= config["team"].collect{|t| Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{t}-time.tct"))}
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ module Timekeeper
2
+
3
+ class ViewerOptions < Hash
4
+ attr_reader :opts
5
+
6
+ def initialize(args)
7
+ super()
8
+
9
+ @opts = OptionParser.new do |o|
10
+ o.banner = "Usage: #{File.basename($0)} [options]"
11
+
12
+ o.on("--config FILE", "location of your configuration file - default is ./timekeeper.yml") do |file|
13
+ self[:config] = file
14
+ end
15
+
16
+ o.on("--csv [FILE]", "export to csv") do |file|
17
+ self[:output] = [(file || "timekeeper"), :csv]
18
+ end
19
+
20
+ o.on('-n', '--name NAME', 'Query on name') do |title|
21
+ self[:title] = title
22
+ end
23
+
24
+ o.on('-t', '--title TITLE', 'Query on title') do |title|
25
+ self[:title] = title
26
+ end
27
+
28
+ o.on('-c', '--target TARGET', 'Query on target') do |target|
29
+ self[:target] = target
30
+ end
31
+
32
+ o.on('-m', '--description DESCRIPTION', 'Query on description') do |description|
33
+ self[:description] = description
34
+ end
35
+
36
+ o.on('-d', '--date DATE', 'Query on date') do |date|
37
+ self[:date] = date
38
+ end
39
+
40
+ o.on_tail('-h', '--help', 'Display this help and exit') do
41
+ puts @opts
42
+ exit
43
+ end
44
+
45
+ end
46
+
47
+ begin
48
+ @opts.parse!(args)
49
+ rescue OptionParser::InvalidOption => e
50
+ self[:invalid_argument] = e.message
51
+ end
52
+ end
53
+
54
+ end
55
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timekeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - atog
@@ -55,8 +55,11 @@ extra_rdoc_files:
55
55
  files:
56
56
  - lib/timekeeper.rb
57
57
  - lib/timekeeper/keep.rb
58
- - lib/timekeeper/timekeeper.rb
59
- - lib/timekeeper/timeviewer.rb
58
+ - lib/timekeeper/keeper.rb
59
+ - lib/timekeeper/keeper_options.rb
60
+ - lib/timekeeper/runner.rb
61
+ - lib/timekeeper/viewer.rb
62
+ - lib/timekeeper/viewer_options.rb
60
63
  - LICENSE
61
64
  - README.rdoc
62
65
  has_rdoc: true
@@ -1,37 +0,0 @@
1
- class Timekeeper
2
-
3
- def config(file="timekeeper.yml")
4
- @config ||= YAML.load_file(file)
5
- end
6
-
7
- def delete(id)
8
- table.delete(id)
9
- end
10
-
11
- def delete_all
12
- table.clear
13
- end
14
-
15
- def store(attributes)
16
- attributes.store("name", config["name"])
17
- attributes.store("date", Date.today) unless attributes["date"]
18
- table[table.genuid] = Keep.new(attributes).to_hash
19
- end
20
-
21
- def get(id)
22
- if attributes = table.lget(id.to_s).values.first
23
- Keep.new(attributes)
24
- end
25
- end
26
-
27
- def update(id, attributes_to_update)
28
- if attributes = table.lget(id.to_s).values.first
29
- table[id] = Keep.new(attributes).update(attributes_to_update).to_hash
30
- end
31
- end
32
-
33
- def table
34
- @table ||= Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{config["name"]}-time.tct"))
35
- end
36
-
37
- end
@@ -1,31 +0,0 @@
1
- class Timeviewer
2
-
3
- def config(file="timekeeper.yml")
4
- @config ||= YAML.load_file(file)
5
- end
6
-
7
- def all
8
- tables.collect{|table| table.query}.flatten!
9
- end
10
-
11
- def self.export(records, name="export", type= :csv)
12
- if records.any?
13
- case type
14
- when :csv
15
- FasterCSV.open("#{name}.#{type}", "w") do |csv|
16
- csv << records[0].keys
17
- records.each do |record|
18
- csv << record.values
19
- end
20
- end
21
- end
22
- end
23
- end
24
-
25
- private
26
-
27
- def tables
28
- @tables ||= config["team"].collect{|t| Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{t}-time.tct"))}
29
- end
30
-
31
- end