resme 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,234 +1,253 @@
1
- require 'slop'
1
+ require "optparse"
2
2
 
3
3
  module Resme
4
4
  module CommandSyntax
5
- # return a hash with all the commands and their options
5
+ # Return a hash of hashes. Each key is the name of a command and
6
+ # includes useful information, such as an Option object to
7
+ # parse options and a documentation string.
6
8
  def self.commands
7
- h = Hash.new
8
- self.methods.each do |method|
9
- if method.to_s.include?("_opts") then
10
- h = h.merge(eval(method.to_s))
11
- end
9
+ cmd_spec = {}
10
+ methods.each do |method|
11
+ cmd_spec = cmd_spec.merge eval(method.to_s) if method.to_s.include?("_opts")
12
12
  end
13
- return h
13
+ cmd_spec
14
14
  end
15
15
 
16
- private
17
-
18
16
  def self.version_opts
19
- opts = Slop::Options.new
20
- opts.banner = "version -- print version information"
21
- help = <<EOS
22
- NAME
23
- #{opts.banner}
24
-
25
- SYNOPSYS
26
- #{opts.to_s}
27
-
28
- DESCRIPTION
29
- return version information
30
-
31
- EXAMPLES
32
- # resme version
33
- resme version #{VERSION}
34
- EOS
35
- return { :version => [opts, :version, help] }
17
+ opts = OptionParser.new do |opts|
18
+ opts.banner = "version # print version information"
19
+ end
20
+
21
+ help = <<-EOS
22
+ NAME
23
+ #{opts.banner}
24
+
25
+ SYNOPSYS
26
+ #{opts.to_s}
27
+
28
+ DESCRIPTION
29
+ return version information
30
+
31
+ EXAMPLES
32
+ # resme version
33
+ resme version #{VERSION}
34
+ EOS
35
+
36
+ {
37
+ version: {
38
+ name: :version,
39
+ options: opts,
40
+ help: help.gsub(" ", "")
41
+ }
42
+ }
36
43
  end
37
44
 
38
45
  def self.console_opts
39
- opts = Slop::Options.new
40
- opts.banner = "console [options] -- Enter the console"
41
- help = <<EOS
42
- NAME
43
- #{opts.banner}
44
-
45
- SYNOPSYS
46
- #{opts.to_s}
47
-
48
- DESCRIPTION
49
- Invoke a console, from which you can more easily run
50
- resme commands.
51
-
52
- EXAMPLES
53
- resme console
54
- resme:000>
55
- resme:001>
56
- resme:002>
57
- EOS
58
- return { :console => [opts, :console, help] }
46
+ opts = OptionParser.new do |opts|
47
+ opts.banner = "console # enter the console"
48
+ end
49
+
50
+ help = <<-EOS
51
+ NAME
52
+ #{opts.banner}
53
+
54
+ SYNOPSYS
55
+ #{opts.to_s}
56
+
57
+ DESCRIPTION
58
+ Invoke a console, from which you can more easily run
59
+ resme commands.
60
+
61
+ EXAMPLES
62
+ resme console
63
+ resme:000> check
64
+ resme:001> generate -t md
65
+ resme:002>
66
+ EOS
67
+
68
+ {
69
+ console: {
70
+ name: :console,
71
+ options: opts,
72
+ help: help.gsub(" ", "")
73
+ }
74
+ }
59
75
  end
60
76
 
61
77
  def self.man_opts
62
- opts = Slop::Options.new
63
- opts.banner = "man -- print a manual page"
64
- help = <<EOS
65
- NAME
66
- #{opts.banner}
67
-
68
- SYNOPSYS
69
- #{opts.to_s}
70
-
71
- DESCRIPTION
72
- Print the README file of this gem
73
-
74
- EXAMPLES
75
- resme man
76
- EOS
77
- return { :man => [opts, :man, help] }
78
+ opts = OptionParser.new do |opts|
79
+ opts.banner = "man # print resme manual page"
80
+ end
81
+
82
+ help = <<-EOS
83
+ NAME
84
+ #{opts.banner}
85
+
86
+ SYNOPSYS
87
+ #{opts.to_s}
88
+
89
+ DESCRIPTION
90
+ Print the README file of this gem
91
+
92
+ EXAMPLES
93
+ resme man
94
+ EOS
95
+
96
+ {
97
+ man: {
98
+ name: :man,
99
+ options: opts,
100
+ help: help.gsub(" ", "")
101
+ }
102
+ }
78
103
  end
79
104
 
80
105
  def self.help_opts
81
- opts = Slop::Options.new
82
- opts.banner = "help [command] -- print usage string"
83
- help = <<EOS
84
- NAME
85
- #{opts.banner}
86
-
87
- SYNOPSYS
88
- #{opts.to_s}
89
-
90
- DESCRIPTION
91
- Print help about a command
92
-
93
- EXAMPLES
94
- resme help
95
- resme help generate
96
- EOS
97
- return { :help => [opts, :help, help] }
98
- end
99
-
100
- def self.check_opts
101
- opts = Slop::Options.new
102
- opts.banner = "check -- Check whether a YAML file conforms with the RESME syntax"
103
- help = <<EOS
104
- NAME
105
- #{opts.banner}
106
-
107
- SYNOPSYS
108
- #{opts.to_s}
109
-
110
- DESCRIPTION
111
- Check whether a YAML file conforms with the RESME syntax.
112
-
106
+ opts = OptionParser.new do |opts|
107
+ opts.banner = "help [command] # print command usage"
108
+ end
113
109
 
114
- EXAMPLES
115
- resme file.yml
116
- EOS
117
- return { :check => [opts, :check, help] }
110
+ help = <<-EOS
111
+ NAME
112
+ #{opts.banner}
113
+
114
+ SYNOPSYS
115
+ #{opts.to_s}
116
+
117
+ DESCRIPTION
118
+ Print help about a command
119
+
120
+ EXAMPLES
121
+ resme help
122
+ resme help generate
123
+ EOS
124
+ {
125
+ help: {
126
+ name: :help,
127
+ options: opts,
128
+ help: help.gsub(" ", "")
129
+ }
130
+ }
118
131
  end
119
132
 
120
133
  def self.init_opts
121
- opts = Slop::Options.new
122
- opts.banner = "init [-o output_filename]"
123
- opts.string "-o", "--output", "Output filename"
124
- opts.boolean "-f", "--force", "Overwrite existing file (if present)"
125
- help = <<EOS
126
- NAME
127
- #{opts.banner}
128
-
129
- SYNOPSYS
130
- #{opts.to_s}
131
-
132
- DESCRIPTION
133
-
134
- Generate a YAML template for your resume in the current directory.
135
-
136
- EXAMPLES
137
-
138
- resme init
139
- resme -o r.yml
140
- resme -o r.yml --force
141
- EOS
142
- return { init: [opts, :init, help] }
143
- end
144
-
145
- def self.md_opts
146
- opts = Slop::Options.new
147
- opts.banner = "md [-o output_filename] file.yml ..."
148
- opts.string "-o", "--output", "Output filename"
149
- help = <<EOS
150
- NAME
151
- #{opts.banner}
152
-
153
- SYNOPSYS
154
- #{opts.to_s}
155
-
156
- DESCRIPTION
157
-
158
- Generate a markdown resume from the YAML input files.
159
-
160
- EXAMPLES
161
-
162
- resme md -o r.md resume.yml
163
- EOS
164
- return { md: [opts, :md, help] }
165
- end
166
-
167
- def self.org_opts
168
- opts = Slop::Options.new
169
- opts.banner = "org [-o output_filename] file.yml ..."
170
- opts.string "-o", "--output", "Output filename"
171
- help = <<EOS
172
- NAME
173
- #{opts.banner}
174
-
175
- SYNOPSYS
176
- #{opts.to_s}
177
-
178
- DESCRIPTION
179
-
180
- Generate an org-mode resume from the YAML input files.
181
-
182
- EXAMPLES
183
-
184
- resme md -o r.md resume.yml
185
- EOS
186
- return { org: [opts, :org, help] }
187
- end
188
-
189
- def self.json_opts
190
- opts = Slop::Options.new
191
- opts.banner = "json [-o output_filename] file.yml ..."
192
- opts.string "-o", "--output", "Output filename"
193
- help = <<EOS
194
- NAME
195
- #{opts.banner}
196
-
197
- SYNOPSYS
198
- #{opts.to_s}
199
-
200
- DESCRIPTION
201
-
202
- Generate a JSON resume from the YAML input files.
203
-
204
- EXAMPLES
205
-
206
- resme json -o r.md resume.yml
207
- EOS
208
- return { json: [opts, :json, help] }
134
+ opts = OptionParser.new do |opts|
135
+ opts.banner = "init [options] # generate an empty resume.yml file"
136
+ opts.on("-o", "--output FILENAME", String, "Output filename")
137
+ opts.on("-f", "--force", FalseClass, "Overwrite existing file (if present)")
138
+ end
139
+
140
+ help = <<-EOS
141
+ NAME
142
+ #{opts.banner}
143
+
144
+ SYNOPSYS
145
+ #{opts.to_s}
146
+
147
+ DESCRIPTION
148
+ Generate a YAML template for your resume in the current directory.
149
+
150
+ EXAMPLES
151
+ resme init
152
+ resme init -o r.yml
153
+ resme init -o r.yml --force
154
+ EOS
155
+ {
156
+ init: {
157
+ name: :init,
158
+ options: opts,
159
+ help: help.gsub(" ", "")
160
+ }
161
+ }
209
162
  end
210
163
 
211
- def self.europass_opts
212
- opts = Slop::Options.new
213
- opts.banner = "europass [-o output_filename] file.yml ..."
214
- opts.string "-o", "--output", "Output filename"
215
- help = <<EOS
216
- NAME
217
- #{opts.banner}
164
+ def self.check_opts
165
+ opts = OptionParser.new do |opts|
166
+ opts.banner = "check resume.yml # Check syntax of resume.yml"
167
+ end
218
168
 
219
- SYNOPSYS
220
- #{opts.to_s}
169
+ help = <<-EOS
170
+ NAME
171
+ #{opts.banner}
172
+
173
+ SYNOPSYS
174
+ #{opts.to_s}
175
+
176
+ DESCRIPTION
177
+ Check whether a YAML file conforms with the RESME syntax.
178
+
179
+ EXAMPLES
180
+ resme check file.yml
181
+ EOS
182
+
183
+ {
184
+ check: {
185
+ name: :check,
186
+ options: opts,
187
+ help: help.gsub(" ", "")
188
+ }
189
+ }
190
+ end
221
191
 
222
- DESCRIPTION
192
+ def self.list_opts
193
+ opts = OptionParser.new do |opts|
194
+ opts.banner = "list resume.yml # List main sections in resume.yml"
195
+ end
223
196
 
224
- Generate a Europass XML resume from the YAML input files.
197
+ help = <<-EOS
198
+ NAME
199
+ #{opts.banner}
200
+
201
+ SYNOPSYS
202
+ #{opts.to_s}
203
+
204
+ DESCRIPTION
205
+ List main sections in resume.yml.
206
+
207
+ EXAMPLES
208
+ resme list file.yml
209
+ EOS
210
+
211
+ {
212
+ list: {
213
+ name: :list,
214
+ options: opts,
215
+ help: help.gsub(" ", "")
216
+ }
217
+ }
218
+ end
225
219
 
226
- EXAMPLES
227
-
228
- resme europass -o r.md resume.yml
229
- EOS
230
- return { europass: [opts, :europass, help] }
231
- end
220
+ def self.generate_opts
221
+ opts = OptionParser.new do |o|
222
+ o.banner = "generate [options] resume.yml ... # output resume"
223
+ o.on("-e", "--erb FILENAME", String, "Template to use")
224
+ o.on("-t", "--to FORMAT", String, "Output format")
225
+ o.on("-o", "--output FILENAME", String, "Output filename")
226
+ o.on("-s", "--skip SECTION,SECTION", Array, "Sections to skip")
227
+ end
232
228
 
229
+ help = <<-EOS
230
+ NAME
231
+ #{opts.banner}
232
+
233
+ SYNOPSYS
234
+ #{opts.to_s}
235
+
236
+ DESCRIPTION
237
+ Generate a resume from the YAML input files.
238
+
239
+ EXAMPLES
240
+ resme generate -t org resume.yml
241
+ resme generate -t md -o r.md section-1.yml section-2.yml
242
+ EOS
243
+
244
+ {
245
+ generate: {
246
+ name: :generate,
247
+ options: opts,
248
+ help: help.gsub(" ", "")
249
+ }
250
+ }
251
+ end
233
252
  end
234
253
  end
@@ -133,23 +133,26 @@ def has_day input
133
133
  end
134
134
  end
135
135
 
136
- # Access hash keys like they were class methods
137
- # hash["key"] -> hash.key
136
+ # Access hash keys like they were class methods (hash["key"] -> hash.key) and
137
+ # report errors if key is missing
138
138
  class Hash
139
139
  def method_missing(m)
140
140
  key = m.to_s
141
141
 
142
+ # we put a bit of info about the top level structure of a resume to avoid
143
+ # extra-long error messages I don't want to print detailed information
144
+ # about top-level entries missing in the resume
145
+ top_level_entries = %w[
146
+ contacts addresses web_presence summary work teaching projects other
147
+ committees volunteer visits education publications talks awards
148
+ achievements software skills languages driving interests references
149
+ ]
150
+
142
151
  # error: nil value
143
152
  if self.has_key? key and self[key] == nil
144
153
  $stderr.puts "[W] The value of key '#{key}' is nil in the following entry:"
145
154
 
146
- # we put a bit of info about the top level structure of a resume to avoid extra-long error messages
147
- # I don't want to print detailed information about top-level entries missing in the resume
148
- top_level_entries = [
149
- "contacts", "addresses", "web_presence", "summary", "work", "teaching", "projects", "other",
150
- "committees", "volunteer", "visits", "education", "publications", "talks", "awards", "achievements",
151
- "software", "skills", "languages", "driving", "interests", "references"]
152
- if not top_level_entries.include?(key) then
155
+ unless top_level_entries.include?(key)
153
156
  # $stderr.puts self.to_s
154
157
  self.keys.each do |k|
155
158
  $stderr.puts " #{k}: #{self[k]}"
@@ -160,18 +163,17 @@ class Hash
160
163
 
161
164
  return self[key] if self.has_key? key
162
165
 
163
- # we get here if the key is not found
164
- # we report an error, return "" and continue
165
- # the actual mileage might vary
166
+ # we get here if the key is not found we report an error, return
167
+ # "" and continue the actual mileage might vary
166
168
 
167
- # more error reporting: key not found
168
169
  $stderr.puts "[E] Key '#{key}' not found in the following entry:"
169
- # $stderr.puts self.to_s
170
- self.keys.each do |k|
171
- $stderr.puts " #{k}: #{self[k]}"
170
+ unless top_level_entries.include?(key)
171
+ self.keys.each do |k|
172
+ $stderr.puts " #{k}: #{self[k]}"
173
+ end
174
+ $stderr.puts ""
172
175
  end
173
- $stderr.puts ""
174
-
176
+
175
177
  return ""
176
178
  end
177
179
  end
@@ -1,8 +1,8 @@
1
- # <%= full_name data %>, <%= data.basics.title %>
1
+ # <%= full_name data %>, <%= data.basics&.title %>
2
2
 
3
3
  <%
4
- addresses = data.addresses.map { |x| "**#{x.label}**: #{x.street}, #{x.zip_code} #{x.city}" }
5
- presence = data.contacts.map { |x| "**#{x.label}:** #{x.value}" } + data.web_presence.map { |x| "<" + x.value + ">" }
4
+ addresses = (data["addresses"] || []).map { |x| "**#{x.label}**: #{x.street}, #{x.zip_code} #{x.city}" }
5
+ presence = (data["contacts"] || []).map { |x| "**#{x.label}:** #{x.value}" } + (data["web_presence"] || []).map { |x| "<" + x.value + ">" }
6
6
  -%>
7
7
  <%= presence.map { |x| "* #{x}" }.join("\n") %>
8
8
  <%= addresses.map { |x| "* #{x}" }.join("\n") %>
@@ -1,26 +1,29 @@
1
- #+TITLE: <%= full_name data %>, <%= data.basics.title %>
2
- #+AUTHOR: <%= data.contacts.select { |x| x.label == "email" }.first.value %>
1
+ #+TITLE: Curriculum Vitae
2
+ #+AUTHOR: <%= full_name data %>, <%= data.basics&.title %>
3
+ #+EMAIL: <%= (data["contacts"] || []).select { |x| x.label == "email" }.first&.value %>
3
4
  #+DATE: <<%= Date.today %>>
4
5
  #+STARTUP: showall
5
6
  #+OPTIONS: toc:nil num:nil
6
7
  #+OPTIONS: h:1
7
8
  #+OPTIONS: prop:nil
8
9
 
10
+ <% if data["addresses"] or data["contacts"] %>
9
11
  * Contacts
10
12
  :PROPERTIES:
11
- <% data.addresses.each do |x| -%>
13
+ <% (data["addresses"] || []).each do |x| -%>
12
14
  <%= ":#{x.label.upcase}: #{x.street}, #{x.zip_code} #{x.city}" %>
13
15
  <% end -%>
14
- <% data.contacts.each do |x| -%>
16
+ <% (data["contacts"] || []).each do |x| -%>
15
17
  <%= ":#{x.label.upcase}: #{x.value}" %>
16
18
  <% end -%>
17
19
  :END:
18
20
 
19
- <% data.contacts.each do |x| -%>
21
+ <% (data["contacts"] || []).each do |x| -%>
20
22
  | <%= "%-30s" % x.label %> | <%= "%-40s" % x.value %> |
21
23
  <% end -%>
24
+ <% end %>
22
25
 
23
- <% if data["work"] -%>
26
+ <% if data["summary"] -%>
24
27
  * Summary
25
28
 
26
29
  <%= reflow_to_string data.summary, 78 -%>
@@ -40,7 +43,7 @@
40
43
  * Work Experience
41
44
 
42
45
  <% (data.work || []).each do |item| -%>
43
- ** *<%= period item %>: <%= clean [item.role, item.who].join(", ") %>*
46
+ ** <%= period item %>: <%= clean [item.role, item.who].join(", ") %>
44
47
  <%= propertify item, " " %>
45
48
 
46
49
  <%= reflow_to_string item["summary"], 72, " " -%>
@@ -52,7 +55,7 @@
52
55
  * Teaching
53
56
 
54
57
  <% (data.teaching || []).each do |item| -%>
55
- ** *<%= period item %>: <%= item.subject %>*
58
+ ** <%= period item %>: <%= item.subject %>
56
59
  <%= propertify item, " " %>
57
60
 
58
61
  <%= [item["role"], item["school"], item["who"]].join(", ") %>
@@ -64,7 +67,7 @@
64
67
  * Projects
65
68
 
66
69
  <% (data.projects || []).each do |item| -%>
67
- ** *<%= period item %>: <%= [item.name, item.role].join(", ") %>*
70
+ ** <%= period item %>: <%= [item.name, item.role].join(", ") %>
68
71
  <%= propertify item, " " %>
69
72
 
70
73
  <%= reflow_to_string item["summary"], 72, " " -%>
@@ -73,10 +76,10 @@
73
76
  <% end -%>
74
77
 
75
78
  <% if data["other"] -%>
76
- * Other Initiatives
79
+ * Other
77
80
 
78
81
  <% (data.other || []).each do |item| -%>
79
- ** *<%= period item %>: <%= [item["who"], item["role"]].join(", ") %>*
82
+ ** <%= period item %>: <%= [item["who"], item["role"]].join(", ") %>
80
83
  <%= propertify item, " " %>
81
84
 
82
85
  <%= reflow_to_string item["summary"], 72, " " -%>
@@ -150,7 +153,7 @@
150
153
  * <%= group.capitalize %>
151
154
 
152
155
  <% (group || []).each do |item| -%>
153
- ** *<%= item.date %>: <%= [item.title, item.who, item.address].join(", ") %>*
156
+ ** <%= item.date %>: <%= [item.title, item.who, item.address].join(", ") %>
154
157
  <%= propertify item, " " %>
155
158
 
156
159
  <%= reflow_to_string item.summary, 72, " " -%>