ptimelog 0.10.0 → 0.12.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.
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'time'
5
+ require 'yaml'
6
+
7
+ module Ptimelog
8
+ # Extract entries from the time-sessions Operon tracks on its tasks
9
+ class Operon # rubocop:disable Metrics/ClassLength
10
+ # Operon documents its own task-syntax as examples, and the archive is history
11
+ SKIP_PATHS = ['Operon/Docs', 'archive'].freeze
12
+
13
+ FIELD_RE = /\{\{(\w+)::\s*(.*?)\}\}/
14
+ TASK_RE = /^\s*-\s\[( |x|X)\]\s/
15
+ RANGE_RE = %r{
16
+ \A(?<start>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?)/
17
+ (?<stop>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?)\z
18
+ }x
19
+
20
+ # A config naming only one key must not lose the other
21
+ # TODO: determine if this can be done in the Ptimelog::Configuration
22
+ def self.custom_keys
23
+ Ptimelog::Configuration::CONFIGURATION_DEFAULTS['operon_custom_keys']
24
+ .merge(Ptimelog::Configuration.instance['operon_custom_keys'].to_h)
25
+ end
26
+
27
+ def initialize(day)
28
+ @day = day
29
+ @configuration = Ptimelog::Configuration.instance
30
+ end
31
+
32
+ # A missing vault would silently look like a day without any tracked time
33
+ class VaultNotFound < Ptimelog::Error
34
+ def initialize(path)
35
+ super(<<~MSG)
36
+ Could not find your Obsidian vault at #{path}
37
+
38
+ Please check 'obsidian_vault' in your ptimelog-config. It should
39
+ point to the folder which contains your '.obsidian'-directory.
40
+ MSG
41
+ end
42
+ end
43
+
44
+ # A session belongs to the day it started on. Plans and running timers are no time yet
45
+ def entries
46
+ tasks.flat_map { |task| entries_of(task) }
47
+ .sort_by(&:start_time)
48
+ end
49
+
50
+ # What a new entry would continue from: a running timer, the last session, the start of the day
51
+ def previous_entry
52
+ start = running_timer || entries.last&.finish_time || @configuration['operon_start_time'] || '08:00'
53
+
54
+ Ptimelog::Entry.new.tap do |entry|
55
+ entry.date = @day
56
+ entry.description = 'start **'
57
+ entry.start_time = start
58
+ entry.finish_time = start
59
+ end
60
+ end
61
+
62
+ # An entry can come from any note of the vault, so there is no one file to point at
63
+ def file = NullPathname.new
64
+
65
+ private
66
+
67
+ def vault
68
+ @vault ||= begin
69
+ path = @configuration['obsidian_vault']
70
+ raise VaultNotFound, path unless File.directory?(path)
71
+
72
+ path
73
+ end
74
+ end
75
+
76
+ def markdown_files
77
+ Dir.glob(vault.join('**/*.md')).reject { |fn| ignored?(fn) }
78
+ end
79
+
80
+ def ignored?(fn)
81
+ relative = fn.delete_prefix("#{vault}/")
82
+
83
+ SKIP_PATHS.any? { |path| relative.start_with?("#{path}/") }
84
+ end
85
+
86
+ # Every task of the vault, an inline one on its line, a file task in its frontmatter
87
+ def tasks
88
+ markdown_files.flat_map do |fn|
89
+ frontmatter, body = split_frontmatter(File.read(fn, encoding: 'UTF-8'))
90
+
91
+ file_tasks(frontmatter, fn) + inline_tasks(body)
92
+ end
93
+ end
94
+
95
+ def file_tasks(frontmatter, fn)
96
+ return [] unless frontmatter.is_a?(Hash)
97
+
98
+ [{ fields: frontmatter, description: File.basename(fn, '.md') }]
99
+ end
100
+
101
+ def inline_tasks(body)
102
+ body.each_line.filter_map do |line|
103
+ next unless line.match?(TASK_RE)
104
+
105
+ { fields: fields_of(line), description: description_of(line) }
106
+ end
107
+ end
108
+
109
+ def fields_of(line) = line.scan(FIELD_RE).to_h.transform_values(&:strip)
110
+
111
+ def description_of(line)
112
+ line.sub(TASK_RE, '').sub(/\s*\{\{.*\}\}\s*\z/m, '').strip
113
+ end
114
+
115
+ # A file task keeps its fields in frontmatter, an inline task carries them on its line
116
+ def split_frontmatter(text)
117
+ return [nil, text] unless text.start_with?('---')
118
+
119
+ close = text.index("\n---", 3)
120
+ return [nil, text] unless close
121
+
122
+ [YAML.safe_load(text[4...close], permitted_classes: [Date, Time], aliases: true), text[(close + 4)..]]
123
+ rescue Psych::Exception
124
+ [nil, text]
125
+ end
126
+
127
+ def entries_of(task)
128
+ session_list(task[:fields]['trackers']).filter_map do |session|
129
+ next unless on_day?(session[:start])
130
+
131
+ entry_for(session, task)
132
+ end
133
+ end
134
+
135
+ # Malformed ranges are dropped, one broken note must not sink a whole day
136
+ def session_list(sessions)
137
+ list = sessions.is_a?(String) ? sessions.split('; ') : Array(sessions)
138
+
139
+ list.filter_map { |session| RANGE_RE.match(session.to_s.strip) }
140
+ end
141
+
142
+ # A running timer is no session yet, but it says where the work stopped
143
+ def running_timer
144
+ started = tasks.filter_map { |task| task[:fields]['activeTracker'] }.find { |at| on_day?(at) }
145
+
146
+ started && Time.parse(started).strftime('%R')
147
+ end
148
+
149
+ def on_day?(datetime)
150
+ Time.parse(datetime).strftime('%F') == @day
151
+ end
152
+
153
+ def entry_for(session, task) # rubocop:disable Metrics/AbcSize
154
+ fields = task[:fields]
155
+
156
+ Ptimelog::Entry.new.tap do |entry|
157
+ entry.date = @day
158
+ entry.ticket = fields[custom_key('ticket')]
159
+ entry.description = task[:description]
160
+ entry.tags = fields[custom_key('inferer')]
161
+ entry.start_time = Time.parse(session[:start]).strftime('%R')
162
+ entry.finish_time = Time.parse(session[:stop]).strftime('%R')
163
+
164
+ entry.infer_ptime_settings
165
+ end
166
+ end
167
+
168
+ def custom_key(name) = self.class.custom_keys.fetch(name)
169
+ end
170
+ end
@@ -10,7 +10,7 @@ module Ptimelog
10
10
 
11
11
  def inferer(name)
12
12
  return NullPathname.new if name.to_s.empty?
13
- raise if name =~ %r{[\\/]} # prevent relavtive paths, stupidly, FIXME: really check FS
13
+ raise if %r{[\\/]}.match?(name) # prevent relavtive paths, stupidly, FIXME: really check FS
14
14
 
15
15
  @config_dir.join('inferers').join(name).expand_path
16
16
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'singleton'
3
4
  require 'pathname'
4
5
 
5
6
  module Ptimelog
@@ -13,12 +14,16 @@ module Ptimelog
13
14
  end
14
15
 
15
16
  def timelog_txt
16
- Pathname.new(Configuration.instance[:timelog]).expand_path
17
+ Pathname.new(Configuration.instance[:timelog_txt]).expand_path
17
18
  end
18
19
 
19
20
  def previous_entry
20
- lines = timelog_txt.readlines.last(2)
21
- last_line = lines.map(&:chomp).delete_if(&:empty?).last
21
+ lines = timelog_txt.readlines.last(10)
22
+
23
+ last_line = lines.map(&:chomp).delete_if do |line|
24
+ line.empty? || line.end_with?('**')
25
+ end.last
26
+
22
27
  last_entry = instance.tokenize(last_line)
23
28
 
24
29
  Entry.from_timelog(last_entry)
@@ -41,6 +46,15 @@ module Ptimelog
41
46
  timelog_txt.read
42
47
  end
43
48
 
49
+ # TODO: spec and activate this code
50
+ # def add(_entry)
51
+ # @new_lines = []
52
+ # add_empty_line if @timelog.previous_entry.date == yesterday
53
+ # add_entry(*parse_task(task))
54
+ #
55
+ # save_file
56
+ # end
57
+
44
58
  def parse(data)
45
59
  data.split("\n")
46
60
  .map { |line| tokenize(line) }
@@ -58,5 +72,44 @@ module Ptimelog
58
72
  regexp = /^#{re_date} #{re_time}: #{re_tick}?#{re_desc}#{re_tags}?$/
59
73
  line.match(regexp)
60
74
  end
75
+
76
+ # TODO: spec and maybe activate this code. this might be covered by the "add"-command already.
77
+ # def parse_task(line)
78
+ # matches = line.match('(?<time>\d{1,2}:\d{2} )?(?<offset>[+-]\d+ )?(?<task>.*)')
79
+ # formatted_time = if matches[:time]
80
+ # Time.parse(matches[:time])
81
+ # else
82
+ # Time.now
83
+ # end
84
+ # .localtime
85
+ # .then { |time| time + (matches[:offset].to_i * 60) }
86
+ # .strftime('%F %R')
87
+ #
88
+ # [formatted_time, matches[:task]]
89
+ # end
90
+
91
+ # TODO: spec and activate this code.
92
+ # def add_entry(date_time, task)
93
+ # @new_lines << "#{date_time}: #{task}"
94
+ # end
95
+
96
+ # TODO: spec and activate this code.
97
+ # def add_empty_line
98
+ # @new_lines << ''
99
+ # end
100
+
101
+ # TODO: spec and activate this code.
102
+ # def save_file
103
+ # @timelog.timelog_txt.open('a') do |log|
104
+ # @new_lines.each do |line|
105
+ # log << "#{line}\n"
106
+ # end
107
+ # end
108
+ # end
109
+
110
+ # TODO: spec and activate this code.
111
+ # def yesterday
112
+ # NamedDate.new.named_date('yesterday')
113
+ # end
61
114
  end
62
115
  end
@@ -15,6 +15,14 @@
15
15
  # any remaining questions, please open an issue or even better a pull-request
16
16
  # with an improvement. Keep in mind that this is also covered by rspec so I
17
17
  # expect (pun intended) 100% test-coverage for any additional code.
18
+ #
19
+ # Without much preparation came the addition of cmdparse to this gem. While
20
+ # adding it, it became apparent that a duplication between the gemspec and the
21
+ # main executable may exist. In order to avoid this dreadfully duplicated
22
+ # description, a constant for this has been added to this module. So, the
23
+ # correct subtitle of this documentation-block would be "and a Banner not named
24
+ # Bruce."
18
25
  module Ptimelog
19
- VERSION = '0.10.0'
26
+ VERSION = '0.12.0'
27
+ BANNER = 'Move time-entries from gTimelog or Obsidian to PuzzleTime'
20
28
  end
data/lib/ptimelog.rb CHANGED
@@ -6,20 +6,31 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
6
6
  module Ptimelog
7
7
  autoload :App, 'ptimelog/app'
8
8
  autoload :Configuration, 'ptimelog/configuration'
9
- autoload :Day, 'ptimelog/day'
9
+ autoload :DataSource, 'ptimelog/data_source'
10
10
  autoload :DeprecationWarning, 'ptimelog/deprecation_warning'
11
11
  autoload :Entry, 'ptimelog/entry'
12
+ autoload :Error, 'ptimelog/error'
13
+ autoload :Joiner, 'ptimelog/joiner'
12
14
  autoload :NamedDate, 'ptimelog/named_date'
13
15
  autoload :NullPathname, 'ptimelog/null_pathname'
14
16
  autoload :Script, 'ptimelog/script'
15
- autoload :Timelog, 'ptimelog/timelog'
16
17
  autoload :VERSION, 'ptimelog/version'
17
18
 
19
+ # datasources
20
+
21
+ # obsidian
22
+ autoload :Operon, 'ptimelog/operon'
23
+
24
+ # timelog.txt
25
+ autoload :Day, 'ptimelog/day'
26
+ autoload :Timelog, 'ptimelog/timelog'
27
+
18
28
  # Collection of commands available at the CLI
19
29
  module Command
20
30
  autoload :Add, 'ptimelog/command/add'
21
- autoload :Base, 'ptimelog/command/base'
31
+ autoload :Confirm, 'ptimelog/command/confirm'
22
32
  autoload :Edit, 'ptimelog/command/edit'
33
+ autoload :Info, 'ptimelog/command/info'
23
34
  autoload :Show, 'ptimelog/command/show'
24
35
  autoload :Upload, 'ptimelog/command/upload'
25
36
  autoload :Version, 'ptimelog/command/version'
data/opencode.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "agent": {
4
+ "researcher": {
5
+ "permission": {
6
+ "edit": "deny",
7
+ "skill": "deny",
8
+ "question": "allow",
9
+ }
10
+ },
11
+ "assistant": {
12
+ "permission": {
13
+ "bash": {
14
+ "*": "ask",
15
+ "rspec*": "allow",
16
+ "rubocop*": "allow",
17
+ "rake*": "allow",
18
+ "git status*": "allow",
19
+ "git diff*": "allow",
20
+ "git log*": "allow",
21
+ "git show*": "allow",
22
+ "git add --intent-to-add*": "allow",
23
+ "git add*": "ask",
24
+ "git commit*": "ask",
25
+ "git push*": "deny",
26
+ "ls*": "allow",
27
+ "tail *": "allow",
28
+ "head *": "allow",
29
+ "grep*": "allow",
30
+ "cat*": "allow",
31
+ "pwd": "allow"
32
+ },
33
+ }
34
+ }
35
+ }
36
+ }
37
+
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ptimelog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Viehweger
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2021-01-27 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: cmdparse
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: naught
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +37,20 @@ dependencies:
24
37
  - - ">="
25
38
  - !ruby/object:Gem::Version
26
39
  version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
27
54
  - !ruby/object:Gem::Dependency
28
55
  name: bundler
29
56
  requirement: !ruby/object:Gem::Requirement
@@ -42,87 +69,156 @@ dependencies:
42
69
  name: overcommit
43
70
  requirement: !ruby/object:Gem::Requirement
44
71
  requirements:
45
- - - "~>"
72
+ - - ">="
46
73
  - !ruby/object:Gem::Version
47
- version: '0.45'
74
+ version: '0'
48
75
  type: :development
49
76
  prerelease: false
50
77
  version_requirements: !ruby/object:Gem::Requirement
51
78
  requirements:
52
- - - "~>"
79
+ - - ">="
53
80
  - !ruby/object:Gem::Version
54
- version: '0.45'
81
+ version: '0'
55
82
  - !ruby/object:Gem::Dependency
56
83
  name: pry
57
84
  requirement: !ruby/object:Gem::Requirement
58
85
  requirements:
59
- - - "~>"
86
+ - - ">="
60
87
  - !ruby/object:Gem::Version
61
- version: '0.12'
88
+ version: '0'
62
89
  type: :development
63
90
  prerelease: false
64
91
  version_requirements: !ruby/object:Gem::Requirement
65
92
  requirements:
66
- - - "~>"
93
+ - - ">="
67
94
  - !ruby/object:Gem::Version
68
- version: '0.12'
95
+ version: '0'
69
96
  - !ruby/object:Gem::Dependency
70
97
  name: rake
71
98
  requirement: !ruby/object:Gem::Requirement
72
99
  requirements:
73
100
  - - ">="
74
101
  - !ruby/object:Gem::Version
75
- version: 12.3.3
102
+ version: '0'
76
103
  type: :development
77
104
  prerelease: false
78
105
  version_requirements: !ruby/object:Gem::Requirement
79
106
  requirements:
80
107
  - - ">="
81
108
  - !ruby/object:Gem::Version
82
- version: 12.3.3
109
+ version: '0'
83
110
  - !ruby/object:Gem::Dependency
84
111
  name: rspec
85
112
  requirement: !ruby/object:Gem::Requirement
86
113
  requirements:
87
- - - "~>"
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rspec-collection_matchers
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
88
129
  - !ruby/object:Gem::Version
89
- version: '3.0'
130
+ version: '0'
90
131
  type: :development
91
132
  prerelease: false
92
133
  version_requirements: !ruby/object:Gem::Requirement
93
134
  requirements:
94
- - - "~>"
135
+ - - ">="
95
136
  - !ruby/object:Gem::Version
96
- version: '3.0'
137
+ version: '0'
97
138
  - !ruby/object:Gem::Dependency
98
139
  name: rubocop
99
140
  requirement: !ruby/object:Gem::Requirement
100
141
  requirements:
101
- - - "~>"
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: rubocop-packaging
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
102
157
  - !ruby/object:Gem::Version
103
- version: '0.50'
158
+ version: '0'
104
159
  type: :development
105
160
  prerelease: false
106
161
  version_requirements: !ruby/object:Gem::Requirement
107
162
  requirements:
108
- - - "~>"
163
+ - - ">="
109
164
  - !ruby/object:Gem::Version
110
- version: '0.50'
165
+ version: '0'
166
+ - !ruby/object:Gem::Dependency
167
+ name: rubocop-performance
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ - !ruby/object:Gem::Dependency
181
+ name: rubocop-rake
182
+ requirement: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ type: :development
188
+ prerelease: false
189
+ version_requirements: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ - !ruby/object:Gem::Dependency
195
+ name: rubocop-rspec
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ type: :development
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
111
208
  - !ruby/object:Gem::Dependency
112
209
  name: timecop
113
210
  requirement: !ruby/object:Gem::Requirement
114
211
  requirements:
115
- - - "~>"
212
+ - - ">="
116
213
  - !ruby/object:Gem::Version
117
- version: '0.9'
214
+ version: '0'
118
215
  type: :development
119
216
  prerelease: false
120
217
  version_requirements: !ruby/object:Gem::Requirement
121
218
  requirements:
122
- - - "~>"
219
+ - - ">="
123
220
  - !ruby/object:Gem::Version
124
- version: '0.9'
125
- description:
221
+ version: '0'
126
222
  email:
127
223
  - kronn@kronn.de
128
224
  executables:
@@ -130,45 +226,39 @@ executables:
130
226
  extensions: []
131
227
  extra_rdoc_files: []
132
228
  files:
133
- - ".envrc"
134
- - ".gitignore"
135
- - ".overcommit.yml"
136
- - ".rspec"
137
- - ".rubocop.yml"
138
- - ".rubocop_todo.yml"
139
- - ".ruby-version"
140
- - ".tool-versions"
141
- - ".travis.yml"
229
+ - AGENTS.md
142
230
  - Gemfile
143
231
  - LICENSE.txt
232
+ - PLAN-ADD-COMMAND.md
144
233
  - README.md
145
234
  - Rakefile
146
- - bin/console
147
- - bin/setup
148
235
  - exe/ptimelog
149
236
  - lib/ptimelog.rb
150
- - lib/ptimelog/app.rb
151
237
  - lib/ptimelog/command/add.rb
152
- - lib/ptimelog/command/base.rb
238
+ - lib/ptimelog/command/confirm.rb
153
239
  - lib/ptimelog/command/edit.rb
240
+ - lib/ptimelog/command/info.rb
154
241
  - lib/ptimelog/command/show.rb
155
242
  - lib/ptimelog/command/upload.rb
156
- - lib/ptimelog/command/version.rb
157
243
  - lib/ptimelog/configuration.rb
244
+ - lib/ptimelog/data_source.rb
158
245
  - lib/ptimelog/day.rb
159
246
  - lib/ptimelog/deprecation_warning.rb
160
247
  - lib/ptimelog/entry.rb
248
+ - lib/ptimelog/error.rb
249
+ - lib/ptimelog/joiner.rb
161
250
  - lib/ptimelog/named_date.rb
162
251
  - lib/ptimelog/null_pathname.rb
252
+ - lib/ptimelog/operon.rb
163
253
  - lib/ptimelog/script.rb
164
254
  - lib/ptimelog/timelog.rb
165
255
  - lib/ptimelog/version.rb
166
- - ptimelog.gemspec
256
+ - opencode.json
167
257
  homepage: https://github.com/kronn/ptimelog
168
258
  licenses:
169
259
  - MIT
170
- metadata: {}
171
- post_install_message:
260
+ metadata:
261
+ rubygems_mfa_required: 'true'
172
262
  rdoc_options: []
173
263
  require_paths:
174
264
  - lib
@@ -176,15 +266,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
266
  requirements:
177
267
  - - ">="
178
268
  - !ruby/object:Gem::Version
179
- version: 2.7.0
269
+ version: '3.1'
180
270
  required_rubygems_version: !ruby/object:Gem::Requirement
181
271
  requirements:
182
272
  - - ">="
183
273
  - !ruby/object:Gem::Version
184
274
  version: '0'
185
275
  requirements: []
186
- rubygems_version: 3.1.4
187
- signing_key:
276
+ rubygems_version: 4.0.19
188
277
  specification_version: 4
189
- summary: Move time-entries from gTimelog to PuzzleTime
278
+ summary: Move time-entries from gTimelog or Obsidian to PuzzleTime
190
279
  test_files: []
data/.envrc DELETED
@@ -1 +0,0 @@
1
- PATH_add exe
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- /spec/state.txt