plansheet 0.7.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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +13 -4
- data/Gemfile +5 -0
- data/Gemfile.lock +42 -1
- data/Guardfile +9 -0
- data/exe/plansheet +8 -1
- data/lib/plansheet/project.rb +214 -22
- data/lib/plansheet/sheet.rb +2 -2
- data/lib/plansheet/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d1c4e7e5e45d00a1218ac7346c60ba9182c7b73ac2761958c24ea8c8dcf15d9d
|
|
4
|
+
data.tar.gz: 50cc492240c458e5bc13539f03203007b8922dcd2e00e5108d6f929c81419f2e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2fe3310c09dfe7d4e79172a476f3bcfc0a3ef6261757a4070a6f49d9857673524663ee97622db603acae911201d5f1acc9cdb65d7c30547ea0e3f4610dc5e0bf
|
|
7
|
+
data.tar.gz: 58aee2a5ab4f95c114461a8ef614823b5c4e22e0961c792623d0720b033a40c1abbdf1d23887b7b5a38b4823138994116d3eb6b42f2675263d0825d567fee173
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2022-06-
|
|
3
|
+
# on 2022-06-04 17:25:54 UTC using RuboCop version 1.29.1.
|
|
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: 1
|
|
10
|
+
# Configuration parameters: CountComments, CountAsOne.
|
|
11
|
+
Metrics/ClassLength:
|
|
12
|
+
Enabled: false
|
|
13
|
+
|
|
9
14
|
# Offense count: 1
|
|
10
15
|
# Configuration parameters: IgnoredMethods.
|
|
11
16
|
Metrics/CyclomaticComplexity:
|
|
12
|
-
|
|
17
|
+
Enabled: false
|
|
18
|
+
|
|
19
|
+
# Offense count: 2
|
|
20
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
21
|
+
Metrics/MethodLength:
|
|
22
|
+
Enabled: false
|
|
13
23
|
|
|
14
24
|
# Offense count: 1
|
|
15
25
|
# Configuration parameters: IgnoredMethods.
|
|
16
26
|
Metrics/PerceivedComplexity:
|
|
17
|
-
|
|
27
|
+
Enabled: false
|
|
18
28
|
|
|
19
29
|
# Offense count: 2
|
|
20
30
|
# Configuration parameters: AllowedConstants.
|
|
21
31
|
Style/Documentation:
|
|
22
32
|
Exclude:
|
|
23
|
-
- 'spec/**/*'
|
|
24
33
|
- 'test/**/*'
|
|
25
34
|
- 'lib/plansheet.rb'
|
|
26
35
|
- 'lib/plansheet/project.rb'
|
data/Gemfile
CHANGED
|
@@ -6,7 +6,12 @@ source "https://rubygems.org"
|
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
8
|
group :development, optional: true do
|
|
9
|
+
gem "guard", "~> 2.18"
|
|
10
|
+
gem "guard-minitest", "~> 2.4"
|
|
9
11
|
gem "minitest", "~> 5.0"
|
|
10
12
|
gem "rake", "~> 13.0"
|
|
13
|
+
|
|
11
14
|
gem "rubocop", "~> 1.21"
|
|
15
|
+
gem "rubocop-minitest"
|
|
16
|
+
gem "rubocop-rake"
|
|
12
17
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,20 +1,51 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
plansheet (0.
|
|
4
|
+
plansheet (0.12.0)
|
|
5
5
|
dc-kwalify (~> 1.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
ast (2.4.2)
|
|
11
|
+
coderay (1.1.3)
|
|
11
12
|
dc-kwalify (1.0.0)
|
|
13
|
+
ffi (1.15.5)
|
|
14
|
+
formatador (1.1.0)
|
|
15
|
+
guard (2.18.0)
|
|
16
|
+
formatador (>= 0.2.4)
|
|
17
|
+
listen (>= 2.7, < 4.0)
|
|
18
|
+
lumberjack (>= 1.0.12, < 2.0)
|
|
19
|
+
nenv (~> 0.1)
|
|
20
|
+
notiffany (~> 0.0)
|
|
21
|
+
pry (>= 0.13.0)
|
|
22
|
+
shellany (~> 0.0)
|
|
23
|
+
thor (>= 0.18.1)
|
|
24
|
+
guard-compat (1.2.1)
|
|
25
|
+
guard-minitest (2.4.6)
|
|
26
|
+
guard-compat (~> 1.2)
|
|
27
|
+
minitest (>= 3.0)
|
|
28
|
+
listen (3.7.1)
|
|
29
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
30
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
|
31
|
+
lumberjack (1.2.8)
|
|
32
|
+
method_source (1.0.0)
|
|
12
33
|
minitest (5.15.0)
|
|
34
|
+
nenv (0.3.0)
|
|
35
|
+
notiffany (0.1.3)
|
|
36
|
+
nenv (~> 0.1)
|
|
37
|
+
shellany (~> 0.0)
|
|
13
38
|
parallel (1.22.1)
|
|
14
39
|
parser (3.1.2.0)
|
|
15
40
|
ast (~> 2.4.1)
|
|
41
|
+
pry (0.14.1)
|
|
42
|
+
coderay (~> 1.1)
|
|
43
|
+
method_source (~> 1.0)
|
|
16
44
|
rainbow (3.1.1)
|
|
17
45
|
rake (13.0.6)
|
|
46
|
+
rb-fsevent (0.11.1)
|
|
47
|
+
rb-inotify (0.10.1)
|
|
48
|
+
ffi (~> 1.0)
|
|
18
49
|
regexp_parser (2.4.0)
|
|
19
50
|
rexml (3.2.5)
|
|
20
51
|
rubocop (1.29.1)
|
|
@@ -28,17 +59,27 @@ GEM
|
|
|
28
59
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
29
60
|
rubocop-ast (1.18.0)
|
|
30
61
|
parser (>= 3.1.1.0)
|
|
62
|
+
rubocop-minitest (0.20.0)
|
|
63
|
+
rubocop (>= 0.90, < 2.0)
|
|
64
|
+
rubocop-rake (0.6.0)
|
|
65
|
+
rubocop (~> 1.0)
|
|
31
66
|
ruby-progressbar (1.11.0)
|
|
67
|
+
shellany (0.0.1)
|
|
68
|
+
thor (1.2.1)
|
|
32
69
|
unicode-display_width (2.1.0)
|
|
33
70
|
|
|
34
71
|
PLATFORMS
|
|
35
72
|
x86_64-linux
|
|
36
73
|
|
|
37
74
|
DEPENDENCIES
|
|
75
|
+
guard (~> 2.18)
|
|
76
|
+
guard-minitest (~> 2.4)
|
|
38
77
|
minitest (~> 5.0)
|
|
39
78
|
plansheet!
|
|
40
79
|
rake (~> 13.0)
|
|
41
80
|
rubocop (~> 1.21)
|
|
81
|
+
rubocop-minitest
|
|
82
|
+
rubocop-rake
|
|
42
83
|
|
|
43
84
|
BUNDLED WITH
|
|
44
85
|
2.3.6
|
data/Guardfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
directories(%w[lib test].select { |d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist") })
|
|
4
|
+
|
|
5
|
+
guard :minitest do
|
|
6
|
+
watch(%r{^test/test_(.*)\.rb$}) { "test" }
|
|
7
|
+
watch(%r{^lib/plansheet/(.*)\.rb$}) { "test" }
|
|
8
|
+
watch(%r{^lib/plansheet\.rb$}) { "test" }
|
|
9
|
+
end
|
data/exe/plansheet
CHANGED
|
@@ -17,6 +17,10 @@ parser.on(
|
|
|
17
17
|
"--cli",
|
|
18
18
|
"CLI dump of projects (WIP)"
|
|
19
19
|
)
|
|
20
|
+
parser.on(
|
|
21
|
+
"--location_filter LOCATION",
|
|
22
|
+
"location filter for CLI dump (WIP)"
|
|
23
|
+
)
|
|
20
24
|
options = {}
|
|
21
25
|
parser.parse!(into: options)
|
|
22
26
|
|
|
@@ -32,7 +36,10 @@ elsif options[:sort]
|
|
|
32
36
|
Plansheet.resort_projects_in_dir config["projects_dir"]
|
|
33
37
|
elsif options[:cli]
|
|
34
38
|
project_arr = Plansheet.load_projects_dir config["projects_dir"]
|
|
35
|
-
project_arr.sort
|
|
39
|
+
project_arr.sort!
|
|
40
|
+
project_arr.delete_if { |x| x.status == "dropped" || x.status == "done" }
|
|
41
|
+
project_arr.select! { |x| x.location == options[:location_filter] } if options[:location_filter]
|
|
42
|
+
project_arr.each do |proj|
|
|
36
43
|
puts proj
|
|
37
44
|
puts "\n"
|
|
38
45
|
end
|
data/lib/plansheet/project.rb
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "yaml"
|
|
4
|
+
require "date"
|
|
4
5
|
|
|
5
6
|
module Plansheet
|
|
6
7
|
PROJECT_STATUS_PRIORITY = {
|
|
7
8
|
"wip" => 1,
|
|
8
9
|
"ready" => 2,
|
|
9
10
|
"blocked" => 3,
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
11
|
+
"waiting" => 4,
|
|
12
|
+
"planning" => 5,
|
|
13
|
+
"idea" => 6,
|
|
14
|
+
"dropped" => 7,
|
|
15
|
+
"done" => 8
|
|
14
16
|
}.freeze
|
|
15
17
|
|
|
16
18
|
PROJECT_PRIORITY = {
|
|
@@ -43,9 +45,10 @@ module Plansheet
|
|
|
43
45
|
type: str
|
|
44
46
|
enum:
|
|
45
47
|
- wip # project is a work-in-progress
|
|
46
|
-
- ready # project
|
|
47
|
-
-
|
|
48
|
-
-
|
|
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)
|
|
49
52
|
- idea # project is little more than an idea
|
|
50
53
|
- dropped # project has been explicitly dropped, but
|
|
51
54
|
# want to keep around for reference, etc
|
|
@@ -57,6 +60,40 @@ module Plansheet
|
|
|
57
60
|
"notes":
|
|
58
61
|
desc: Free-form notes string
|
|
59
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
|
|
60
97
|
"externals":
|
|
61
98
|
desc: List of external commitments, ie who else cares about project completion?
|
|
62
99
|
type: seq
|
|
@@ -77,9 +114,21 @@ module Plansheet
|
|
|
77
114
|
type: seq
|
|
78
115
|
sequence:
|
|
79
116
|
- type: str
|
|
117
|
+
"tags":
|
|
118
|
+
desc: List of tags (WIP)
|
|
119
|
+
type: seq
|
|
120
|
+
sequence:
|
|
121
|
+
- type: str
|
|
80
122
|
YAML
|
|
81
123
|
PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
|
|
82
124
|
|
|
125
|
+
def self.parse_date_duration(str)
|
|
126
|
+
return Regexp.last_match(1).to_i if str.strip.match(/(\d+)[dD]/)
|
|
127
|
+
return (Regexp.last_match(1).to_i * 7) if str.strip.match(/(\d+)[wW]/)
|
|
128
|
+
|
|
129
|
+
raise "Can't parse time duration string #{str}"
|
|
130
|
+
end
|
|
131
|
+
|
|
83
132
|
# The use of instance_variable_set/get probably seems a bit weird, but the
|
|
84
133
|
# intent is to avoid object allocation on non-existent project properties, as
|
|
85
134
|
# well as avoiding a bunch of copy-paste boilerplate when adding a new
|
|
@@ -89,11 +138,20 @@ module Plansheet
|
|
|
89
138
|
class Project
|
|
90
139
|
include Comparable
|
|
91
140
|
|
|
141
|
+
DEFAULT_COMPARISON_ORDER = %w[
|
|
142
|
+
completeness
|
|
143
|
+
dependency
|
|
144
|
+
priority
|
|
145
|
+
defer
|
|
146
|
+
due
|
|
147
|
+
status
|
|
148
|
+
].map { |x| "compare_#{x}".to_sym }.freeze
|
|
92
149
|
# NOTE: The order of these affects presentation!
|
|
93
|
-
STRING_PROPERTIES = %w[priority status location notes].freeze
|
|
94
|
-
|
|
150
|
+
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
|
|
152
|
+
ARRAY_PROPERTIES = %w[dependencies externals urls tasks done tags].freeze
|
|
95
153
|
|
|
96
|
-
ALL_PROPERTIES = STRING_PROPERTIES + ARRAY_PROPERTIES
|
|
154
|
+
ALL_PROPERTIES = STRING_PROPERTIES + DATE_PROPERTIES + ARRAY_PROPERTIES
|
|
97
155
|
|
|
98
156
|
attr_reader :name, *ALL_PROPERTIES
|
|
99
157
|
|
|
@@ -118,34 +176,153 @@ module Plansheet
|
|
|
118
176
|
end
|
|
119
177
|
|
|
120
178
|
def <=>(other)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
PROJECT_PRIORITY[@priority] <=> PROJECT_PRIORITY[other.priority]
|
|
179
|
+
ret_val = 0
|
|
180
|
+
DEFAULT_COMPARISON_ORDER.each do |method|
|
|
181
|
+
ret_val = send(method, other)
|
|
182
|
+
break if ret_val != 0
|
|
126
183
|
end
|
|
184
|
+
ret_val
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def compare_priority(other)
|
|
188
|
+
PROJECT_PRIORITY[@priority] <=> PROJECT_PRIORITY[other.priority]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def compare_status(other)
|
|
192
|
+
PROJECT_STATUS_PRIORITY[status] <=> PROJECT_STATUS_PRIORITY[other.status]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def compare_due(other)
|
|
196
|
+
# -1 is receiving object being older
|
|
197
|
+
|
|
198
|
+
# Handle nil
|
|
199
|
+
if @due.nil?
|
|
200
|
+
return 0 if other.due.nil?
|
|
201
|
+
|
|
202
|
+
return 1
|
|
203
|
+
elsif other.due.nil?
|
|
204
|
+
return -1
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
@due <=> other.due
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def compare_defer(other)
|
|
211
|
+
receiver = @defer.nil? || @defer < Date.today ? Date.today : @defer
|
|
212
|
+
comparison = other.defer.nil? || other.defer < Date.today ? Date.today : other.defer
|
|
213
|
+
receiver <=> comparison
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def compare_dependency(other)
|
|
217
|
+
return 0 if @dependencies.nil? && other.dependencies.nil?
|
|
218
|
+
|
|
219
|
+
if @dependencies.nil?
|
|
220
|
+
return -1 if other.dependencies.any? do |dep|
|
|
221
|
+
@name.downcase == dep.downcase
|
|
222
|
+
end
|
|
223
|
+
elsif @dependencies.any? do |dep|
|
|
224
|
+
other.name.downcase == dep.downcase
|
|
225
|
+
end
|
|
226
|
+
return 1
|
|
227
|
+
end
|
|
228
|
+
0
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Projects that are dropped or done are considered "complete", insofar as
|
|
232
|
+
# they are only kept around for later reference.
|
|
233
|
+
def compare_completeness(other)
|
|
234
|
+
return 0 if dropped_or_done? && other.dropped_or_done?
|
|
235
|
+
return 0 if !dropped_or_done? && !other.dropped_or_done?
|
|
236
|
+
|
|
237
|
+
dropped_or_done? ? 1 : -1
|
|
127
238
|
end
|
|
128
239
|
|
|
129
240
|
def status
|
|
130
241
|
return @status if @status
|
|
242
|
+
return recurring_status if recurring?
|
|
243
|
+
return task_based_status if (@tasks || @done)
|
|
244
|
+
# TODO: return done if done count is positive...
|
|
131
245
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
246
|
+
"idea"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def task_based_status
|
|
250
|
+
if @tasks&.count&.positive? && @done&.count&.positive?
|
|
251
|
+
"wip"
|
|
252
|
+
elsif @tasks&.count&.positive?
|
|
253
|
+
"ready"
|
|
254
|
+
elsif @done&.count&.positive?
|
|
255
|
+
"done"
|
|
138
256
|
else
|
|
139
257
|
"idea"
|
|
140
258
|
end
|
|
141
259
|
end
|
|
142
260
|
|
|
261
|
+
def recurring_status
|
|
262
|
+
# 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
|
|
267
|
+
# This project has been done once before
|
|
268
|
+
subsequent_recurring_status
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def subsequent_recurring_status
|
|
273
|
+
return "done" if @lead_time && defer > Date.today
|
|
274
|
+
return "done" if due > Date.today
|
|
275
|
+
task_based_status
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def process_recurring
|
|
279
|
+
# TODO: Tasks will be moved from done->tasks if recurring project is
|
|
280
|
+
# starting again
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Due date either explicit or recurring
|
|
284
|
+
def due
|
|
285
|
+
return @due if @due
|
|
286
|
+
return recurring_due_date if recurring?
|
|
287
|
+
nil
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def recurring_due_date
|
|
291
|
+
if @last_done
|
|
292
|
+
@last_done + Plansheet.parse_date_duration(@frequency)
|
|
293
|
+
else
|
|
294
|
+
Date.today
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def defer
|
|
299
|
+
return @defer if @defer
|
|
300
|
+
return lead_time_deferral if @lead_time && due
|
|
301
|
+
nil
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def lead_time_deferral
|
|
305
|
+
[(due - Plansheet.parse_date_duration(@lead_time)),
|
|
306
|
+
Date.today].max
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def recurring?
|
|
310
|
+
!@frequency.nil?
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def dropped_or_done?
|
|
314
|
+
status == "dropped" || status == "done"
|
|
315
|
+
end
|
|
316
|
+
|
|
143
317
|
def to_s
|
|
144
318
|
str = String.new
|
|
145
319
|
str << "# #{@name}\n"
|
|
146
320
|
STRING_PROPERTIES.each do |o|
|
|
147
321
|
str << stringify_string_property(o)
|
|
148
322
|
end
|
|
323
|
+
DATE_PROPERTIES.each do |o|
|
|
324
|
+
str << stringify_string_property(o)
|
|
325
|
+
end
|
|
149
326
|
ARRAY_PROPERTIES.each do |o|
|
|
150
327
|
str << stringify_array_property(o)
|
|
151
328
|
end
|
|
@@ -160,6 +337,14 @@ module Plansheet
|
|
|
160
337
|
end
|
|
161
338
|
end
|
|
162
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
|
+
|
|
163
348
|
def stringify_array_property(prop)
|
|
164
349
|
str = String.new
|
|
165
350
|
if instance_variable_defined? "@#{prop}"
|
|
@@ -188,7 +373,14 @@ module Plansheet
|
|
|
188
373
|
def initialize(path)
|
|
189
374
|
@path = path
|
|
190
375
|
# TODO: this won't GC, inline validation instead?
|
|
191
|
-
|
|
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
|
+
|
|
192
384
|
validate_schema
|
|
193
385
|
@projects = @raw.map { |proj| Project.new proj }
|
|
194
386
|
end
|
data/lib/plansheet/sheet.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Plansheet
|
|
|
10
10
|
projects_str = String.new
|
|
11
11
|
projects_str << sheet_header
|
|
12
12
|
|
|
13
|
-
sorted_arr.
|
|
13
|
+
sorted_arr.each do |p|
|
|
14
14
|
projects_str << project_minipage(p)
|
|
15
15
|
end
|
|
16
16
|
puts "Writing to #{output_file}"
|
|
@@ -32,7 +32,7 @@ module Plansheet
|
|
|
32
32
|
str = String.new
|
|
33
33
|
str << "\\begin{minipage}{4.5cm}\n"
|
|
34
34
|
str << project_header(proj)
|
|
35
|
-
proj
|
|
35
|
+
proj&.tasks&.each do |t|
|
|
36
36
|
str << "$\\square$ #{t} \\\\\n"
|
|
37
37
|
end
|
|
38
38
|
str << "\\end{minipage}\n"
|
data/lib/plansheet/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: plansheet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Crosby
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-06-
|
|
11
|
+
date: 2022-06-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dc-kwalify
|
|
@@ -37,6 +37,7 @@ files:
|
|
|
37
37
|
- CODE_OF_CONDUCT.md
|
|
38
38
|
- Gemfile
|
|
39
39
|
- Gemfile.lock
|
|
40
|
+
- Guardfile
|
|
40
41
|
- LICENSE.txt
|
|
41
42
|
- README.md
|
|
42
43
|
- Rakefile
|