plansheet 0.7.1 → 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: d9c1a116df170c31d73c29dce213b757743c0e49bbee8c86a47ce7ce09009730
4
- data.tar.gz: 2baeb58d82c15823d9beb3e6504bb452e14cabded159f9931bf2300fdaed5d8f
3
+ metadata.gz: 72d3799f5166153c1775c768f0734cf0e390adfd80893ef1ae1aa710b7888b0b
4
+ data.tar.gz: a18fd6eeb6a787438ddcdff1e6b0f25a17688f05a7bccff82495520517754b19
5
5
  SHA512:
6
- metadata.gz: a87a4f7386a651ca82d385600f7b32ee78ff436406d596b6c2966ed721bdcee16f9bd4ad73b158be03305541dceda0d525e68ea2dc520a028fb603a6b5f0c1c0
7
- data.tar.gz: d679906ef154e9b84e9282e1811ac0dff8da8b4dfb17c6e0e24d7f08226933346c4229468ddf51526e7532af7bdfd9a502557b64efc6439c128716a380e86d86
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 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.7.1)
4
+ plansheet (0.12.3)
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.each do |proj|
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
@@ -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,16 +2,19 @@
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 = {
8
10
  "wip" => 1,
9
11
  "ready" => 2,
10
12
  "blocked" => 3,
11
- "planning" => 4,
12
- "idea" => 5,
13
- "dropped" => 6,
14
- "done" => 7
13
+ "waiting" => 4,
14
+ "planning" => 5,
15
+ "idea" => 6,
16
+ "dropped" => 7,
17
+ "done" => 8
15
18
  }.freeze
16
19
 
17
20
  PROJECT_PRIORITY = {
@@ -20,72 +23,12 @@ module Plansheet
20
23
  "low" => 3
21
24
  }.freeze
22
25
 
23
- # Once there's some stability in plansheet and dc-kwalify, will pre-load this
24
- # to save the later YAML.load
25
- PROJECT_YAML_SCHEMA = <<~YAML
26
- desc: dc-tasks project schema
27
- type: seq
28
- sequence:
29
- - type: map
30
- mapping:
31
- "project":
32
- desc: Project name
33
- type: str
34
- required: yes
35
- "priority":
36
- desc: Project priority
37
- type: str
38
- enum:
39
- - high
40
- - medium
41
- - low
42
- "status":
43
- desc: The current status of the project
44
- type: str
45
- enum:
46
- - wip # project is a work-in-progress
47
- - ready # project is fully scoped, ready to go
48
- - blocked # project is blocked, but otherwise ready/wip
49
- - planning # project in planning phase
50
- - idea # project is little more than an idea
51
- - dropped # project has been explicitly dropped, but
52
- # want to keep around for reference, etc
53
- - done # project is finished, but want to keep around
54
- # for reference, etc.
55
- "location":
56
- desc: Location
57
- type: str
58
- "notes":
59
- desc: Free-form notes string
60
- type: str
61
- "due":
62
- desc: Due date of the task (WIP)
63
- type: date
64
- "defer":
65
- desc: Defer task until this day (WIP)
66
- type: date
67
- "externals":
68
- desc: List of external commitments, ie who else cares about project completion?
69
- type: seq
70
- sequence:
71
- - type: str
72
- "urls":
73
- desc: List of URLs that may be pertinent
74
- type: seq
75
- sequence:
76
- - type: str
77
- "tasks":
78
- desc: List of tasks to do
79
- type: seq
80
- sequence:
81
- - type: str
82
- "done":
83
- desc: List of tasks which have been completed
84
- type: seq
85
- sequence:
86
- - type: str
87
- YAML
88
- PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
26
+ def self.parse_date_duration(str)
27
+ return Regexp.last_match(1).to_i if str.strip.match(/(\d+)[dD]/)
28
+ return (Regexp.last_match(1).to_i * 7) if str.strip.match(/(\d+)[wW]/)
29
+
30
+ raise "Can't parse time duration string #{str}"
31
+ end
89
32
 
90
33
  # The use of instance_variable_set/get probably seems a bit weird, but the
91
34
  # intent is to avoid object allocation on non-existent project properties, as
@@ -96,10 +39,18 @@ module Plansheet
96
39
  class Project
97
40
  include Comparable
98
41
 
42
+ DEFAULT_COMPARISON_ORDER = %w[
43
+ completeness
44
+ dependency
45
+ priority
46
+ defer
47
+ due
48
+ status
49
+ ].map { |x| "compare_#{x}".to_sym }.freeze
99
50
  # NOTE: The order of these affects presentation!
100
- STRING_PROPERTIES = %w[priority status location notes].freeze
101
- DATE_PROPERTIES = %w[due defer].freeze
102
- ARRAY_PROPERTIES = %w[externals urls tasks done].freeze
51
+ STRING_PROPERTIES = %w[priority status location notes time_estimate frequency lead_time].freeze
52
+ DATE_PROPERTIES = %w[due defer completed_on created_on starts_on last_done last_reviewed].freeze
53
+ ARRAY_PROPERTIES = %w[dependencies externals urls tasks done tags].freeze
103
54
 
104
55
  ALL_PROPERTIES = STRING_PROPERTIES + DATE_PROPERTIES + ARRAY_PROPERTIES
105
56
 
@@ -126,109 +77,155 @@ module Plansheet
126
77
  end
127
78
 
128
79
  def <=>(other)
129
- if @priority == other.priority
130
- # TODO: if planning status, then sort based on tasks? category? alphabetically?
131
- PROJECT_STATUS_PRIORITY[status] <=> PROJECT_STATUS_PRIORITY[other.status]
132
- else
133
- PROJECT_PRIORITY[@priority] <=> PROJECT_PRIORITY[other.priority]
80
+ ret_val = 0
81
+ DEFAULT_COMPARISON_ORDER.each do |method|
82
+ ret_val = send(method, other)
83
+ break if ret_val != 0
134
84
  end
85
+ ret_val
135
86
  end
136
87
 
137
- def status
138
- return @status if @status
88
+ def compare_priority(other)
89
+ PROJECT_PRIORITY[@priority] <=> PROJECT_PRIORITY[other.priority]
90
+ end
139
91
 
140
- if @tasks&.count&.positive?
141
- if @done&.count&.positive?
142
- "wip"
143
- else
144
- "planning"
145
- end
146
- else
147
- "idea"
148
- end
92
+ def compare_status(other)
93
+ PROJECT_STATUS_PRIORITY[status] <=> PROJECT_STATUS_PRIORITY[other.status]
149
94
  end
150
95
 
151
- def to_s
152
- str = String.new
153
- str << "# #{@name}\n"
154
- STRING_PROPERTIES.each do |o|
155
- str << stringify_string_property(o)
156
- end
157
- DATE_PROPERTIES.each do |o|
158
- str << stringify_string_property(o)
96
+ def compare_due(other)
97
+ # -1 is receiving object being older
98
+
99
+ # Handle nil
100
+ if @due.nil?
101
+ return 0 if other.due.nil?
102
+
103
+ return 1
104
+ elsif other.due.nil?
105
+ return -1
159
106
  end
160
- ARRAY_PROPERTIES.each do |o|
161
- str << stringify_array_property(o)
107
+
108
+ @due <=> other.due
109
+ end
110
+
111
+ def compare_defer(other)
112
+ receiver = @defer.nil? || @defer < Date.today ? Date.today : @defer
113
+ comparison = other.defer.nil? || other.defer < Date.today ? Date.today : other.defer
114
+ receiver <=> comparison
115
+ end
116
+
117
+ def compare_dependency(other)
118
+ return 0 if @dependencies.nil? && other.dependencies.nil?
119
+
120
+ if @dependencies.nil?
121
+ return -1 if other.dependencies.any? do |dep|
122
+ @name.downcase == dep.downcase
123
+ end
124
+ elsif @dependencies.any? do |dep|
125
+ other.name.downcase == dep.downcase
126
+ end
127
+ return 1
162
128
  end
163
- str
129
+ 0
130
+ end
131
+
132
+ # Projects that are dropped or done are considered "complete", insofar as
133
+ # they are only kept around for later reference.
134
+ def compare_completeness(other)
135
+ return 0 if dropped_or_done? && other.dropped_or_done?
136
+ return 0 if !dropped_or_done? && !other.dropped_or_done?
137
+
138
+ dropped_or_done? ? 1 : -1
139
+ end
140
+
141
+ def status
142
+ return @status if @status
143
+ return recurring_status if recurring?
144
+ return task_based_status if @tasks || @done
145
+ return "done" if @completed_on && @tasks.nil?
146
+
147
+ "idea"
164
148
  end
165
149
 
166
- def stringify_string_property(prop)
167
- if instance_variable_defined? "@#{prop}"
168
- "#{prop}: #{instance_variable_get("@#{prop}")}\n"
150
+ def task_based_status
151
+ if @tasks&.count&.positive? && @done&.count&.positive?
152
+ "wip"
153
+ elsif @tasks&.count&.positive?
154
+ "ready"
155
+ elsif @done&.count&.positive?
156
+ "done"
169
157
  else
170
- ""
158
+ "idea"
171
159
  end
172
160
  end
173
161
 
174
- def stringify_date_property(prop)
175
- if instance_variable_defined? "@#{prop}"
176
- "#{prop}: #{instance_variable_get("@#{prop}")}\n"
162
+ def recurring_status
163
+ # add frequency to last_done
164
+ if @last_done
165
+ # This project has been done once before
166
+ subsequent_recurring_status
177
167
  else
178
- ""
168
+ # This recurring project is being done for the first time
169
+ task_based_status
179
170
  end
180
171
  end
181
172
 
182
- def stringify_array_property(prop)
183
- str = String.new
184
- if instance_variable_defined? "@#{prop}"
185
- str << "#{prop}:\n"
186
- instance_variable_get("@#{prop}").each do |t|
187
- str << "- #{t}\n"
188
- end
189
- end
190
- str
173
+ def subsequent_recurring_status
174
+ return "done" if @lead_time && defer > Date.today
175
+ return "done" if due > Date.today
176
+
177
+ task_based_status
191
178
  end
192
179
 
193
- def to_h
194
- h = { "project" => @name }
195
- ALL_PROPERTIES.each do |prop|
196
- h[prop] = instance_variable_get("@#{prop}") if instance_variable_defined?("@#{prop}")
180
+ def process_recurring
181
+ # TODO: Tasks will be moved from done->tasks if recurring project is
182
+ # starting again
183
+ end
184
+
185
+ # Due date either explicit or recurring
186
+ def due
187
+ return @due if @due
188
+ return recurring_due_date if recurring?
189
+
190
+ nil
191
+ end
192
+
193
+ def recurring_due_date
194
+ if @last_done
195
+ @last_done + Plansheet.parse_date_duration(@frequency)
196
+ else
197
+ Date.today
197
198
  end
198
- h.delete "priority" if h.key?("priority") && h["priority"] == "low"
199
- h.delete "status" if h.key?("status") && h["status"] == "idea"
200
- h
201
199
  end
202
- end
203
200
 
204
- class ProjectYAMLFile
205
- attr_reader :projects
201
+ def defer
202
+ return @defer if @defer
203
+ return lead_time_deferral if @lead_time && due
206
204
 
207
- def initialize(path)
208
- @path = path
209
- # TODO: this won't GC, inline validation instead?
210
- @raw = YAML.load_file(path, permitted_classes: [Date])
211
- validate_schema
212
- @projects = @raw.map { |proj| Project.new proj }
205
+ nil
213
206
  end
214
207
 
215
- def validate_schema
216
- validator = Kwalify::Validator.new(Plansheet::PROJECT_SCHEMA)
217
- errors = validator.validate(@raw)
218
- # Check YAML validity
219
- return unless errors && !errors.empty?
208
+ def lead_time_deferral
209
+ [(due - Plansheet.parse_date_duration(@lead_time)),
210
+ Date.today].max
211
+ end
220
212
 
221
- $stderr.write "Schema errors in #{@path}:\n"
222
- errors.each { |err| puts "- [#{err.path}] #{err.message}" }
223
- abort
213
+ def recurring?
214
+ !@frequency.nil?
224
215
  end
225
216
 
226
- def sort!
227
- @projects.sort!
217
+ def dropped_or_done?
218
+ status == "dropped" || status == "done"
228
219
  end
229
220
 
230
- def yaml_dump
231
- YAML.dump(@projects.map(&:to_h))
221
+ def to_h
222
+ h = { "project" => @name }
223
+ ALL_PROPERTIES.each do |prop|
224
+ h[prop] = instance_variable_get("@#{prop}") if instance_variable_defined?("@#{prop}")
225
+ end
226
+ h.delete "priority" if h.key?("priority") && h["priority"] == "low"
227
+ h.delete "status" if h.key?("status") && h["status"] == "idea"
228
+ h
232
229
  end
233
230
  end
234
231
  end
@@ -10,7 +10,7 @@ module Plansheet
10
10
  projects_str = String.new
11
11
  projects_str << sheet_header
12
12
 
13
- sorted_arr.first(60).each do |p|
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.tasks.each do |t|
35
+ proj&.tasks&.each do |t|
36
36
  str << "$\\square$ #{t} \\\\\n"
37
37
  end
38
38
  str << "\\end{minipage}\n"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plansheet
4
- VERSION = "0.7.1"
4
+ VERSION = "0.12.3"
5
5
  end
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.7.1
4
+ version: 0.12.3
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-02 00:00:00.000000000 Z
11
+ date: 2022-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dc-kwalify
@@ -33,10 +33,10 @@ 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
39
+ - Guardfile
40
40
  - LICENSE.txt
41
41
  - README.md
42
42
  - Rakefile
@@ -44,6 +44,8 @@ files:
44
44
  - exe/plansheet
45
45
  - lib/plansheet.rb
46
46
  - lib/plansheet/project.rb
47
+ - lib/plansheet/project/stringify.rb
48
+ - lib/plansheet/project/yaml.rb
47
49
  - lib/plansheet/sheet.rb
48
50
  - lib/plansheet/version.rb
49
51
  homepage: https://dafyddcrosby.com
data/.rubocop_todo.yml DELETED
@@ -1,31 +0,0 @@
1
- # This configuration was generated by
2
- # `rubocop --auto-gen-config`
3
- # on 2022-06-02 13:59:36 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: IgnoredMethods.
11
- Metrics/CyclomaticComplexity:
12
- Max: 8
13
-
14
- # Offense count: 1
15
- # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
16
- Metrics/MethodLength:
17
- Max: 12
18
-
19
- # Offense count: 1
20
- # Configuration parameters: IgnoredMethods.
21
- Metrics/PerceivedComplexity:
22
- Max: 10
23
-
24
- # Offense count: 2
25
- # Configuration parameters: AllowedConstants.
26
- Style/Documentation:
27
- Exclude:
28
- - 'spec/**/*'
29
- - 'test/**/*'
30
- - 'lib/plansheet.rb'
31
- - 'lib/plansheet/project.rb'