ptimelog 0.5.3 → 0.6.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
2
  SHA256:
3
- metadata.gz: 4683decb77f362d2861b903e30db9dcb330151f7ee43d6ddb3c332d3af4243b2
4
- data.tar.gz: 23c0c132975613fb3f16c064930e6aa72b49e28fbd7cd9b3636aef6863cbb1e4
3
+ metadata.gz: 53f453d27b45af79d5bef690d87c5ad36984848f3df02a3114cc60fb3e4a4dbf
4
+ data.tar.gz: 77c4269e3d12bc42db29624bf4b06e2092f1c60459d13aed8a2d3bf28e03ba12
5
5
  SHA512:
6
- metadata.gz: e24c93aefa5a8ae475013593af737f872bade8f0f02997551bd2fe2cce049e64bd42869fe9648630f1b02191f2f7fc87883b942a9e266492c0fa09227c51b592
7
- data.tar.gz: 043b2383d127e1aeccb716f8e14e47a365cdc309862c0d1309916ceb1695b194e1cb9aad1e4bc5f63f3b9a95aa3aae55981606018370b03d077a1f5a3d42159a
6
+ metadata.gz: 6db9a06490897de96ca955ad900876f8848482a2dfe1796cdf1f0dfdbb35ed0d44f61616e2c00fa56acc1cc427b3e39645b37fc65cf7144f55f414fd762fc15b
7
+ data.tar.gz: d6e38738b5f4384b03edac240bdcd7622e2812d8d056529d26d10903b6d1e73e3c72e1f3b4bfede1e4a234c5738ec8171d0385d276f3ab7843a8675759361251
data/.rubocop.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
- Metrics/LineLength:
3
+ Layout/LineLength:
4
4
  Max: 120
5
5
 
6
6
  Metrics/BlockLength:
@@ -13,12 +13,12 @@ Style/TrailingCommaInArrayLiteral:
13
13
  Style/TrailingCommaInHashLiteral:
14
14
  EnforcedStyleForMultiline: consistent_comma
15
15
 
16
- Layout/AlignHash:
16
+ Layout/HashAlignment:
17
17
  EnforcedHashRocketStyle: table
18
18
  EnforcedColonStyle: table
19
19
  EnforcedLastArgumentHashStyle: always_inspect # default
20
20
 
21
- Naming/UncommunicativeMethodParamName:
21
+ Naming/MethodParameterName:
22
22
  AllowedNames:
23
23
  - fn
24
24
  # default allowed names
data/.rubocop_todo.yml CHANGED
@@ -1,12 +1,12 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-08-06 22:23:40 +0200 using RuboCop version 0.65.0.
3
+ # on 2020-01-22 14:10:50 +0100 using RuboCop version 0.79.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 3
9
+ # Offense count: 4
10
10
  Metrics/AbcSize:
11
11
  Max: 16
12
12
 
data/README.md CHANGED
@@ -37,6 +37,7 @@ small tooling to transfer timelog-entries from gtimelog's timelog.txt to the Puz
37
37
  - [ ] from *-notation
38
38
  - [ ] allow to have a list of "favourite" time-accounts
39
39
  - [ ] select best-matching time-account according to tags, possibly limited to the favourites
40
+ - [x] combine billable and account-lookup into one script
40
41
  - [ ] add cli-help
41
42
  - [ ] use commander for CLI?
42
43
 
@@ -84,16 +85,15 @@ Otherwise, a script to determine the time-account is loaded.
84
85
  ptimelog can prefill the account-number and billable-state of an entry.
85
86
 
86
87
  The tags are used to determine a script that helps infer the time-account.
87
- These scripts should be located in `~/.config/ptimelog/parsers/` and be named
88
+ These scripts should be located in `~/.config/ptimelog/inferers/` and be named
88
89
  like the first tag used. The script gets the ticket, the description and all
89
- remaining tags passed as arguments. The output of the script should only be the
90
- ID of the time-account.
90
+ remaining tags passed as arguments.
91
91
 
92
- In order to infer the billable-state of an entry, a script
93
- `~/.config/ptimelog/billable` is called. It only gets the previously infered
94
- account-id as argument and is expected to output "true" or "false".
92
+ The output of the script should be the ID of the time-account and the
93
+ billable-state as "true" or "false". Both items need to be separated by
94
+ whitespace, so you can output those two on the same line or on different lines.
95
95
 
96
- Since these script are called a lot, it is better to write them in a compiled
96
+ Since these scripts are called a lot, it is better to write them in a compiled
97
97
  language. If you only like ruby, take a look at crystal. For such simple
98
98
  scripts, the code is almost identical and "just" needs to be compiled.
99
99
 
@@ -13,7 +13,7 @@ module Ptimelog
13
13
  end
14
14
 
15
15
  def run
16
- launch_editor(@file)
16
+ launch_editor(find_file(@file))
17
17
  end
18
18
 
19
19
  private
@@ -21,10 +21,50 @@ module Ptimelog
21
21
  def launch_editor(file)
22
22
  editor = `which $EDITOR`.chomp
23
23
 
24
- file = file.nil? ? Timelog.timelog_txt : @scripts.parser(@file)
25
-
26
24
  exec "#{editor} #{file}"
27
25
  end
26
+
27
+ def find_file(requested_file)
28
+ %i[
29
+ timelog
30
+ existing_inferer
31
+ existing_parser
32
+ billable
33
+ empty_inferer
34
+ ].each do |file_lookup|
35
+ valid, filename = send(file_lookup, requested_file)
36
+
37
+ return filename if valid
38
+ end
39
+ end
40
+
41
+ def timelog(file)
42
+ [file.nil?, Timelog.timelog_txt]
43
+ end
44
+
45
+ def existing_inferer(file)
46
+ fn = @scripts.inferer(file)
47
+
48
+ [fn.exist?, fn]
49
+ end
50
+
51
+ def existing_parser(file)
52
+ fn = @scripts.parser(file)
53
+
54
+ [fn.exist?, fn]
55
+ end
56
+
57
+ def billable(file)
58
+ [file == 'billable', @scripts.billable]
59
+ end
60
+
61
+ def empty_inferer(file)
62
+ [true, @scripts.inferer(file)]
63
+ end
64
+
65
+ def empty_parser(file)
66
+ [true, @scripts.parser(file)]
67
+ end
28
68
  end
29
69
  end
30
70
  end
@@ -30,6 +30,7 @@ module Ptimelog
30
30
  entry.description,
31
31
  entry.tags,
32
32
  entry.account,
33
+ (entry.billable? ? '$' : nil),
33
34
  ].compact.join(' ∴ '),
34
35
  ].compact.join(' ')
35
36
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ptimelog
4
+ # Allow to add some (hopefully) helpful deprecation warning
5
+ module DeprecationWarning
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ end
9
+
10
+ # Keep track of wether the deprecation have been shown already or not
11
+ module ClassMethods
12
+ def deprecation_warning_rendered?
13
+ @deprecation_warning_rendered == true
14
+ end
15
+
16
+ def reset_deprecation_warning!
17
+ @deprecation_warning_rendered = false
18
+ end
19
+
20
+ def deprecation_warning_rendered!
21
+ @deprecation_warning_rendered = true
22
+ end
23
+ end
24
+
25
+ def deprecate(*args)
26
+ warn deprecate_header(*args)
27
+
28
+ return if self.class.deprecation_warning_rendered?
29
+
30
+ warn deprecate_message(*args)
31
+ self.class.deprecation_warning_rendered!
32
+ end
33
+
34
+ def deprecate_header(_)
35
+ raise <<~MESSAGE
36
+ deprecate_header(args) not implemented
37
+
38
+ Please define a header/short-info for the deprecation, rendered every
39
+ time the deprecation is hit.
40
+ MESSAGE
41
+ end
42
+
43
+ def deprecate_message(_)
44
+ raise <<~MESSAGE
45
+ deprecate_message(args) not implemented
46
+
47
+ Please define a message () for the deprecation, rendered only the first
48
+ time the deprecation is hit.
49
+ MESSAGE
50
+ end
51
+ end
52
+ end
@@ -10,6 +10,9 @@ module Ptimelog
10
10
  # define only trivial writers, omit special and derived values
11
11
  attr_writer :date, :ticket, :description
12
12
 
13
+ BILLABLE = 1
14
+ NON_BILLABLE = 0
15
+
13
16
  def initialize(config = Configuration.instance)
14
17
  @config = config
15
18
  @script = Script.new(@config[:dir])
@@ -53,23 +56,29 @@ module Ptimelog
53
56
  end
54
57
 
55
58
  def hidden?
56
- @description =~ /\*\*$/ # hide lunch and breaks
59
+ @description.to_s.end_with?('**') # hide lunch and breaks
60
+ end
61
+
62
+ def billable?
63
+ @billable == BILLABLE
57
64
  end
58
65
 
66
+ # this method will be reduced in 0.7, when support for parsers is removed
59
67
  def infer_ptime_settings
60
- @account = infer_account
61
- @billable = infer_billable
68
+ return if hidden?
69
+
70
+ if @script.inferer(script_name).exist?
71
+ @account, @billable = infer_account_and_billable
72
+ else
73
+ @account = infer_account
74
+ @billable = infer_billable
75
+ end
62
76
  end
63
77
 
64
78
  def to_s
65
79
  [
66
80
  @start_time, '-', @finish_time,
67
- [
68
- @ticket,
69
- @description,
70
- @tags,
71
- @account,
72
- ].compact.join(' : '),
81
+ [@ticket, @description, @tags, @account].compact.join(' : '),
73
82
  ].compact.join(' ')
74
83
  end
75
84
 
@@ -92,24 +101,43 @@ module Ptimelog
92
101
  end.map { |part| part.to_s.rjust(2, '0') }.join(':')
93
102
  end
94
103
 
95
- def infer_account
96
- return unless @tags
104
+ def script_name
105
+ @script_name ||= @tags.to_a.first.to_s
106
+ end
97
107
 
98
- parser_name = @tags.first
99
- parser = @script.parser(parser_name)
108
+ def script_args
109
+ @script_args ||= @tags.to_a[1..-1].to_a.map(&:inspect).join(' ')
110
+ end
100
111
 
112
+ # this method will be removed in 0.7, when support for parsers is removed
113
+ def infer_account
114
+ parser = @script.parser(script_name)
101
115
  return unless parser.exist?
102
116
 
103
- cmd = %(#{parser} "#{@ticket}" "#{@description}" #{@tags[1..-1].map(&:inspect).join(' ')})
117
+ @script.deprecate(parser)
118
+
119
+ cmd = %(#{parser} "#{@ticket}" "#{@description}" #{script_args})
104
120
  `#{cmd}`.chomp # maybe only execute if parser is in correct dir?
105
121
  end
106
122
 
123
+ # this method will be removed in 0.7, when support for billable is removed
107
124
  def infer_billable
108
125
  script = @script.billable
126
+ return BILLABLE unless script.exist?
127
+
128
+ @script.deprecate(script)
129
+
130
+ `#{script} #{@account}`.chomp == 'true' ? BILLABLE : NON_BILLABLE
131
+ end
132
+
133
+ def infer_account_and_billable
134
+ script = @script.inferer(script_name)
135
+
136
+ cmd = %(#{script} "#{@ticket}" "#{@description}" #{script_args})
109
137
 
110
- return 1 unless script.exist?
138
+ account, billable = `#{cmd}`.chomp.split
111
139
 
112
- `#{script} #{@account}`.chomp == 'true' ? 1 : 0
140
+ [account, (billable == 'true' ? BILLABLE : NON_BILLABLE)]
113
141
  end
114
142
  end
115
143
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'naught'
4
+ require 'pathname'
5
+
6
+ NullPathname = Naught.build do |config|
7
+ config.impersonate Pathname
8
+ config.predicates_return false
9
+ end
@@ -16,5 +16,27 @@ module Ptimelog
16
16
  def billable
17
17
  @config_dir.join('billable').expand_path
18
18
  end
19
+
20
+ def inferer(name)
21
+ return NullPathname.new if name.to_s.empty?
22
+ raise if name =~ %r{[\\/]} # prevent relavtive paths, stupidly, FIXME: really check FS
23
+
24
+ @config_dir.join('inferers').join(name).expand_path
25
+ end
26
+
27
+ include DeprecationWarning
28
+
29
+ def deprecate_message(_)
30
+ <<~MESSAGE
31
+ Please move the parser- and billable-scripts to an inferer-script.
32
+ Support for the previous scripts in parsers/* and billable will
33
+ be dropped in 0.7.
34
+
35
+ MESSAGE
36
+ end
37
+
38
+ def deprecate_header(script_fn)
39
+ "DEPRECATION NOTICE: #{script_fn} is deprecated"
40
+ end
19
41
  end
20
42
  end
@@ -1,6 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Version
3
+ # the version, following semver
4
+ #
5
+ # Someone wanted to have documentation, so here goes...
6
+ #
7
+ # Please note that the version-string is not frozen. Although it of course is,
8
+ # because all strings in this file are frozen. That's what the magic comment
9
+ # at the top of the file does. :gasp:
10
+ #
11
+ # What else? Yeah, the VERSION-constant is part of the module Ptimelog because
12
+ # that is what is described here.
13
+ #
14
+ # So, I truly hope you are happy now, that I documented this file properly. For
15
+ # any remaining questions, please open an issue or even better a pull-request
16
+ # with an improvement. Keep in mind that this is also covered by rspec so I
17
+ # expect (pun intended) 100% test-coverage for any additional code.
4
18
  module Ptimelog
5
- VERSION = '0.5.3'
19
+ VERSION = '0.6.0'
6
20
  end
data/lib/ptimelog.rb CHANGED
@@ -6,8 +6,10 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
6
6
  module Ptimelog
7
7
  autoload :App, 'ptimelog/app'
8
8
  autoload :Configuration, 'ptimelog/configuration'
9
+ autoload :DeprecationWarning, 'ptimelog/deprecation_warning'
9
10
  autoload :Entry, 'ptimelog/entry'
10
11
  autoload :NamedDate, 'ptimelog/named_date'
12
+ autoload :NullPathname, 'ptimelog/null_pathname'
11
13
  autoload :Script, 'ptimelog/script'
12
14
  autoload :Timelog, 'ptimelog/timelog'
13
15
  autoload :VERSION, 'ptimelog/version'
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.add_dependency 'naught'
26
+
25
27
  spec.add_development_dependency 'bundler'
26
28
  spec.add_development_dependency 'overcommit', '~> 0.45'
27
29
  spec.add_development_dependency 'pry', '~> 0.12'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ptimelog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.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: 2019-08-15 00:00:00.000000000 Z
11
+ date: 2020-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: naught
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -138,8 +152,10 @@ files:
138
152
  - lib/ptimelog/command/show.rb
139
153
  - lib/ptimelog/command/upload.rb
140
154
  - lib/ptimelog/configuration.rb
155
+ - lib/ptimelog/deprecation_warning.rb
141
156
  - lib/ptimelog/entry.rb
142
157
  - lib/ptimelog/named_date.rb
158
+ - lib/ptimelog/null_pathname.rb
143
159
  - lib/ptimelog/script.rb
144
160
  - lib/ptimelog/timelog.rb
145
161
  - lib/ptimelog/version.rb