punched 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c11e735e75e510009cdd02e3966362587174661a
4
- data.tar.gz: 73395dc375aced17abbaad5698b26eb384ad3675
2
+ SHA256:
3
+ metadata.gz: d45242bb8b8cbb631b9a5c933d404ca960c54912c21f7d5d67709785252e9fc1
4
+ data.tar.gz: 8da01d442a353abdba95f800c2f34b3f231ca51ee315b54e6405b3c71bc96935
5
5
  SHA512:
6
- metadata.gz: 5ab915be0d34843bb5a588b49b88e9921ebfc21892d6bb3ab5350a1ce7f382935bff00393493956f049b434b507a5c59f722f6c61ef53d73a0cf175ba100e288
7
- data.tar.gz: 51a5575c46bd9cc2e7e731de35fd0bdfdcf5408aa08c5108dafa3503791e553f05effa61da3c986aa776f2a6d95d46ed107eeedddc95ad52cc66722206c4caaa
6
+ metadata.gz: a590849b3b356ae0e1ed80cf77e5415f25c125662964b718d45688497d3f227cab309bd59f251aaf83c2f0634305f4f62a242430c008919df3ac76b0a830118f
7
+ data.tar.gz: c8749fa2a658eeb19db42d03ca6266bef9177eb9e601c5c80864abe937ba5c8fd564ea049a2d485855bc811a2907e99c04b5eda6d527f7252a60455a2d3681f3
data/.travis.yml CHANGED
@@ -1,9 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0
4
3
  - 2.1
5
4
  - 2.2
6
- - 2.3.0
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
7
8
  - ruby-head
8
9
  script: bundle exec rspec
9
10
  matrix:
data/Gemfile CHANGED
@@ -1,2 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
  gem "rspec"
3
+ gem "markdown-tables", "~> 1.0.2"
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Punchcard
2
2
  ## Minimal time tracking tool for cli
3
3
 
4
- [![Build Status](https://travis-ci.org/pstaender/punchcard.svg?branch=master)](https://travis-ci.org/pstaender/punchcard)
4
+ [![Build Status](https://img.shields.io/travis/pstaender/punched.svg?branch=v1.0.0&style=flat-square)](https://travis-ci.org/pstaender/punched)
5
5
 
6
6
  ### Requirements
7
7
 
data/bin/punched CHANGED
@@ -1,13 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
+
3
4
  require 'punchcard'
5
+ require 'csv'
6
+ require 'markdown-tables'
7
+ require 'date'
4
8
 
5
9
  #
6
10
  # CLI Wrapper
7
11
  #
8
12
 
9
13
  def available_actions
10
- PunchCard.new(nil).public_methods(false).reject { |item| item.to_s.end_with?('=') || item.to_s == 'project' }.sort
14
+ PunchCard.new(nil).public_methods(false).reject { |item| item.to_s.end_with?('=') || item.to_s == 'project' }.concat([:all]).sort
11
15
  end
12
16
 
13
17
  def action_available? action
@@ -24,11 +28,13 @@ def usage
24
28
  end
25
29
 
26
30
  def all action
27
- require 'csv'
28
- require 'date'
29
- puts ["project","status","last active on","total duration","hourly rate","earnings"].to_csv if action == 'csv'
30
- puts Dir[PunchCard::SETTINGS_DIR+'/*'].map { |file|
31
- data = CSV.parse(`ruby #{__FILE__} #{action} '#{File.basename(file)}'`).first
31
+ available_formats = %w(csv plain md)
32
+ unless available_formats.include?(action)
33
+ raise "Format #{action} is not supported. Possible formats are: #{available_formats.join(',')}"
34
+ end
35
+ labels = ["project","status","last active on","total duration","hourly rate","earnings"]
36
+ data = Dir[PunchCard::SETTINGS_DIR+'/*'].map { |file|
37
+ data = CSV.parse(`ruby #{__FILE__} csv '#{File.basename(file)}'`).first
32
38
  last_activity = !data[2].empty? ? DateTime.parse(data[2]).to_time.to_i : 0
33
39
  data.push(last_activity)
34
40
  data
@@ -36,11 +42,22 @@ def all action
36
42
  a.last <=> b.last
37
43
  }.reverse.map { |row|
38
44
  row[0...-1]
39
- }.map(&:to_csv).join
45
+ }
46
+
47
+ case action
48
+ when 'md'
49
+ puts MarkdownTables.make_table(labels, data, is_rows: true, align: ['l'])
50
+ when 'csv'
51
+ puts labels.to_csv
52
+ puts data.map(&:to_csv).join
53
+ when 'plain'
54
+ table = MarkdownTables.make_table(labels, data, is_rows: true, align: ['l'])
55
+ puts MarkdownTables.plain_text(table)
56
+ end
40
57
  end
41
58
 
42
59
  if ARGV.first == 'all'
43
- all ARGV[1] ? ARGV[1] : 'csv'
60
+ all ARGV[1] || 'plain'
44
61
  exit
45
62
  elsif ARGV.first && ['-h', '--help', 'help'].include?(ARGV.first)
46
63
  puts usage
data/lib/punchcard.rb CHANGED
@@ -1,17 +1,18 @@
1
1
  # (c) 2017-2018 by philipp staender
2
2
 
3
3
  require 'date'
4
+ require 'time'
4
5
 
5
- class PunchCardError < StandardError;
6
+ class PunchCardError < StandardError
6
7
  end
7
8
 
8
9
  class PunchCard
9
10
 
10
11
  SETTINGS_DIR = ENV['PUNCHCARD_DIR'] || File.expand_path('~/.punchcard')
11
12
  HOURLY_RATE_PATTERN = /^\s*(\d+)([^\d]+)*\s*/i
12
- TIME_POINT_PATTERN = /^(\d+)((\-)(\d+))*$/
13
+ TIME_POINT_PATTERN = /^((\d+|.+?\s[\+\-]\d{4}?\s*)(\-)*(\d+|\s.+\d?)*)$/
13
14
  META_KEY_PATTERN = /^([a-zA-Z0-9]+)\:\s*(.*)$/
14
- VERSION = '0.2.0'
15
+ VERSION = '1.0.0'
15
16
 
16
17
  attr_accessor :project
17
18
 
@@ -220,11 +221,11 @@ class PunchCard
220
221
  end
221
222
 
222
223
  def start_time= time
223
- append_new_line time
224
+ append_new_line timestamp_to_time(time)
224
225
  end
225
226
 
226
227
  def end_time= time
227
- replace_last_line "#{start_time}-#{time}"
228
+ replace_last_line "#{timestamp_to_time(start_time)} - #{timestamp_to_time(time)}"
228
229
  end
229
230
 
230
231
  def end_time
@@ -237,7 +238,23 @@ class PunchCard
237
238
 
238
239
  def line_to_time_points line
239
240
  matches = line.match(TIME_POINT_PATTERN)
240
- matches ? [matches[1].to_i, matches[4] ? matches[4].to_i : nil] : nil
241
+
242
+ time_points = matches ? [string_to_timestamp(matches[2]), string_to_timestamp(matches[4])] : nil
243
+ if time_points && time_points.reject(&:nil?).empty?
244
+ nil
245
+ else
246
+ time_points
247
+ end
248
+
249
+ end
250
+
251
+ def string_to_timestamp(str)
252
+ return str if str.nil?
253
+ str.strip!
254
+ # This is some legacy... previous versions stored timestamp,
255
+ # but now punched stores date-time strings for better readability.
256
+ # So we have to convert timestamp and date-time format into timestamp here
257
+ str =~ /^\d+$/ ? str.to_i : (str =~ /^\d{4}\-\d/ ? Time.parse(str).to_i : nil)
241
258
  end
242
259
 
243
260
  def last_entry
@@ -248,6 +265,10 @@ class PunchCard
248
265
  Time.now.to_i
249
266
  end
250
267
 
268
+ def timestamp_to_time(timestamp)
269
+ Time.at(timestamp)
270
+ end
271
+
251
272
  def read_project_data
252
273
  title = nil
253
274
  meta_data = []
@@ -55,10 +55,9 @@ describe PunchCard do
55
55
  end
56
56
 
57
57
  it 'should track a project time' do
58
- timestamp = Time.now.to_i
59
58
  start_and_stop
60
59
  expect(my_project_file.lines.first.strip).to eq('My Project')
61
- expect(my_project_file.lines.last.strip).to match('^'+timestamp.to_s[0..-3]+'\\d{2}\\-'+timestamp.to_s[0..-3]+'\\d{2}+$')
60
+ expect(my_project_file.lines.last.strip).to match(/^\d+-\d+-\d+ .+? - \d+-\d+-\d+ /)
62
61
  end
63
62
 
64
63
  it 'should calculate tracked total time' do
@@ -116,7 +115,7 @@ describe PunchCard do
116
115
  project_a.stop
117
116
  sleep 2
118
117
  project_b.stop
119
- expect(project_b.total.to_i - project_a.total.to_i).to be_between(2,3)
118
+ expect(project_b.total.to_i - project_a.total.to_i).to be_between(2,4)
120
119
  end
121
120
 
122
121
  it 'should load latest project by wildcard' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: punched
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philipp Staender
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2018-12-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Minimal time tracking tool for cli
14
14
  email:
@@ -47,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
47
  version: '0'
48
48
  requirements: []
49
49
  rubyforge_project: punched
50
- rubygems_version: 2.5.2
50
+ rubygems_version: 2.7.8
51
51
  signing_key:
52
52
  specification_version: 4
53
53
  summary: Punchcard Timetracker