From 318ea11ac6e3db191d129d9c587d62dd09318706 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 14 Sep 2024 22:13:34 +0200 Subject: [PATCH] Add simple typst cv replacement --- cv.typ | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 cv.typ diff --git a/cv.typ b/cv.typ new file mode 100644 index 0000000..e1c5ade --- /dev/null +++ b/cv.typ @@ -0,0 +1,135 @@ +#show heading: set text(font: "New Computer Modern") +#show link: underline + +// Uncomment the following lines to adjust the size of text +// The recommend resume text size is from `10pt` to `12pt` +// #set text( +// size: 12pt, +// ) + +// Choose the compiled language through cli by doing +// +// $ typst compile --input lang=de cv.typ +// +#let lang = { + if "lang" in sys.inputs and sys.inputs.lang == "de" { + "de" + } else { + "en" + } +} + +// Feel free to change the margin below to best fit your own CV +#set page( + paper: "a4", + margin: (x: 0.9cm, y: 1.3cm), + footer: context [ + #set text(8pt) + #text(fill:luma(230))[Marty Oehme] + #set align(right) + #text(fill:luma(230))[#counter(page).display("1",both:false)] + ] +) + +#set par(justify: true) + +#let horizon_line() = {v(-3pt); line(length: 100%); v(-5pt)} + +#let section_header(title) = {[== #title]; horizon_line()}; + +#let section(title: "Section", body) = { + section_header(title); + body +}; + +#let work_item(item: ()) = { + if "client" in item { + [*#item.title.at(lang)*, _#item.client.at(lang)_ #h(1fr)]; + } else { + [*#item.title.at(lang)* #h(1fr)]; + }; + [ _#item.date.at(lang)_ \ ]; + if "bullets" in item { + for bullet in item.bullets { + [- #bullet.at(lang)] + } + } + if "publication" in item { + block(inset: 5%, width: 85%, text(fill:luma(150))[#item.publication.at(lang) \ ]) + }; +} + +#let education_item(item: ()) = { + assert("place" in item and "program" in item and "date" in item, message: "Education items require place, program and date."); + [*#item.place.at(lang)*, #item.program.at(lang) #h(1fr)]; + [ _#item.date.at(lang)_ \ ]; +} + +#let thesis_item(item: ()) = { + assert("type" in item and "title" in item, message: "Thesis items require type and title."); + [*#item.type.at(lang)* #item.title.at(lang) #h(1fr)]; + [#par(item.abstract.at(lang))] +} + +#let skill_item(item: ()) = { + [*#item.at(lang)*: \ ] + for skill in item.content { + [#skill.name.at(lang) (] + for (i, v) in skill.items.enumerate() { + [#v.at(lang)] + if i < skill.items.len() - 1 { + [, ] + } + } + [) \ ] + } +} + +#let resume(contents) = { + [= #contents.about.fullname]; + let contacts = (for c in contents.about.contact { + (c.icon + " " + c.text,) + }) + grid( + columns: (1.5fr, 1fr, 1fr), + gutter: 5pt, + ..contacts + ); + horizon_line(); + if "summary" in contents { + contents.summary.at(lang) + }; + + if "experience" in contents { + section(title: "Professional Experience",{ + for entry in contents.experience { + work_item(item:entry) + } + }) + } + + if "education" in contents { + section(title: "Education",{ + for entry in contents.thesis { + thesis_item(item:entry) + } + for entry in contents.education { + education_item(item:entry) + } + }) + } + + if "skills" in contents { + section(title: "Qualifications",{ + for cat in contents.skills { + skill_item(item:cat) + } + }) + } +} + + +#resume( + yaml("content.yml") +) +