ptimelog 0.9.0 → 0.10.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -0
- data/README.md +44 -7
- data/lib/ptimelog/app.rb +1 -1
- data/lib/ptimelog/command/add.rb +38 -2
- data/lib/ptimelog/command/show.rb +3 -0
- data/lib/ptimelog/configuration.rb +13 -10
- data/lib/ptimelog/day.rb +3 -3
- data/lib/ptimelog/entry.rb +15 -10
- data/lib/ptimelog/named_date.rb +26 -4
- data/lib/ptimelog/timelog.rb +12 -0
- data/lib/ptimelog/version.rb +1 -1
- data/ptimelog.gemspec +6 -0
- metadata +5 -5
- data/.ruby-gemset +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a7ad17dbf09bc8d7694f9261ffcc8216af2f1ec04be03e62ccabadf9732e8b0
|
4
|
+
data.tar.gz: 4ee34a775b9300e50971421adedee472fbfa5f5c0ec226b93e299d17474df411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 198b9c6aefbab6f64b617a6b2ad125f9e9921c829e1740ca08faa41c69c797fda1cca1181665adec6b68b51560b3a5bed88ad3b23a8bceba6382dd4b222bb129
|
7
|
+
data.tar.gz: d37ed829daa68c7527caafe929874c6523986609661f9a9155463f0307ac2fb9d14d3237878d6c6659f799ca59c9536e8cae46770f21cdb13916753277beaf2c
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.0
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.2
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# pTimeLog
|
2
2
|
|
3
|
-
small tooling to transfer timelog-entries from gtimelog's timelog.txt to the PuzzleTime
|
3
|
+
small tooling to transfer timelog-entries from gtimelog's timelog.txt to the PuzzleTime Timetracking Website.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/kronn/ptimelog)
|
4
6
|
|
5
7
|
## Approach
|
6
8
|
|
@@ -24,8 +26,8 @@ small tooling to transfer timelog-entries from gtimelog's timelog.txt to the Puz
|
|
24
26
|
- [ ] send user and pwd with every request
|
25
27
|
- [ ] make entries
|
26
28
|
- [ ] open day in browser for review
|
27
|
-
- [
|
28
|
-
- [
|
29
|
+
- [x] avoid duplicate entries
|
30
|
+
- [x] start/end time as indicator?
|
29
31
|
- [x] offer rounding times to the next 5, 10 or 15 minutes
|
30
32
|
- [x] allow to add entries from the command-line
|
31
33
|
- [ ] handle time-account and billable better
|
@@ -58,10 +60,13 @@ Currently supported actions are
|
|
58
60
|
- show
|
59
61
|
- upload
|
60
62
|
- edit
|
63
|
+
- add
|
64
|
+
- version
|
61
65
|
|
62
66
|
### Date-Identifier
|
63
67
|
|
64
|
-
To handle a specific date, the format YYYY-MM-DD is expected, e.g. 2017-12-25.
|
68
|
+
To handle a specific date, the format YYYY-MM-DD is expected, e.g. 2017-12-25.
|
69
|
+
Please note that you should not work on that day, unless you bring presents.
|
65
70
|
|
66
71
|
For reusability in a shell-history the following keywords are supported:
|
67
72
|
|
@@ -74,12 +79,44 @@ If nothing is specified, the action is applied to entries of the last day.
|
|
74
79
|
|
75
80
|
### Edit-Identifier
|
76
81
|
|
77
|
-
When the action is "edit", the next argument is treated as script that should
|
82
|
+
When the action is "edit", the next argument is treated as script that should
|
83
|
+
be edited.
|
78
84
|
|
79
85
|
If nothing is passed, the main timelog.txt is loaded.
|
80
86
|
|
81
87
|
Otherwise, a script to determine the time-account is loaded.
|
82
88
|
|
89
|
+
### Adding entries
|
90
|
+
|
91
|
+
In order to add entries with the ptimelog-cli, the complete entry needs to be
|
92
|
+
quoted on the command-line to count as one argument.
|
93
|
+
|
94
|
+
$ ptimelog add 'ticket 1337: Implement requirements -- client coding'
|
95
|
+
|
96
|
+
While this requires some knowledge of the file-format, it is no different than
|
97
|
+
entering the same string in gTimelog. For now, the entry is added to the
|
98
|
+
timelog.txt as it is passed. By default, the date/time added to the entry is
|
99
|
+
the one when the command is executed.
|
100
|
+
|
101
|
+
You can prefix a positive or negative signed number to slightly skew the entry
|
102
|
+
(think: '-5 meeting' or '+5 lunch \*\*') or even set a precise time ('10:30
|
103
|
+
meeting').
|
104
|
+
|
105
|
+
$ ptimelog add '-5 meeting: Discuss requirements -- client planning'
|
106
|
+
|
107
|
+
### Showing the Version
|
108
|
+
|
109
|
+
I got tired of asking rubygems which version I installed, so I took on the
|
110
|
+
herculean task of letting ptimelog show its own version.
|
111
|
+
|
112
|
+
### Formatting the Output
|
113
|
+
|
114
|
+
In order to format the output of the show-action into a table, a hopefully
|
115
|
+
convienient field-marker has been chosen. I think it is unlikely, that ∴ is
|
116
|
+
being used in a time-entry. Therefore, you can pipe the output into `column`:
|
117
|
+
|
118
|
+
ptimelog show today | column -t -s ∴
|
119
|
+
|
83
120
|
## Helper-Scripts
|
84
121
|
|
85
122
|
ptimelog can prefill the account-number and billable-state of an entry.
|
@@ -102,8 +139,8 @@ scripts, the code is almost identical and "just" needs to be compiled.
|
|
102
139
|
A config-file is read from `$HOME/.config/ptimelog/config`. It is expected
|
103
140
|
to be a YAML-file. Currently, it supports the following keys:
|
104
141
|
|
105
|
-
|
106
|
-
|
142
|
+
- rounding: [integer or false, default 15]
|
143
|
+
- base_url: [url to your puzzletime-installation, default https://time.puzzle.ch]
|
107
144
|
|
108
145
|
## Development
|
109
146
|
|
data/lib/ptimelog/app.rb
CHANGED
@@ -7,7 +7,7 @@ module Ptimelog
|
|
7
7
|
@config = Configuration.instance
|
8
8
|
command = (args[0] || 'show')
|
9
9
|
|
10
|
-
constant_name = command.to_s[0].upcase + command[1
|
10
|
+
constant_name = command.to_s[0].upcase + command[1..].downcase
|
11
11
|
command_class = Command.const_get(constant_name.to_sym)
|
12
12
|
raise ArgumentError, "Unsupported Command '#{command}'" if command_class.nil?
|
13
13
|
|
data/lib/ptimelog/command/add.rb
CHANGED
@@ -11,6 +11,7 @@ module Ptimelog
|
|
11
11
|
|
12
12
|
@task = task
|
13
13
|
@timelog = Ptimelog::Timelog.instance
|
14
|
+
@new_lines = []
|
14
15
|
end
|
15
16
|
|
16
17
|
def needs_entries?
|
@@ -18,12 +19,47 @@ module Ptimelog
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def run
|
21
|
-
|
22
|
+
add_empty_line if @timelog.previous_entry.date == yesterday
|
23
|
+
add_entry(*parse_task(@task))
|
22
24
|
|
25
|
+
save_file
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_task(line)
|
31
|
+
matches = line.match('(?<time>\d{1,2}:\d{2} )?(?<offset>[+-]\d+ )?(?<task>.*)')
|
32
|
+
formatted_time = if matches[:time]
|
33
|
+
Time.parse(matches[:time])
|
34
|
+
else
|
35
|
+
Time.now
|
36
|
+
end
|
37
|
+
.localtime
|
38
|
+
.then { |time| time + (matches[:offset].to_i * 60) }
|
39
|
+
.strftime('%F %R')
|
40
|
+
|
41
|
+
[formatted_time, matches[:task]]
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_entry(date_time, task)
|
45
|
+
@new_lines << "#{date_time}: #{task}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_empty_line
|
49
|
+
@new_lines << ''
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_file
|
23
53
|
@timelog.timelog_txt.open('a') do |log|
|
24
|
-
|
54
|
+
@new_lines.each do |line|
|
55
|
+
log << "#{line}\n"
|
56
|
+
end
|
25
57
|
end
|
26
58
|
end
|
59
|
+
|
60
|
+
def yesterday
|
61
|
+
NamedDate.new.named_date('yesterday')
|
62
|
+
end
|
27
63
|
end
|
28
64
|
end
|
29
65
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'pathname'
|
5
|
+
require 'yaml'
|
5
6
|
|
6
7
|
module Ptimelog
|
7
8
|
# Wrapper around configuration-options and -loading
|
@@ -9,10 +10,10 @@ module Ptimelog
|
|
9
10
|
include Singleton
|
10
11
|
|
11
12
|
CONFIGURATION_DEFAULTS = {
|
12
|
-
base_url
|
13
|
-
rounding
|
14
|
-
dir
|
15
|
-
timelog
|
13
|
+
'base_url' => 'https://time.puzzle.ch',
|
14
|
+
'rounding' => 15,
|
15
|
+
'dir' => '~/.config/ptimelog',
|
16
|
+
'timelog' => '~/.local/share/gtimelog/timelog.txt',
|
16
17
|
}.freeze
|
17
18
|
|
18
19
|
def initialize
|
@@ -21,10 +22,12 @@ module Ptimelog
|
|
21
22
|
|
22
23
|
def reset
|
23
24
|
@config = load_config(
|
24
|
-
Pathname.new(CONFIGURATION_DEFAULTS[
|
25
|
+
Pathname.new(CONFIGURATION_DEFAULTS['dir'])
|
26
|
+
.expand_path
|
27
|
+
.join('config')
|
25
28
|
)
|
26
|
-
wrap_with_pathname(
|
27
|
-
wrap_with_pathname(
|
29
|
+
wrap_with_pathname('dir')
|
30
|
+
wrap_with_pathname('timelog')
|
28
31
|
end
|
29
32
|
|
30
33
|
def load_config(fn)
|
@@ -34,13 +37,13 @@ module Ptimelog
|
|
34
37
|
end
|
35
38
|
|
36
39
|
def [](key)
|
37
|
-
@config[key.
|
40
|
+
@config[key.to_s]
|
38
41
|
end
|
39
42
|
|
40
43
|
def []=(key, value)
|
41
|
-
@config[key.
|
44
|
+
@config[key.to_s] = value
|
42
45
|
|
43
|
-
wrap_with_pathname(key.
|
46
|
+
wrap_with_pathname(key.to_s) if %w[dir timelog].include?(key.to_s)
|
44
47
|
end
|
45
48
|
|
46
49
|
private
|
data/lib/ptimelog/day.rb
CHANGED
@@ -9,10 +9,10 @@ module Ptimelog
|
|
9
9
|
|
10
10
|
def entries
|
11
11
|
timelog.each_with_object({}) do |(date, lines), entries|
|
12
|
-
next unless date
|
13
|
-
next unless @date ==
|
12
|
+
next unless date # guard against the machine
|
13
|
+
next unless @date.to_s == 'all' || @date == date # limit to one day if passed
|
14
14
|
|
15
|
-
entries[date] = join_similar(entries_of_day(lines)) # lines |> entries_of_day |> join_similar
|
15
|
+
entries[date] = join_similar(entries_of_day(lines)) # lines |> entries_of_day |> join_similar
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
data/lib/ptimelog/entry.rb
CHANGED
@@ -5,12 +5,11 @@ require 'time'
|
|
5
5
|
module Ptimelog
|
6
6
|
# Dataclass to wrap an entry
|
7
7
|
class Entry
|
8
|
-
# allow to read everything
|
9
|
-
attr_reader :date, :start_time, :finish_time, :ticket, :description,
|
10
|
-
:tags, :billable, :account
|
11
|
-
|
12
8
|
# define only trivial writers, omit special and derived values
|
13
|
-
|
9
|
+
attr_accessor :date, :ticket, :description
|
10
|
+
|
11
|
+
# allow to read everything else
|
12
|
+
attr_reader :start_time, :finish_time, :tags, :billable, :account
|
14
13
|
|
15
14
|
BILLABLE = 1
|
16
15
|
NON_BILLABLE = 0
|
@@ -54,7 +53,7 @@ module Ptimelog
|
|
54
53
|
end
|
55
54
|
|
56
55
|
def valid?
|
57
|
-
@start_time && !hidden?
|
56
|
+
@start_time && duration.positive? && !hidden?
|
58
57
|
end
|
59
58
|
|
60
59
|
def hidden?
|
@@ -77,10 +76,16 @@ module Ptimelog
|
|
77
76
|
end
|
78
77
|
|
79
78
|
def to_s
|
80
|
-
billable = billable? ? '$' : nil
|
79
|
+
billable = billable? ? '($)' : nil
|
80
|
+
tag_list = Array(@tags).compact
|
81
|
+
|
82
|
+
tags = tag_list.join(' ') if tag_list.any?
|
83
|
+
desc = [@ticket, @description].compact.join(': ')
|
84
|
+
acc = [@account, billable].compact.join(' ') if @account
|
85
|
+
|
81
86
|
[
|
82
|
-
@start_time, '-', @finish_time,
|
83
|
-
[
|
87
|
+
@start_time, '-', @finish_time, '∴',
|
88
|
+
[desc, tags, acc].compact.join(' ∴ '),
|
84
89
|
].compact.join(' ')
|
85
90
|
end
|
86
91
|
|
@@ -107,7 +112,7 @@ module Ptimelog
|
|
107
112
|
end
|
108
113
|
|
109
114
|
def script_args
|
110
|
-
@script_args ||= @tags.to_a[1
|
115
|
+
@script_args ||= @tags.to_a[1..].to_a.map(&:inspect).join(' ')
|
111
116
|
end
|
112
117
|
|
113
118
|
def infer_account_and_billable
|
data/lib/ptimelog/named_date.rb
CHANGED
@@ -9,17 +9,39 @@ module Ptimelog
|
|
9
9
|
named_date(arg) || :all
|
10
10
|
end
|
11
11
|
|
12
|
-
def named_date(date)
|
12
|
+
def named_date(date) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize
|
13
13
|
case date.to_s
|
14
|
-
when 'yesterday' then
|
14
|
+
when 'yesterday' then yesterday
|
15
15
|
when 'today' then Date.today.to_s
|
16
|
-
when 'last', '' then
|
17
|
-
when
|
16
|
+
when 'last', '' then last_entry.to_s || yesterday
|
17
|
+
when 'mon', 'monday' then previous_weekday('monday')
|
18
|
+
when 'tue', 'tuesday' then previous_weekday('tuesday')
|
19
|
+
when 'wed', 'wednesday' then previous_weekday('wednesday')
|
20
|
+
when 'thu', 'thursday' then previous_weekday('thursday')
|
21
|
+
when 'fri', 'friday' then previous_weekday('friday')
|
22
|
+
when 'sat', 'saturday' then previous_weekday('saturday')
|
23
|
+
when 'sun', 'sunday' then previous_weekday('sunday')
|
24
|
+
when /\d{4}(-\d{2}){2}/ then date.to_s
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
private
|
22
29
|
|
30
|
+
def previous_weekday(date)
|
31
|
+
Date.today.prev_day(7)
|
32
|
+
.step(Date.today.prev_day)
|
33
|
+
.find { |d| d.send(:"#{date}?") }
|
34
|
+
.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def last_entry
|
38
|
+
timelog.to_h.keys.compact.sort[-2]
|
39
|
+
end
|
40
|
+
|
41
|
+
def yesterday
|
42
|
+
Date.today.prev_day.to_s
|
43
|
+
end
|
44
|
+
|
23
45
|
def timelog
|
24
46
|
Timelog.load
|
25
47
|
end
|
data/lib/ptimelog/timelog.rb
CHANGED
@@ -15,6 +15,14 @@ module Ptimelog
|
|
15
15
|
def timelog_txt
|
16
16
|
Pathname.new(Configuration.instance[:timelog]).expand_path
|
17
17
|
end
|
18
|
+
|
19
|
+
def previous_entry
|
20
|
+
lines = timelog_txt.readlines.last(2)
|
21
|
+
last_line = lines.map(&:chomp).delete_if(&:empty?).last
|
22
|
+
last_entry = instance.tokenize(last_line)
|
23
|
+
|
24
|
+
Entry.from_timelog(last_entry)
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
28
|
def load
|
@@ -25,6 +33,10 @@ module Ptimelog
|
|
25
33
|
self.class.timelog_txt
|
26
34
|
end
|
27
35
|
|
36
|
+
def previous_entry
|
37
|
+
self.class.previous_entry
|
38
|
+
end
|
39
|
+
|
28
40
|
def read
|
29
41
|
timelog_txt.read
|
30
42
|
end
|
data/lib/ptimelog/version.rb
CHANGED
data/ptimelog.gemspec
CHANGED
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ['lib']
|
24
24
|
|
25
|
+
spec.required_ruby_version = '>= 2.7.0'
|
26
|
+
|
25
27
|
spec.add_dependency 'naught'
|
26
28
|
|
27
29
|
spec.add_development_dependency 'bundler'
|
@@ -30,5 +32,9 @@ Gem::Specification.new do |spec|
|
|
30
32
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
31
33
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
34
|
spec.add_development_dependency 'rubocop', '~> 0.50'
|
35
|
+
# spec.add_development_dependency 'rubocop-rake'
|
36
|
+
# spec.add_development_dependency 'rubocop-rspec'
|
37
|
+
# spec.add_development_dependency 'rubocop-packaging'
|
38
|
+
# spec.add_development_dependency 'rubocop-performance'
|
33
39
|
spec.add_development_dependency 'timecop', '~> 0.9'
|
34
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ptimelog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Viehweger
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: naught
|
@@ -136,8 +136,8 @@ files:
|
|
136
136
|
- ".rspec"
|
137
137
|
- ".rubocop.yml"
|
138
138
|
- ".rubocop_todo.yml"
|
139
|
-
- ".ruby-gemset"
|
140
139
|
- ".ruby-version"
|
140
|
+
- ".tool-versions"
|
141
141
|
- ".travis.yml"
|
142
142
|
- Gemfile
|
143
143
|
- LICENSE.txt
|
@@ -176,14 +176,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
176
|
requirements:
|
177
177
|
- - ">="
|
178
178
|
- !ruby/object:Gem::Version
|
179
|
-
version:
|
179
|
+
version: 2.7.0
|
180
180
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
181
|
requirements:
|
182
182
|
- - ">="
|
183
183
|
- !ruby/object:Gem::Version
|
184
184
|
version: '0'
|
185
185
|
requirements: []
|
186
|
-
rubygems_version: 3.1.
|
186
|
+
rubygems_version: 3.1.4
|
187
187
|
signing_key:
|
188
188
|
specification_version: 4
|
189
189
|
summary: Move time-entries from gTimelog to PuzzleTime
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
gpuzzletime
|