plansheet 0.12.0 → 0.12.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1c4e7e5e45d00a1218ac7346c60ba9182c7b73ac2761958c24ea8c8dcf15d9d
4
- data.tar.gz: 50cc492240c458e5bc13539f03203007b8922dcd2e00e5108d6f929c81419f2e
3
+ metadata.gz: 72d3799f5166153c1775c768f0734cf0e390adfd80893ef1ae1aa710b7888b0b
4
+ data.tar.gz: a18fd6eeb6a787438ddcdff1e6b0f25a17688f05a7bccff82495520517754b19
5
5
  SHA512:
6
- metadata.gz: 2fe3310c09dfe7d4e79172a476f3bcfc0a3ef6261757a4070a6f49d9857673524663ee97622db603acae911201d5f1acc9cdb65d7c30547ea0e3f4610dc5e0bf
7
- data.tar.gz: 58aee2a5ab4f95c114461a8ef614823b5c4e22e0961c792623d0720b033a40c1abbdf1d23887b7b5a38b4823138994116d3eb6b42f2675263d0825d567fee173
6
+ metadata.gz: c97c83093f8e70948a96392b5d02329128c5f1031a0645b35b9c42bebeabb82192207c3ff71671081792ef3d61e9277c219984f0f558a7b54c1fac632fa68445
7
+ data.tar.gz: 6723401a02c2086976e1002e4f8d08855f25726d1610fd9f4e593ae3ceac707c47bb6a1114ec1b40f707295c1c627fd5b72cce5ebe45f84b78b24d8304107bcf
data/.rubocop.yml CHANGED
@@ -1,5 +1,3 @@
1
- inherit_from: .rubocop_todo.yml
2
-
3
1
  AllCops:
4
2
  TargetRubyVersion: 2.6
5
3
  NewCops: enable
@@ -15,3 +13,9 @@ Style/StringLiteralsInInterpolation:
15
13
 
16
14
  Layout/LineLength:
17
15
  Max: 120
16
+
17
+ Metrics:
18
+ Enabled: false
19
+
20
+ Style/Documentation:
21
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plansheet (0.12.0)
4
+ plansheet (0.12.3)
5
5
  dc-kwalify (~> 1.0)
6
6
 
7
7
  GEM
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plansheet
4
+ class Project
5
+ def to_s
6
+ str = String.new
7
+ str << "# #{@name}\n"
8
+ STRING_PROPERTIES.each do |o|
9
+ str << stringify_string_property(o)
10
+ end
11
+ DATE_PROPERTIES.each do |o|
12
+ str << stringify_string_property(o)
13
+ end
14
+ ARRAY_PROPERTIES.each do |o|
15
+ str << stringify_array_property(o)
16
+ end
17
+ str
18
+ end
19
+
20
+ def stringify_string_property(prop)
21
+ if instance_variable_defined? "@#{prop}"
22
+ "#{prop}: #{instance_variable_get("@#{prop}")}\n"
23
+ else
24
+ ""
25
+ end
26
+ end
27
+
28
+ def stringify_date_property(prop)
29
+ if instance_variable_defined? "@#{prop}"
30
+ "#{prop}: #{instance_variable_get("@#{prop}")}\n"
31
+ else
32
+ ""
33
+ end
34
+ end
35
+
36
+ def stringify_array_property(prop)
37
+ str = String.new
38
+ if instance_variable_defined? "@#{prop}"
39
+ str << "#{prop}:\n"
40
+ instance_variable_get("@#{prop}").each do |t|
41
+ str << "- #{t}\n"
42
+ end
43
+ end
44
+ str
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "date"
5
+
6
+ module Plansheet
7
+ # Once there's some stability in plansheet and dc-kwalify, will pre-load this
8
+ # to save the later YAML.load
9
+ PROJECT_YAML_SCHEMA = <<~YAML
10
+ desc: dc-tasks project schema
11
+ type: seq
12
+ sequence:
13
+ - type: map
14
+ mapping:
15
+ "project":
16
+ desc: Project name
17
+ type: str
18
+ required: yes
19
+ "priority":
20
+ desc: Project priority
21
+ type: str
22
+ enum:
23
+ - high
24
+ - medium
25
+ - low
26
+ "status":
27
+ desc: The current status of the project
28
+ type: str
29
+ enum:
30
+ - wip # project is a work-in-progress
31
+ - ready # project has tasks, ready to go
32
+ - waiting # project in waiting on some external person/event
33
+ - blocked # project is blocked by another project, but otherwise ready/wip
34
+ - planning # project in planning phase (set manually)
35
+ - idea # project is little more than an idea
36
+ - dropped # project has been explicitly dropped, but
37
+ # want to keep around for reference, etc
38
+ - done # project is finished, but want to keep around
39
+ # for reference, etc.
40
+ "location":
41
+ desc: Location
42
+ type: str
43
+ "notes":
44
+ desc: Free-form notes string
45
+ type: str
46
+ "time_estimate":
47
+ desc: The estimated amount of time before a project is completed
48
+ type: str
49
+ "frequency":
50
+ desc: The amount of time before a recurring project moves to ready status again from when it was last done (WIP)
51
+ type: str
52
+ pattern: /\\d+[dwDW]/
53
+ "lead_time":
54
+ desc: The amount of time before a recurring project is "due" moved to ready where the project (sort of a deferral mechanism) (WIP)
55
+ type: str
56
+ pattern: /\\d+[dwDW]/
57
+ "due":
58
+ desc: Due date of the task
59
+ type: date
60
+ "defer":
61
+ desc: Defer task until this day
62
+ type: date
63
+ "completed_on":
64
+ desc: When the (non-recurring) project was completed
65
+ type: date
66
+ "created_on":
67
+ desc: When the project was created
68
+ type: date
69
+ "starts_on":
70
+ desc: For ICS (WIP)
71
+ type: date
72
+ "last_reviewed":
73
+ desc: When the project was last reviewed (WIP)
74
+ type: date
75
+ "last_done":
76
+ desc: When the recurring project was last completed (WIP)
77
+ type: date
78
+ "dependencies":
79
+ desc: The names of projects that need to be completed before this project can be started/completed
80
+ type: seq
81
+ sequence:
82
+ - type: str
83
+ "externals":
84
+ desc: List of external commitments, ie who else cares about project completion?
85
+ type: seq
86
+ sequence:
87
+ - type: str
88
+ "urls":
89
+ desc: List of URLs that may be pertinent
90
+ type: seq
91
+ sequence:
92
+ - type: str
93
+ "tasks":
94
+ desc: List of tasks to do
95
+ type: seq
96
+ sequence:
97
+ - type: str
98
+ "done":
99
+ desc: List of tasks which have been completed
100
+ type: seq
101
+ sequence:
102
+ - type: str
103
+ "tags":
104
+ desc: List of tags (WIP)
105
+ type: seq
106
+ sequence:
107
+ - type: str
108
+ YAML
109
+ PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
110
+
111
+ class ProjectYAMLFile
112
+ attr_reader :projects
113
+
114
+ def initialize(path)
115
+ @path = path
116
+ # TODO: this won't GC, inline validation instead?
117
+
118
+ # Handle pre-Ruby 3.1 psych versions (this is brittle)
119
+ @raw = if Psych::VERSION.split(".")[0].to_i >= 4
120
+ YAML.load_file(path, permitted_classes: [Date])
121
+ else
122
+ YAML.load_file(path)
123
+ end
124
+
125
+ validate_schema
126
+ @projects = @raw.map { |proj| Project.new proj }
127
+ end
128
+
129
+ def validate_schema
130
+ validator = Kwalify::Validator.new(Plansheet::PROJECT_SCHEMA)
131
+ errors = validator.validate(@raw)
132
+ # Check YAML validity
133
+ return unless errors && !errors.empty?
134
+
135
+ $stderr.write "Schema errors in #{@path}:\n"
136
+ errors.each { |err| puts "- [#{err.path}] #{err.message}" }
137
+ abort
138
+ end
139
+
140
+ def sort!
141
+ @projects.sort!
142
+ end
143
+
144
+ def yaml_dump
145
+ YAML.dump(@projects.map(&:to_h))
146
+ end
147
+ end
148
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "yaml"
4
4
  require "date"
5
+ require_relative "project/yaml"
6
+ require_relative "project/stringify"
5
7
 
6
8
  module Plansheet
7
9
  PROJECT_STATUS_PRIORITY = {
@@ -21,107 +23,6 @@ module Plansheet
21
23
  "low" => 3
22
24
  }.freeze
23
25
 
24
- # Once there's some stability in plansheet and dc-kwalify, will pre-load this
25
- # to save the later YAML.load
26
- PROJECT_YAML_SCHEMA = <<~YAML
27
- desc: dc-tasks project schema
28
- type: seq
29
- sequence:
30
- - type: map
31
- mapping:
32
- "project":
33
- desc: Project name
34
- type: str
35
- required: yes
36
- "priority":
37
- desc: Project priority
38
- type: str
39
- enum:
40
- - high
41
- - medium
42
- - low
43
- "status":
44
- desc: The current status of the project
45
- type: str
46
- enum:
47
- - wip # project is a work-in-progress
48
- - ready # project has tasks, ready to go
49
- - waiting # project in waiting on some external person/event
50
- - blocked # project is blocked by another project, but otherwise ready/wip
51
- - planning # project in planning phase (set manually)
52
- - idea # project is little more than an idea
53
- - dropped # project has been explicitly dropped, but
54
- # want to keep around for reference, etc
55
- - done # project is finished, but want to keep around
56
- # for reference, etc.
57
- "location":
58
- desc: Location
59
- type: str
60
- "notes":
61
- desc: Free-form notes string
62
- type: str
63
- "time_estimate":
64
- desc: The estimated amount of time before a project is completed
65
- type: str
66
- "frequency":
67
- desc: The amount of time before a recurring project moves to ready status again from when it was last done (WIP)
68
- type: str
69
- pattern: /\\d+[dwDW]/
70
- "lead_time":
71
- desc: The amount of time before a recurring project is "due" moved to ready where the project (sort of a deferral mechanism) (WIP)
72
- type: str
73
- pattern: /\\d+[dwDW]/
74
- "due":
75
- desc: Due date of the task
76
- type: date
77
- "defer":
78
- desc: Defer task until this day
79
- type: date
80
- "created_on":
81
- desc: When the project was created
82
- type: date
83
- "starts_on":
84
- desc: For ICS (WIP)
85
- type: date
86
- "last_reviewed":
87
- desc: When the project was last reviewed (WIP)
88
- type: date
89
- "last_done":
90
- desc: When the recurring project was last completed (WIP)
91
- type: date
92
- "dependencies":
93
- desc: The names of projects that need to be completed before this project can be started/completed
94
- type: seq
95
- sequence:
96
- - type: str
97
- "externals":
98
- desc: List of external commitments, ie who else cares about project completion?
99
- type: seq
100
- sequence:
101
- - type: str
102
- "urls":
103
- desc: List of URLs that may be pertinent
104
- type: seq
105
- sequence:
106
- - type: str
107
- "tasks":
108
- desc: List of tasks to do
109
- type: seq
110
- sequence:
111
- - type: str
112
- "done":
113
- desc: List of tasks which have been completed
114
- type: seq
115
- sequence:
116
- - type: str
117
- "tags":
118
- desc: List of tags (WIP)
119
- type: seq
120
- sequence:
121
- - type: str
122
- YAML
123
- PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
124
-
125
26
  def self.parse_date_duration(str)
126
27
  return Regexp.last_match(1).to_i if str.strip.match(/(\d+)[dD]/)
127
28
  return (Regexp.last_match(1).to_i * 7) if str.strip.match(/(\d+)[wW]/)
@@ -148,7 +49,7 @@ module Plansheet
148
49
  ].map { |x| "compare_#{x}".to_sym }.freeze
149
50
  # NOTE: The order of these affects presentation!
150
51
  STRING_PROPERTIES = %w[priority status location notes time_estimate frequency lead_time].freeze
151
- DATE_PROPERTIES = %w[due defer created_on starts_on last_done last_reviewed].freeze
52
+ DATE_PROPERTIES = %w[due defer completed_on created_on starts_on last_done last_reviewed].freeze
152
53
  ARRAY_PROPERTIES = %w[dependencies externals urls tasks done tags].freeze
153
54
 
154
55
  ALL_PROPERTIES = STRING_PROPERTIES + DATE_PROPERTIES + ARRAY_PROPERTIES
@@ -240,8 +141,8 @@ module Plansheet
240
141
  def status
241
142
  return @status if @status
242
143
  return recurring_status if recurring?
243
- return task_based_status if (@tasks || @done)
244
- # TODO: return done if done count is positive...
144
+ return task_based_status if @tasks || @done
145
+ return "done" if @completed_on && @tasks.nil?
245
146
 
246
147
  "idea"
247
148
  end
@@ -260,18 +161,19 @@ module Plansheet
260
161
 
261
162
  def recurring_status
262
163
  # add frequency to last_done
263
- unless @last_done
264
- # This recurring project is being done for the first time
265
- task_based_status
266
- else
164
+ if @last_done
267
165
  # This project has been done once before
268
166
  subsequent_recurring_status
167
+ else
168
+ # This recurring project is being done for the first time
169
+ task_based_status
269
170
  end
270
171
  end
271
172
 
272
173
  def subsequent_recurring_status
273
174
  return "done" if @lead_time && defer > Date.today
274
175
  return "done" if due > Date.today
176
+
275
177
  task_based_status
276
178
  end
277
179
 
@@ -284,6 +186,7 @@ module Plansheet
284
186
  def due
285
187
  return @due if @due
286
188
  return recurring_due_date if recurring?
189
+
287
190
  nil
288
191
  end
289
192
 
@@ -298,6 +201,7 @@ module Plansheet
298
201
  def defer
299
202
  return @defer if @defer
300
203
  return lead_time_deferral if @lead_time && due
204
+
301
205
  nil
302
206
  end
303
207
 
@@ -314,48 +218,6 @@ module Plansheet
314
218
  status == "dropped" || status == "done"
315
219
  end
316
220
 
317
- def to_s
318
- str = String.new
319
- str << "# #{@name}\n"
320
- STRING_PROPERTIES.each do |o|
321
- str << stringify_string_property(o)
322
- end
323
- DATE_PROPERTIES.each do |o|
324
- str << stringify_string_property(o)
325
- end
326
- ARRAY_PROPERTIES.each do |o|
327
- str << stringify_array_property(o)
328
- end
329
- str
330
- end
331
-
332
- def stringify_string_property(prop)
333
- if instance_variable_defined? "@#{prop}"
334
- "#{prop}: #{instance_variable_get("@#{prop}")}\n"
335
- else
336
- ""
337
- end
338
- end
339
-
340
- def stringify_date_property(prop)
341
- if instance_variable_defined? "@#{prop}"
342
- "#{prop}: #{instance_variable_get("@#{prop}")}\n"
343
- else
344
- ""
345
- end
346
- end
347
-
348
- def stringify_array_property(prop)
349
- str = String.new
350
- if instance_variable_defined? "@#{prop}"
351
- str << "#{prop}:\n"
352
- instance_variable_get("@#{prop}").each do |t|
353
- str << "- #{t}\n"
354
- end
355
- end
356
- str
357
- end
358
-
359
221
  def to_h
360
222
  h = { "project" => @name }
361
223
  ALL_PROPERTIES.each do |prop|
@@ -366,42 +228,4 @@ module Plansheet
366
228
  h
367
229
  end
368
230
  end
369
-
370
- class ProjectYAMLFile
371
- attr_reader :projects
372
-
373
- def initialize(path)
374
- @path = path
375
- # TODO: this won't GC, inline validation instead?
376
-
377
- # Handle pre-Ruby 3.1 psych versions (this is brittle)
378
- @raw = if Psych::VERSION.split(".")[0].to_i >= 4
379
- YAML.load_file(path, permitted_classes: [Date])
380
- else
381
- YAML.load_file(path)
382
- end
383
-
384
- validate_schema
385
- @projects = @raw.map { |proj| Project.new proj }
386
- end
387
-
388
- def validate_schema
389
- validator = Kwalify::Validator.new(Plansheet::PROJECT_SCHEMA)
390
- errors = validator.validate(@raw)
391
- # Check YAML validity
392
- return unless errors && !errors.empty?
393
-
394
- $stderr.write "Schema errors in #{@path}:\n"
395
- errors.each { |err| puts "- [#{err.path}] #{err.message}" }
396
- abort
397
- end
398
-
399
- def sort!
400
- @projects.sort!
401
- end
402
-
403
- def yaml_dump
404
- YAML.dump(@projects.map(&:to_h))
405
- end
406
- end
407
231
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plansheet
4
- VERSION = "0.12.0"
4
+ VERSION = "0.12.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plansheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Crosby
@@ -33,7 +33,6 @@ extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - ".rubocop.yml"
36
- - ".rubocop_todo.yml"
37
36
  - CODE_OF_CONDUCT.md
38
37
  - Gemfile
39
38
  - Gemfile.lock
@@ -45,6 +44,8 @@ files:
45
44
  - exe/plansheet
46
45
  - lib/plansheet.rb
47
46
  - lib/plansheet/project.rb
47
+ - lib/plansheet/project/stringify.rb
48
+ - lib/plansheet/project/yaml.rb
48
49
  - lib/plansheet/sheet.rb
49
50
  - lib/plansheet/version.rb
50
51
  homepage: https://dafyddcrosby.com
data/.rubocop_todo.yml DELETED
@@ -1,35 +0,0 @@
1
- # This configuration was generated by
2
- # `rubocop --auto-gen-config`
3
- # on 2022-06-04 17:25:54 UTC using RuboCop version 1.29.1.
4
- # The point is for the user to remove these configuration records
5
- # one by one as the offenses are removed from the code base.
6
- # Note that changes in the inspected code, or installation of new
7
- # versions of RuboCop, may require this file to be generated again.
8
-
9
- # Offense count: 1
10
- # Configuration parameters: CountComments, CountAsOne.
11
- Metrics/ClassLength:
12
- Enabled: false
13
-
14
- # Offense count: 1
15
- # Configuration parameters: IgnoredMethods.
16
- Metrics/CyclomaticComplexity:
17
- Enabled: false
18
-
19
- # Offense count: 2
20
- # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
21
- Metrics/MethodLength:
22
- Enabled: false
23
-
24
- # Offense count: 1
25
- # Configuration parameters: IgnoredMethods.
26
- Metrics/PerceivedComplexity:
27
- Enabled: false
28
-
29
- # Offense count: 2
30
- # Configuration parameters: AllowedConstants.
31
- Style/Documentation:
32
- Exclude:
33
- - 'test/**/*'
34
- - 'lib/plansheet.rb'
35
- - 'lib/plansheet/project.rb'