plansheet 0.31.0 → 0.34.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1b05c9c4733d200c8baee9815468f5645bff5e4c91290d36be60cb292d3cc19
4
- data.tar.gz: bafca3ddbcd281d8fb98098dd77af9771fdf9e896d7edb67bb03c16377e40600
3
+ metadata.gz: 0127f89bb4b286c6bda0d5ff1d1c8e02d4ceb26f0898f78f2031ad7d69913bf1
4
+ data.tar.gz: 0ce4e76d7693d51bfdd96cd6390124955858c15b5fe109f03d11d4aa707bdf98
5
5
  SHA512:
6
- metadata.gz: a392b05530451746c15420d8bd5a96be18666f709974c604ab03ecafadec3464e876fb51203c5824e6203f370e2f71bab62b2eb9c7a5d496b9de70099f021f87
7
- data.tar.gz: 24320acdc706151578b4a3e8ba278aaae5630317ed4d069b3b609c983597c7b668fbdce51002fedaa066ae359d5a05f47825f2e3eb4cf0927efebd6bfb4a1931
6
+ metadata.gz: 7d694e749bff3c2a4b7f6983f75ecc6861eb8a793752658439bc0e2a3381c0037aa09edad3ab4f33fc8365992ee21ab12bdc450eb6283a4e1fa8b2f7250078a3
7
+ data.tar.gz: 81e8c85c1914e225b2bca1fe8655e367b1d36a830ea0905d0bf449fa4c3ced79b023c92ecd9d655cf09a5843ec9be78de67a63e5efdaa341e843999dec736eb6
data/Gemfile CHANGED
@@ -5,6 +5,6 @@ source "https://rubygems.org"
5
5
  gemspec
6
6
 
7
7
  group :development, optional: true do
8
- gem "dc-devtools", "~> 0.1"
8
+ gem "dc-devtools", "~> 0.5"
9
9
  gem "rdoc"
10
10
  end
data/Rakefile CHANGED
@@ -9,8 +9,6 @@ Rake::TestTask.new(:test) do |t|
9
9
  t.test_files = FileList["test/**/test_*.rb"]
10
10
  end
11
11
 
12
- require "rubocop/rake_task"
13
-
14
- RuboCop::RakeTask.new
12
+ require "dc_rake"
15
13
 
16
14
  task default: %i[test rubocop]
data/exe/plansheet CHANGED
@@ -4,11 +4,14 @@
4
4
  require "plansheet"
5
5
  require "optparse"
6
6
 
7
+ options = {}
7
8
  parser = OptionParser.new
8
9
  parser.on(
9
- "--sheet",
10
+ "--sheet [TYPE]",
10
11
  "Generates MD/LaTeX project PDF"
11
- )
12
+ ) do |sheet_type|
13
+ options[:sheet] = sheet_type || "projects"
14
+ end
12
15
  parser.on(
13
16
  "--sort",
14
17
  "Sort project files"
@@ -41,7 +44,6 @@ parser.on(
41
44
  "--location_filter LOCATION",
42
45
  "location filter for CLI dump (WIP)"
43
46
  )
44
- options = {}
45
47
  parser.parse!(into: options)
46
48
 
47
49
  config = Plansheet.load_config
@@ -49,11 +51,21 @@ pool = Plansheet::Pool.new({ projects_dir: config["projects_dir"],
49
51
  sort_order: config["sort_order"] })
50
52
 
51
53
  if options[:sheet] || options.empty?
54
+ # TODO: Add pdflatex command (customizable path)
52
55
  require "plansheet/sheet"
53
56
  FileUtils.mkdir_p config["output_dir"]
54
- project_arr = pool.projects
55
- project_arr.delete_if { |x| %w[dropped done paused].include? x.status }
56
- Plansheet::LaTeXSheet.new("#{config["output_dir"]}/projects.tex", project_arr)
57
+ case options[:sheet]
58
+ when "daily"
59
+ Plansheet::DailyLaTeXSheet.new("#{config["output_dir"]}/daily.tex", config["daily"])
60
+ when "weekly"
61
+ Plansheet::WeeklyLaTeXSheet.new("#{config["output_dir"]}/weekly.tex", pool.projects, config["weekly"])
62
+ when "monthly"
63
+ Plansheet::MonthlyLaTeXSheet.new("#{config["output_dir"]}/monthly.tex", config["monthly"])
64
+ else
65
+ project_arr = pool.projects
66
+ project_arr.delete_if { |x| %w[dropped done paused].include? x.status }
67
+ Plansheet::LaTeXSheet.new("#{config["output_dir"]}/projects.tex", project_arr)
68
+ end
57
69
  elsif options[:irb]
58
70
  binding.irb # rubocop:disable Lint/Debugger
59
71
  elsif options[:stats]
@@ -6,14 +6,17 @@ require_relative "project/yaml"
6
6
  require_relative "project/stringify"
7
7
  require_relative "./time"
8
8
 
9
- # Needed for Project#time_estimate, would be much happier *not* patching Array
10
- class Array
11
- def nil_if_empty
12
- count.zero? ? nil : self
9
+ module Plansheet
10
+ module PlansheetArray
11
+ # Needed for Project#time_estimate
12
+ refine Array do
13
+ def nil_if_empty
14
+ count.zero? ? nil : self
15
+ end
16
+ end
13
17
  end
14
- end
18
+ using PlansheetArray
15
19
 
16
- module Plansheet
17
20
  PROJECT_STATUS_PRIORITY = {
18
21
  "wip" => 1,
19
22
  "ready" => 2,
@@ -121,11 +124,13 @@ module Plansheet
121
124
  end
122
125
 
123
126
  if done?
124
- @completed_on ||= Date.today unless recurring?
125
127
  remove_instance_variable("@status") if @status
126
- remove_instance_variable("@time_estimate") if @time_estimate
127
- remove_instance_variable("@time_estimate_minutes") if @time_estimate
128
- remove_instance_variable("@time_roi_payoff") if @time_roi_payoff
128
+ unless recurring?
129
+ @completed_on ||= Date.today
130
+ remove_instance_variable("@time_estimate") if @time_estimate
131
+ remove_instance_variable("@time_estimate_minutes") if @time_estimate
132
+ remove_instance_variable("@time_roi_payoff") if @time_roi_payoff
133
+ end
129
134
  elsif paused?
130
135
  @paused_on ||= Date.today
131
136
  remove_instance_variable("@status") if @status
@@ -332,16 +337,10 @@ module Plansheet
332
337
  !@frequency.nil? || !@day_of_week.nil? || !@last_done.nil? || !@last_for.nil?
333
338
  end
334
339
 
335
- def paused?
336
- status == "paused"
337
- end
338
-
339
- def dropped?
340
- status == "dropped"
341
- end
342
-
343
- def done?
344
- status == "done"
340
+ PROJECT_STATUS_PRIORITY.each_key do |stat|
341
+ define_method("#{stat}?".to_sym) do
342
+ status == stat
343
+ end
345
344
  end
346
345
 
347
346
  def dropped_or_done?
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: false
2
+
3
+ require "date"
4
+ module Plansheet
5
+ class DailyLaTeXSheet
6
+ include Plansheet::LaTeXMixins
7
+ def initialize(output_file, config)
8
+ @config = config
9
+ projects_str = sheet_header
10
+ projects_str << document do
11
+ sheet_body
12
+ end
13
+
14
+ puts "Writing to #{output_file}"
15
+ File.write(output_file, projects_str)
16
+ end
17
+
18
+ def dateline
19
+ <<~DATELINE
20
+ \\thispagestyle{empty}
21
+
22
+ Date \\(\\underline{\\hspace{4cm}}\\)
23
+
24
+ DATELINE
25
+ end
26
+
27
+ INCOLUMN_SPACING = "7mm".freeze
28
+ def sheet_body
29
+ [
30
+ dateline,
31
+ vspace("1cm"),
32
+ vbox do
33
+ @config["top"].map do |section|
34
+ minipage("8cm") do
35
+ section_output(section)
36
+ end
37
+ end.join
38
+ end,
39
+
40
+ %w[left_bar right_bar].map do |col|
41
+ minipage("8cm") do
42
+ @config[col].map do |section|
43
+ minipage("\\textwidth") do
44
+ section_output(section)
45
+ end
46
+ end.join(vspace(INCOLUMN_SPACING))
47
+ end
48
+ end
49
+ ].flatten.join
50
+ end
51
+
52
+ def section_output(section)
53
+ case section["type"]
54
+ when "checkboxes"
55
+ checkboxes(section["items"])
56
+ when "checkbox_and_lines"
57
+ checkbox_and_lines(section["items"])
58
+ when "multiline_checkbox_and_lines"
59
+ multiline_checkbox_and_lines(section["items"])
60
+ end
61
+ end
62
+
63
+ def checkboxes(items)
64
+ items.map do |l|
65
+ l.map do |i|
66
+ checkbox_item i
67
+ end.join(" ")
68
+ end.join(HARD_NL)
69
+ end
70
+
71
+ def checkbox_and_lines(items)
72
+ items.map do |i|
73
+ checkbox_item(i, line: "4cm")
74
+ end.join(HARD_NL)
75
+ end
76
+
77
+ def multiline_checkbox_and_lines(items)
78
+ items.map do |q|
79
+ "#{checkbox_item q} #{HARD_NL}#{writein_line("\\textwidth")}"
80
+ end.join(HARD_NL)
81
+ end
82
+ end
83
+ end
@@ -2,97 +2,39 @@
2
2
 
3
3
  require "date"
4
4
  module Plansheet
5
- # The Sheet class constructs a Markdown/LaTeX file for use with pandoc
5
+ # The Sheet class constructs a Markdown/LaTeX file for use with pdflatex
6
6
  class LaTeXSheet
7
+ include LaTeXMixins
7
8
  def initialize(output_file, project_arr)
8
- projects_str = String.new
9
- projects_str << sheet_header
10
-
11
- project_arr.each do |p|
12
- projects_str << project_minipage(p)
9
+ projects_str = sheet_header
10
+ projects_str << document do
11
+ "\\thispagestyle{empty}\n\n\\section{Date: #{Date.today}}\n".concat(
12
+ project_arr.map do |p|
13
+ project_minipage(p)
14
+ end.join
15
+ )
13
16
  end
14
17
  puts "Writing to #{output_file}"
15
- projects_str << sheet_footer
16
18
  File.write(output_file, projects_str)
17
19
  end
18
20
 
19
- def sheet_header
20
- # LaTeX used to be generated by pandoc
21
- <<~FRONTMATTER
22
- \\PassOptionsToPackage{unicode}{hyperref}
23
- \\PassOptionsToPackage{hyphens}{url}
24
- \\documentclass[]{article}
25
- \\author{}
26
- \\date{#{Date.today}}
27
- \\usepackage{amsmath,amssymb}
28
- \\usepackage{lmodern}
29
- \\usepackage{iftex}
30
- \\usepackage[T1]{fontenc}
31
- \\usepackage[utf8]{inputenc}
32
- \\usepackage{textcomp}
33
- \\IfFileExists{upquote.sty}{\\usepackage{upquote}}{}
34
- \\IfFileExists{microtype.sty}{
35
- \\usepackage[]{microtype}
36
- \\UseMicrotypeSet[protrusion]{basicmath}
37
- }{}
38
- \\makeatletter
39
- \\@ifundefined{KOMAClassName}{
40
- \\IfFileExists{parskip.sty}{
41
- \\usepackage{parskip}
42
- }{
43
- \\setlength{\\parindent}{0pt}
44
- \\setlength{\\parskip}{6pt plus 2pt minus 1pt}}
45
- }{
46
- \\KOMAoptions{parskip=half}}
47
- \\makeatother
48
- \\usepackage{xcolor}
49
- \\IfFileExists{xurl.sty}{\\usepackage{xurl}}{}
50
- \\IfFileExists{bookmark.sty}{\\usepackage{bookmark}}{\\usepackage{hyperref}}
51
- \\hypersetup{
52
- hidelinks,
53
- pdfcreator={LaTeX via plansheet}}
54
- \\urlstyle{same}
55
- \\usepackage[margin=1.5cm]{geometry}
56
- \\setlength{\\emergencystretch}{3em}
57
- \\providecommand{\\tightlist}{
58
- \\setlength{\\itemsep}{0pt}\\setlength{\\parskip}{0pt}}
59
- \\setcounter{secnumdepth}{-\\maxdimen}
60
-
61
- \\begin{document}
62
-
63
- \\thispagestyle{empty}
64
-
65
- \\section{Date: #{Date.today}}
66
- FRONTMATTER
67
- end
68
-
69
- def sheet_footer
70
- '\end{document}'
71
- end
72
-
73
21
  def project_minipage(proj)
74
- str = String.new
75
- str << "\\begin{minipage}{6cm}\n"
76
- str << project_header(proj)
77
- proj&.tasks&.each do |t|
78
- str << "$\\square$ #{sanitize_string(t)} \\\\\n"
22
+ minipage("6cm") do
23
+ project_header(proj)&.concat(
24
+ proj&.tasks&.map do |t|
25
+ "#{checkbox_item sanitize_string(t)}#{HARD_NL}"
26
+ end&.join("") || "" # empty string to catch nil
27
+ )
79
28
  end
80
- str << "\\end{minipage}\n"
81
- str
82
- end
83
-
84
- def sanitize_string(str)
85
- str.gsub("_", '\_')
86
29
  end
87
30
 
88
31
  def project_header(proj)
89
- str = String.new
90
- str << "#{sanitize_string(proj.namespace)}: #{sanitize_string(proj.name)}\\\\\n"
32
+ str = "#{sanitize_string(proj.namespace)}: #{sanitize_string(proj.name)}#{HARD_NL}"
91
33
  str << proj.status.to_s
92
34
  str << " - #{sanitize_string(proj.location)}" if proj.location
93
35
  str << " due: #{proj.due}" if proj.due
94
36
  str << " time: #{proj.time_estimate}" if proj.time_estimate
95
- str << " \\\\\n"
37
+ str << HARD_NL
96
38
  str
97
39
  end
98
40
  end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ module Plansheet
5
+ module LaTeXMixins
6
+ HARD_NL = " \\\\\n"
7
+ SQUARE = "$\\square$"
8
+
9
+ def vspace(space)
10
+ "\\vspace{#{space}}\n"
11
+ end
12
+
13
+ def writein_line(space)
14
+ "$\\underline{\\hspace{#{space}}}$"
15
+ end
16
+
17
+ def checkbox_item(str, line: nil)
18
+ "#{SQUARE} #{str}#{" #{writein_line(line)}" if line}"
19
+ end
20
+
21
+ def vbox
22
+ "\\vbox{\n#{yield}\n}\n"
23
+ end
24
+
25
+ %w[center document enumerate tabbing].each do |env|
26
+ define_method(env.to_sym) do |&e|
27
+ <<~ENV
28
+ \\begin{#{env}}
29
+ #{e.call}
30
+ \\end{#{env}}
31
+ ENV
32
+ end
33
+ end
34
+
35
+ def itemize_tightlist
36
+ <<~DOCUMENT
37
+ \\begin{itemize}
38
+ \\tightlist
39
+ #{yield}
40
+ \\end{itemize}
41
+ DOCUMENT
42
+ end
43
+
44
+ def itemline(item, opt: nil)
45
+ "\\item#{opt ? "[#{opt}]" : ""} #{item}\n"
46
+ end
47
+
48
+ def minipage(size)
49
+ <<~MINIPAGE
50
+ \\begin{minipage}{#{size}}
51
+ #{yield}
52
+ \\end{minipage}
53
+ MINIPAGE
54
+ end
55
+
56
+ def sanitize_string(str)
57
+ str.gsub("_", '\_')
58
+ end
59
+
60
+ def sheet_header
61
+ # LaTeX used to be generated by pandoc
62
+ <<~FRONTMATTER
63
+ \\PassOptionsToPackage{unicode}{hyperref}
64
+ \\PassOptionsToPackage{hyphens}{url}
65
+ \\documentclass[]{article}
66
+ \\author{}
67
+ \\date{#{Date.today}}
68
+ \\usepackage{amsmath,amssymb}
69
+ \\usepackage{lmodern}
70
+ \\usepackage{iftex}
71
+ \\usepackage[T1]{fontenc}
72
+ \\usepackage[utf8]{inputenc}
73
+ \\usepackage{textcomp}
74
+ \\IfFileExists{upquote.sty}{\\usepackage{upquote}}{}
75
+ \\IfFileExists{microtype.sty}{
76
+ \\usepackage[]{microtype}
77
+ \\UseMicrotypeSet[protrusion]{basicmath}
78
+ }{}
79
+ \\makeatletter
80
+ \\@ifundefined{KOMAClassName}{
81
+ \\IfFileExists{parskip.sty}{
82
+ \\usepackage{parskip}
83
+ }{
84
+ \\setlength{\\parindent}{0pt}
85
+ \\setlength{\\parskip}{6pt plus 2pt minus 1pt}}
86
+ }{
87
+ \\KOMAoptions{parskip=half}}
88
+ \\makeatother
89
+ \\usepackage{xcolor}
90
+ \\IfFileExists{xurl.sty}{\\usepackage{xurl}}{}
91
+ \\IfFileExists{bookmark.sty}{\\usepackage{bookmark}}{\\usepackage{hyperref}}
92
+ \\hypersetup{
93
+ hidelinks,
94
+ pdfcreator={LaTeX via plansheet}}
95
+ \\urlstyle{same}
96
+ \\usepackage[margin=1.5cm]{geometry}
97
+ \\setlength{\\emergencystretch}{3em}
98
+ \\providecommand{\\tightlist}{
99
+ \\setlength{\\itemsep}{0pt}\\setlength{\\parskip}{0pt}}
100
+ \\setcounter{secnumdepth}{-\\maxdimen}
101
+ FRONTMATTER
102
+ end
103
+
104
+ def config_file_sanity_check(options = {})
105
+ options.each do |opt, type|
106
+ unless @config[opt].is_a?(type) && !@config[opt]&.empty?
107
+ abort "Need to specify #{opt} #{type.to_s.downcase} in your ~/.plansheet.yml config"
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: false
2
+
3
+ require "date"
4
+ module Plansheet
5
+ class MonthlyLaTeXSheet
6
+ include LaTeXMixins
7
+ def initialize(output_file, config)
8
+ @config = config || {}
9
+ config_file_sanity_check({
10
+ "highlevel_items" => Array,
11
+ "tags" => Hash
12
+ })
13
+
14
+ str = sheet_header
15
+ str << document do
16
+ [
17
+ month_line,
18
+ highlevel_items,
19
+ center do
20
+ [
21
+ events_minipage,
22
+ tags_minipages
23
+ ].join
24
+ end,
25
+ monthly_calendar_grid
26
+ ].join
27
+ end
28
+ puts "Writing to #{output_file}"
29
+ File.write(output_file, str)
30
+ end
31
+
32
+ def highlevel_items
33
+ itemize_tightlist do
34
+ @config["highlevel_items"].map do |i|
35
+ itemline("#{i} #{writein_line("5cm")}", opt: SQUARE)
36
+ end.join.concat("\n")
37
+ end
38
+ end
39
+
40
+ def tags_minipages
41
+ minipage("6.5cm") do
42
+ @config["tags"].map { |k, v| tag_minipage k, v }.join
43
+ end.concat("\n")
44
+ end
45
+
46
+ def events_minipage
47
+ minipage("8cm") do
48
+ "Events:\n#{
49
+ itemize_tightlist do
50
+ 30.times.map do |n|
51
+ itemline(
52
+ writein_line("6cm"),
53
+ opt: (Date.today + n).strftime("%a %m-%d")
54
+ )
55
+ end.join.concat("\n")
56
+ end
57
+ }"
58
+ end
59
+ end
60
+
61
+ def pretty_tag_name(tag)
62
+ tag.capitalize.gsub("_", " ")
63
+ end
64
+
65
+ def tag_minipage(tag, items = 10)
66
+ "#{pretty_tag_name tag}:\n".concat(
67
+ itemize_tightlist do
68
+ items.times.map do
69
+ itemline(writein_line("6cm"), opt: SQUARE)
70
+ end.join
71
+ end
72
+ )
73
+ end
74
+
75
+ def month_line
76
+ "For the next month: #{Date.today} - #{Date.today + 30}\n\n"
77
+ end
78
+
79
+ def monthly_calendar_grid
80
+ <<~GRID
81
+ \\begin{tabular}{|#{7.times.map { "p{2cm}" }.join("|")}|}
82
+ \\hline
83
+ GRID
84
+ .concat(
85
+ %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].join(" & ").concat(HARD_NL)
86
+ ).concat(
87
+ 5.times.map do |n|
88
+ calendar_grid_line n
89
+ end.join(HARD_NL).concat(HARD_NL)
90
+ ).concat(
91
+ <<~GRID
92
+ \\hline
93
+ \\end{tabular}
94
+ GRID
95
+ )
96
+ end
97
+
98
+ private
99
+
100
+ def calendar_grid_line(week_multiplier = 0)
101
+ "\\hline\n#{
102
+ 7.times.map do |n|
103
+ (Date.today - Date.today.wday + (n + (week_multiplier * 7))).strftime("%d")
104
+ end.join(" & ")
105
+ } #{
106
+ vspace("5mm")
107
+ }"
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: false
2
+
3
+ require "date"
4
+ module Plansheet
5
+ class WeeklyLaTeXSheet
6
+ include LaTeXMixins
7
+ include TimeUtils
8
+ MINIPAGE_SIZE = "6cm".freeze
9
+ def initialize(output_file, projects, config)
10
+ @config = config || {}
11
+ config_file_sanity_check({
12
+ "namespaces" => Hash,
13
+ "tags" => Hash
14
+ })
15
+
16
+ @external_commits = projects.select(&:externals) || []
17
+ @projects = projects # TODO: remove finished?
18
+ str = sheet_header
19
+ str << document do
20
+ [
21
+ week_line,
22
+ [
23
+ event_writeins,
24
+ past_due,
25
+ upcoming_due
26
+ ].compact.join,
27
+ # Since the following are a lot more volatile in minipage length,
28
+ # sort by newline so more fits on the page
29
+ [
30
+ external_commits,
31
+ works_in_progress,
32
+ tag_minipages,
33
+ namespace_minipages,
34
+ recurring_defer
35
+ ].flatten.compact.sort_by { |x| x.count("\n") }.join
36
+ ].flatten.join
37
+ end
38
+ puts "Writing to #{output_file}"
39
+ File.write(output_file, str)
40
+ end
41
+
42
+ def namespace_minipages
43
+ @config["namespaces"].map do |namespace, limit|
44
+ projects = @projects.select { |x| x.namespace == namespace }
45
+ project_minipage namespace, projects_in_time(projects, limit)
46
+ end&.join
47
+ end
48
+
49
+ def tag_minipages
50
+ @config["tags"].map do |tag, limit|
51
+ projects = @projects.select { |x| x&.tags&.any?(tag) }
52
+ project_minipage pretty_tag_name(tag), projects_in_time(projects, limit)
53
+ end&.join
54
+ end
55
+
56
+ def works_in_progress
57
+ projects = @projects.select(&:wip?)
58
+ project_minipage "Works in progress", projects if projects
59
+ end
60
+
61
+ def past_due
62
+ projects = @projects.select { |x| x.due ? x.due < Date.today : false }
63
+ project_minipage "Past due", projects if projects
64
+ end
65
+
66
+ def recurring_defer
67
+ projects = @projects.select { |x| x.last_for ? x.last_for_deferral < Date.today + 8 : false }
68
+ project_minipage "Recurring defer", projects if projects
69
+ end
70
+
71
+ def upcoming_due
72
+ projects = @projects.select { |x| x.due ? (x.due >= Date.today && x.due < Date.today + 8) : false }
73
+ project_minipage "Upcoming due", projects if projects
74
+ end
75
+
76
+ def external_commits
77
+ project_minipage("Externals", @external_commits) unless @external_commits&.empty?
78
+ end
79
+
80
+ def event_writeins
81
+ minipage(MINIPAGE_SIZE) do
82
+ "Events:\n#{
83
+ itemize_tightlist do
84
+ 7.times.map do |n|
85
+ itemline(
86
+ writein_line("4cm"),
87
+ opt: (Date.today + n).strftime("%a %m-%d")
88
+ )
89
+ end.join.concat("\n")
90
+ end
91
+ }"
92
+ end
93
+ end
94
+
95
+ def pretty_tag_name(tag)
96
+ tag.capitalize.gsub("_", " ")
97
+ end
98
+
99
+ def project_minipage(thing, projects = [])
100
+ unless projects&.empty?
101
+ minipage(MINIPAGE_SIZE) do
102
+ "#{thing}:
103
+ #{itemize_tightlist do
104
+ projects&.map do |x|
105
+ itemline("#{x.name} #{x&.time_estimate}", opt: SQUARE)
106
+ end&.join("\n")
107
+ end
108
+ }"
109
+ end
110
+ end
111
+ end
112
+
113
+ DEFAULT_PROJECT_TIME_ESTIMATE_MIN = 120
114
+ def projects_in_time(projects, time)
115
+ projects ||= []
116
+ t = parse_time_duration(time)
117
+ p = []
118
+ projects.each do |proj|
119
+ e = proj&.time_estimate ? parse_time_duration(proj.time_estimate) : DEFAULT_PROJECT_TIME_ESTIMATE_MIN
120
+ if e <= t
121
+ p.append proj
122
+ t -= e
123
+ end
124
+ end
125
+ p
126
+ end
127
+
128
+ def week_line
129
+ "For the next week: #{Date.today} - #{Date.today + 7}\n\n"
130
+ end
131
+ end
132
+ end
@@ -1,3 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "sheet/latex_utils"
3
4
  require_relative "sheet/latex"
5
+ require_relative "sheet/daily"
6
+ require_relative "sheet/weekly"
7
+ require_relative "sheet/monthly"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plansheet
4
- VERSION = "0.31.0"
4
+ VERSION = "0.34.1"
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.31.0
4
+ version: 0.34.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-08-15 00:00:00.000000000 Z
11
+ date: 2022-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dc-kwalify
@@ -75,7 +75,11 @@ files:
75
75
  - lib/plansheet/project/stringify.rb
76
76
  - lib/plansheet/project/yaml.rb
77
77
  - lib/plansheet/sheet.rb
78
+ - lib/plansheet/sheet/daily.rb
78
79
  - lib/plansheet/sheet/latex.rb
80
+ - lib/plansheet/sheet/latex_utils.rb
81
+ - lib/plansheet/sheet/monthly.rb
82
+ - lib/plansheet/sheet/weekly.rb
79
83
  - lib/plansheet/time.rb
80
84
  - lib/plansheet/version.rb
81
85
  homepage: https://dafyddcrosby.com