timekeeper 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/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