plansheet 0.3.3 → 0.5.1
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/Gemfile.lock +1 -1
- data/exe/plansheet +33 -75
- data/lib/plansheet/project.rb +90 -0
- data/lib/plansheet/sheet.rb +52 -0
- data/lib/plansheet/version.rb +1 -1
- data/lib/plansheet.rb +28 -1
- metadata +3 -4
- data/exe/plansheet-sorter +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3546f42fdd342ea128be90bff2e19b7bcb5c0910990e2132b89b87cbf6a1f776
|
4
|
+
data.tar.gz: 2ea5d505262832e19e77a63e7aa7c59c9fff0b98ddc3ee8218c68b010f4768eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 335cb1a3e74ab82a1441ec034099427dc0caabaad8a87c1f2620c7143d1fd4772023fe089a7305063fb12a96d169e44dd0b01f8f20437f45bdfa945b03aa2422
|
7
|
+
data.tar.gz: 5d618d61c6a07d8e32e46cfb4dba5df0264370f01d8b4ecef4c68f9fdcf6fcf600ca33bda0a8918e63992434e2a009e4d836f1f838851e0ee94de53128fe1ab2
|
data/Gemfile.lock
CHANGED
data/exe/plansheet
CHANGED
@@ -1,81 +1,39 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "kwalify"
|
5
|
-
require "yaml"
|
6
4
|
require "plansheet"
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
"idea"
|
42
|
-
end
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
parser = OptionParser.new
|
8
|
+
parser.on(
|
9
|
+
"--sheet",
|
10
|
+
"Generates MD/LaTeX project PDF"
|
11
|
+
)
|
12
|
+
parser.on(
|
13
|
+
"--sort",
|
14
|
+
"Sort project files"
|
15
|
+
)
|
16
|
+
parser.on(
|
17
|
+
"--cli",
|
18
|
+
"CLI dump of projects (WIP)"
|
19
|
+
)
|
20
|
+
options = {}
|
21
|
+
parser.parse!(into: options)
|
22
|
+
|
23
|
+
config = Plansheet.load_config
|
24
|
+
|
25
|
+
if options[:sheet] || options.empty?
|
26
|
+
project_arr = Plansheet.load_projects_dir config["projects_dir"]
|
27
|
+
|
28
|
+
Dir.mkdir config["output_dir"] unless Dir.exist? config["output_dir"]
|
29
|
+
|
30
|
+
Plansheet::Sheet.new("#{config["output_dir"]}/projects.md", project_arr)
|
31
|
+
elsif options[:sort]
|
32
|
+
Plansheet.resort_projects_in_dir config["projects_dir"]
|
33
|
+
elsif options[:cli]
|
34
|
+
project_arr = Plansheet.load_projects_dir config["projects_dir"]
|
35
|
+
project_arr.each do |proj|
|
36
|
+
puts proj
|
37
|
+
puts "\n"
|
43
38
|
end
|
44
39
|
end
|
45
|
-
|
46
|
-
sorted_hash = project_hash.sort_by do |_, v|
|
47
|
-
Plansheet::PROJECT_STATUS_PRIORITY[v[:status]]
|
48
|
-
end
|
49
|
-
|
50
|
-
def project_minipage(proj)
|
51
|
-
str = String.new
|
52
|
-
str << "\\begin{minipage}{5cm}\n"
|
53
|
-
str << "#{proj[:name]} - #{proj[:status]} \\\\\n"
|
54
|
-
proj[:tasks]&.each do |t|
|
55
|
-
str << "$\\square$ #{t} \\\\\n"
|
56
|
-
end
|
57
|
-
str << "\\end{minipage}\n"
|
58
|
-
str
|
59
|
-
end
|
60
|
-
|
61
|
-
require "date"
|
62
|
-
projects_str = String.new
|
63
|
-
projects_str << <<~FRONTMATTER
|
64
|
-
---
|
65
|
-
geometry: margin=3cm
|
66
|
-
---
|
67
|
-
\\thispagestyle{empty}
|
68
|
-
|
69
|
-
# Date: #{Date.today}
|
70
|
-
FRONTMATTER
|
71
|
-
|
72
|
-
sorted_hash.first(60).each do |_, p|
|
73
|
-
projects_str << project_minipage(p)
|
74
|
-
end
|
75
|
-
|
76
|
-
output_file = "#{config["output_dir"]}/projects.md"
|
77
|
-
puts "Writing to #{output_file}"
|
78
|
-
Dir.mkdir config["output_dir"] unless Dir.exist? config["output_dir"]
|
79
|
-
f = File.open(output_file, "w")
|
80
|
-
f.write(projects_str)
|
81
|
-
f.close
|
data/lib/plansheet/project.rb
CHANGED
@@ -44,6 +44,9 @@ module Plansheet
|
|
44
44
|
enum:
|
45
45
|
- high
|
46
46
|
- low
|
47
|
+
"location":
|
48
|
+
desc: Location (not currently implemented)
|
49
|
+
type: str
|
47
50
|
"tasks":
|
48
51
|
desc: List of tasks to do
|
49
52
|
type: seq
|
@@ -59,4 +62,91 @@ module Plansheet
|
|
59
62
|
type: str
|
60
63
|
YAML
|
61
64
|
PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
|
65
|
+
class Project
|
66
|
+
attr_reader :name, :tasks, :done, :notes, :location
|
67
|
+
|
68
|
+
def initialize(options)
|
69
|
+
@name = options["project"]
|
70
|
+
|
71
|
+
@tasks = options["tasks"] || []
|
72
|
+
@done = options["done"] || []
|
73
|
+
|
74
|
+
@notes = options["notes"] if options["notes"]
|
75
|
+
@location = options["location"] if options["location"]
|
76
|
+
@status = options["status"] if options["status"]
|
77
|
+
end
|
78
|
+
|
79
|
+
def status
|
80
|
+
return @status if @status
|
81
|
+
|
82
|
+
if @tasks.count.positive?
|
83
|
+
if @done.count.positive?
|
84
|
+
"wip"
|
85
|
+
else
|
86
|
+
"planning"
|
87
|
+
end
|
88
|
+
else
|
89
|
+
"idea"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_s
|
94
|
+
str = String.new
|
95
|
+
str << "# #{@name}\n"
|
96
|
+
str << "status: #{status}\n"
|
97
|
+
str << "notes: #{notes}\n" unless @notes.nil?
|
98
|
+
str << "location: #{location}\n" unless @location.nil?
|
99
|
+
str << "tasks:\n" unless @tasks.empty?
|
100
|
+
@tasks.each do |t|
|
101
|
+
str << "- #{t}\n"
|
102
|
+
end
|
103
|
+
str << "done:\n" unless @done.empty?
|
104
|
+
@done.each do |d|
|
105
|
+
str << "- #{d}\n"
|
106
|
+
end
|
107
|
+
str
|
108
|
+
end
|
109
|
+
def to_h
|
110
|
+
h = { "project" => @name }
|
111
|
+
h["status"] = status unless status == "idea"
|
112
|
+
h["notes"] = @notes unless @notes.nil?
|
113
|
+
h["location"] = @location unless @location.nil?
|
114
|
+
h["tasks"] = @tasks unless @tasks.empty?
|
115
|
+
h["done"] = @done unless @done.empty?
|
116
|
+
h
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ProjectYAMLFile
|
121
|
+
attr_reader :projects
|
122
|
+
|
123
|
+
def initialize(path)
|
124
|
+
@path = path
|
125
|
+
# TODO: this won't GC, inline validation instead?
|
126
|
+
@raw = YAML.load_file(path)
|
127
|
+
validate_schema
|
128
|
+
@projects = @raw.map { |proj| Project.new proj }
|
129
|
+
end
|
130
|
+
|
131
|
+
def validate_schema
|
132
|
+
validator = Kwalify::Validator.new(Plansheet::PROJECT_SCHEMA)
|
133
|
+
errors = validator.validate(@raw)
|
134
|
+
# Check YAML validity
|
135
|
+
if errors && !errors.empty?
|
136
|
+
$stderr.write "Schema errors in #{l}\n"
|
137
|
+
errors.each { |err| puts "- [#{err.path}] #{err.message}" }
|
138
|
+
abort
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def sort!
|
143
|
+
@projects.sort_by! do |project|
|
144
|
+
Plansheet::PROJECT_STATUS_PRIORITY[project.status]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def yaml_dump
|
149
|
+
YAML.dump(@projects.map(&:to_h))
|
150
|
+
end
|
151
|
+
end
|
62
152
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
module Plansheet
|
5
|
+
# The Sheet class constructs a Markdown/LaTeX file for use with pandoc
|
6
|
+
class Sheet
|
7
|
+
def initialize(output_file, project_arr)
|
8
|
+
sorted_arr = project_arr.sort_by do |p|
|
9
|
+
Plansheet::PROJECT_STATUS_PRIORITY[p.status]
|
10
|
+
end
|
11
|
+
|
12
|
+
projects_str = String.new
|
13
|
+
projects_str << sheet_header
|
14
|
+
|
15
|
+
sorted_arr.first(60).each do |p|
|
16
|
+
projects_str << project_minipage(p)
|
17
|
+
end
|
18
|
+
puts "Writing to #{output_file}"
|
19
|
+
File.write(output_file, projects_str)
|
20
|
+
end
|
21
|
+
|
22
|
+
def sheet_header
|
23
|
+
<<~FRONTMATTER
|
24
|
+
---
|
25
|
+
geometry: margin=1.5cm
|
26
|
+
---
|
27
|
+
\\thispagestyle{empty}
|
28
|
+
|
29
|
+
# Date: #{Date.today}
|
30
|
+
FRONTMATTER
|
31
|
+
end
|
32
|
+
|
33
|
+
def project_minipage(proj)
|
34
|
+
str = String.new
|
35
|
+
str << "\\begin{minipage}{4.5cm}\n"
|
36
|
+
str << project_header(proj)
|
37
|
+
proj.tasks.each do |t|
|
38
|
+
str << "$\\square$ #{t} \\\\\n"
|
39
|
+
end
|
40
|
+
str << "\\end{minipage}\n"
|
41
|
+
str
|
42
|
+
end
|
43
|
+
|
44
|
+
def project_header(proj)
|
45
|
+
str = String.new
|
46
|
+
str << "#{proj.name} - #{proj.status}"
|
47
|
+
str << " - #{proj.location}" if proj.location
|
48
|
+
str << " \\\\\n"
|
49
|
+
str
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/plansheet/version.rb
CHANGED
data/lib/plansheet.rb
CHANGED
@@ -2,8 +2,35 @@
|
|
2
2
|
|
3
3
|
require_relative "plansheet/version"
|
4
4
|
require_relative "plansheet/project"
|
5
|
+
require_relative "plansheet/sheet"
|
6
|
+
require "yaml"
|
7
|
+
require "kwalify"
|
5
8
|
|
6
9
|
module Plansheet
|
7
10
|
class Error < StandardError; end
|
8
|
-
|
11
|
+
|
12
|
+
def self.load_config
|
13
|
+
YAML.load_file "#{Dir.home}/.plansheet.yml"
|
14
|
+
rescue StandardError
|
15
|
+
abort "unable to load plansheet config file"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.resort_projects_in_dir(dir)
|
19
|
+
project_files = Dir.glob("#{dir}/*yml")
|
20
|
+
project_files.each do |f|
|
21
|
+
pyf = ProjectYAMLFile.new(f)
|
22
|
+
pyf.sort!
|
23
|
+
File.write(f, pyf.yaml_dump)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.load_projects_dir(dir)
|
28
|
+
project_arr = []
|
29
|
+
projects = Dir.glob("*yml", base: dir)
|
30
|
+
projects.each do |l|
|
31
|
+
project_arr << ProjectYAMLFile.new(File.join(dir, l)).projects
|
32
|
+
end
|
33
|
+
|
34
|
+
project_arr.flatten!
|
35
|
+
end
|
9
36
|
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.
|
4
|
+
version: 0.5.1
|
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-05-
|
11
|
+
date: 2022-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dc-kwalify
|
@@ -29,7 +29,6 @@ email:
|
|
29
29
|
- dave@dafyddcrosby.com
|
30
30
|
executables:
|
31
31
|
- plansheet
|
32
|
-
- plansheet-sorter
|
33
32
|
extensions: []
|
34
33
|
extra_rdoc_files: []
|
35
34
|
files:
|
@@ -42,9 +41,9 @@ files:
|
|
42
41
|
- Rakefile
|
43
42
|
- examples/backpack.yml
|
44
43
|
- exe/plansheet
|
45
|
-
- exe/plansheet-sorter
|
46
44
|
- lib/plansheet.rb
|
47
45
|
- lib/plansheet/project.rb
|
46
|
+
- lib/plansheet/sheet.rb
|
48
47
|
- lib/plansheet/version.rb
|
49
48
|
homepage: https://dafyddcrosby.com
|
50
49
|
licenses:
|
data/exe/plansheet-sorter
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
# An ugly script to sort projects by status (and eventually priority)
|
5
|
-
|
6
|
-
require "yaml"
|
7
|
-
require "plansheet"
|
8
|
-
|
9
|
-
def project_priority(project)
|
10
|
-
if project["status"]
|
11
|
-
project["status"]
|
12
|
-
elsif project["tasks"]
|
13
|
-
"planning"
|
14
|
-
else
|
15
|
-
"idea"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
filename = ARGV.first
|
20
|
-
contents = YAML.load_file(filename)
|
21
|
-
sorted_hash = contents.sort_by do |project|
|
22
|
-
Plansheet::PROJECT_STATUS_PRIORITY[project_priority project]
|
23
|
-
end
|
24
|
-
|
25
|
-
File.write(filename, YAML.dump(sorted_hash))
|