Compare commits

..

No commits in common. "502749c838ccd5f9021bfd23f4d7234b8b80c44f" and "493193872f85ebfe51e83eb017f693bcb42cfcea" have entirely different histories.

6 changed files with 644 additions and 666 deletions

950
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,13 +2,13 @@
name = "panres"
version = "0.1.0"
authors = ["Edward Shen <code@eddie.sh>"]
edition = "2021"
edition = "2018"
[dependencies]
tera = "1"
clap = { version = "3", features = ["derive", "cargo"] }
tera = "1.0.0-beta.13"
clap = "2"
serde = "1"
serde_json = "1"
json5 = "0.4"
notify = "5.0.0-pre.15"
crossbeam = "0.8"
serde_json = "1.0"
json5 = "0.2.8"
notify = "5.0.0-pre.3"
crossbeam = "0.7"

View file

@ -2,10 +2,10 @@
"author": {
"name": "Edward Shen",
"addresses": {
"home": "550 Moreland Way Apt 4410, Santa Clara, CA 95054",
"home": "8080 Highland Farms Drive, East Amherst, NY 14051",
"school": "480 Parker Street, Boston, MA 02115"
},
"email": "hi@eddie.sh",
"email": "code@eddie.sh",
"phone": "(716) 491-3343",
"website": "eddie.sh",
"github": "edward-shen",
@ -19,17 +19,22 @@
"school": "Northeastern University",
"college": "Khoury College of Computer Sciences",
"location": "Boston, MA",
"start": "Sep. 2017",
"end_date": "May 2021",
"start": "Sept. 2017",
"end": "Present",
"end_date": "Present (May 2021)",
"list": [
{
"name": "degree",
"desc": "Bachelor of Science in Computer Science"
"desc": "Candidate for a Bachelor of Science in Computer Science"
},
{
"name": "honors",
"desc": "3.85 / 4.00; summa cum laude; Dean's List"
"desc": "3.84 / 4.00, Dean's List"
},
{
"name": "courses",
"desc": "Data Collection, Integration, and Analysis; Machine Learning/Data Mining 1; Algorithms and Data; Object-Oriented Design; Networks and Distributed Systems"
}
]
},
"skills": [
@ -37,82 +42,63 @@
"name": "languages",
"desc": [
{
"level": "primary",
"langs": "Rust",
"level": "proficient",
"langs": "Rust, Python, TypeScript, HTML5, CSS"
},
{
"level": "secondary",
"langs": "Python, Bash",
"level": "familiar",
"langs": "JavaScript, Java, LaTeX, C++, Bash"
},
{
"level": "auxiliary",
"langs": "C, C++, TypeScript",
"level": "explored",
"langs": "C, Ruby, Racket, Scala"
}
]
},
{
"name": "recent technology",
"desc": "cxx.rs, libc, fbthrift, cgroups v2",
"name": "other",
"desc": "Git, (Arch) Linux, VS Code, Raspberry Pi"
},
{
"name": "miscellaneous",
"desc": "Regex, LaTeX"
},
{
"name": "interests",
"desc": "Rhythm games; Self-hosting; Security; Scalability; Free software",
"name": "certs",
"desc": "CompTIA A+, Dell Certified Technician, Apple Certified Mac Technician"
}
],
"experiences": [
{
"title": "Production Engineer",
"company": "Meta",
"location": "Menlo Park, CA",
"start": "Sep. 2021",
"end": "Present",
"notes": [
"Joined the PE Executable Access Control team to identify, track, and jail untrusted binaries running on internal hosts.",
"Tech lead for Alcatraz, an internal binary that presents common frontend for process-level jailing backends.",
"Advocate for Rust adoption, volunteering for Rust code reviews and presenting Rust talks to teams.",
]
},
{
"title": "SEAR Intern",
"company": "Apple",
"location": "Cupertino, CA",
"remote": true,
"start": "Aug. 2020",
"end": "Dec. 2020",
"notes": [
"Joined the Trusted Execution team, focused on code execution across the Apple ecosystem.",
"Planned, driven, and completed proof-of-concept for iOS 16's Lockdown Mode.",
"Developed kernel and bootloader security policies focused on attack surface reduction.",
]
},
// {
// "title": "Software Development Engineer Intern",
// "company": "Apple",
// "location": "Menlo Park, CA",
// "start": "Aug. 2020",
// "end": "Dec. 2020",
// "notes": [
// "sekureetee"
// ]
// },
{
"title": "Production Engineer Intern",
"company": "Facebook",
"location": "Menlo Park, CA",
"remote": true,
"start": "May 2020",
"end": "Aug. 2020",
"notes": [
"Rewritten Python config generation in multithreaded asynchronous Rust, reducing overall runtime by 80\\% on large inputs and improving runtime of profiled areas by a factor of 36.6.",
"Designed core Rust libraries for foundational services for ubiquitous use across all Rust applications.",
"Highlighted as a top intern project for the Production Engineering organization."
"Detected and resolved soundness issues and misconfigurations in existing python code to preempt Severity 1 site events."
]
},
{
"title": "Software Engineer Intern",
"company": "Datto",
"location": "Boston, MA",
"start": "Aug. 2019",
"end": "Dec. 2019",
"notes": [
"Refactored frontend codebase to utilize Typescript, Webpack, and Babel while reducing average JS footprint by 98\\% percent, from 10.4MB to 250KB.",
"Assisted and completed developer environment virtualization project to reduce onboarding time for new developers by 5 days.",
"Integrated into Scrum team that focused on re-implementation of license management systems in a legacy Ruby codebase to Scala and PHP."
]
},
// {
// "title": "Software Engineer Intern",
// "company": "Datto",
// "location": "Boston, MA",
// "start": "Aug. 2019",
// "end": "Dec. 2019",
// "notes": [
// "Refactored frontend codebase to utilize Typescript, Webpack, and Babel while reducing average JS footprint by 98\\% percent, from 10.4MB to 250KB.",
// "Integrated into Scrum team that focused on re-implementation of license management systems in a legacy Ruby codebase to Scala and PHP."
// ]
// },
{
"title": "Production Engineer Intern",
"company": "Facebook",
@ -121,7 +107,8 @@
"end": "Aug. 2019",
"notes": [
"Implemented a disaster mitigation for decentralized service discovery when upstream data source is unavailable or in a degraded state.",
"Designed an out-of-band flow to resolve core infrastructure services dependent on service discovery in disaster scenarios to minimize downtime for all Facebook products.",
"Designed an out-of-band flow to allow resolution of core infrastructure services dependent on service discovery in disaster scenarios to minimize downtime for all Facebook products.",
"Modernized and restructured core tooling to improve reliability and testing."
]
}
],

View file

@ -1,14 +1,13 @@
#![forbid(unsafe_code)]
use clap::{crate_authors, crate_version, Parser};
use crossbeam::channel::unbounded;
use clap::{crate_authors, crate_version, App, AppSettings, Arg};
use crossbeam::crossbeam_channel::unbounded;
use json5::from_str;
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use serde_json::Value;
use std::env;
use std::error::Error;
use std::fs::{create_dir_all, read_dir, read_to_string, write};
use std::path::{Path, PathBuf};
use std::process;
use tera::{Context, Error as TeraError, Tera};
@ -29,51 +28,60 @@ fn env_or_default(env_name: &str, default: &str) -> String {
env::var(env_name).unwrap_or_else(|_| String::from(default))
}
/// Universal resume formatter
#[derive(Parser)]
#[clap(version = crate_version!(), author = crate_authors!())]
struct Args {
/// Watch for changes
#[clap(short)]
watch: bool,
/// Specifies which output format you want
#[clap(short, long, multiple_occurrences = true)]
output: Vec<String>,
}
fn run() -> Result<(), Box<dyn Error>> {
let config: Value = from_str(&read_to_string("config.json5")?)?;
let template_dir = env_or_default("PANRES_TEMPLATE_DIR", DEFAULT_TEMPLATE_DIR);
let output_dir = env_or_default("PANRES_OUTPUT_DIR", DEFAULT_OUTPUT_DIR);
let args = Args::parse();
let matches = get_args();
let tera = Tera::new(&format!("{template_dir}/**/*"))?;
let tera = Tera::new(&format!("{}/**/*", template_dir))?;
let mut context = Context::new();
context.insert("config", &config);
let template_dir = PathBuf::from(template_dir);
let outputs: Vec<String> = matches
.values_of("output-format")
.unwrap_or_default()
.map(String::from)
.collect();
output(&tera, &context, &output_dir, &args.output, &template_dir)?;
output(&tera, &context, &output_dir, &outputs, &template_dir)?;
if args.watch {
watch_mode(tera, context, output_dir, args.output, &template_dir)?;
if matches.is_present("watch") {
watch_mode(tera, context, output_dir, outputs, template_dir)?;
}
Ok(())
}
/// Returns the args passed by the user.
fn get_args() -> clap::ArgMatches<'static> {
App::new("panres")
.version(crate_version!())
.author(crate_authors!())
.about("Universal resume formatter")
.arg(Arg::with_name("watch").short("w").help("Watch for changes"))
.arg(
Arg::with_name("output-format")
.help("Specifies which output format you want")
.required(true)
.multiple(true),
)
.settings(&[AppSettings::ArgRequiredElseHelp])
.get_matches()
}
/// Usually never returns, unless there was an error initializing the watcher.
/// Handles watching for file changes, and reloads tera if there's a change.
fn watch_mode(
fn watch_mode<'a>(
mut engine: Tera,
context: Context,
dir: String,
outputs: Vec<String>,
template_dir: &Path,
template_dir: String,
) -> Result<(), Box<dyn Error>> {
let (tx, rx) = unbounded();
let mut watcher: RecommendedWatcher = Watcher::new(move |res| tx.send(res).unwrap())?;
watcher.watch(template_dir, RecursiveMode::Recursive)?;
let mut watcher: RecommendedWatcher = Watcher::new_immediate(move |res| tx.send(res).unwrap())?;
watcher.watch(&template_dir, RecursiveMode::Recursive)?;
for res in rx {
match res {
@ -81,7 +89,7 @@ fn watch_mode(
Ok(event) => {
println!("got event {:?}", event);
engine.full_reload().expect("Failed to perform full reload");
output(&engine, &context, &dir, &outputs, template_dir)
output(&engine, &context, &dir, &outputs, &template_dir)
.expect("Failed to call output");
}
}
@ -92,12 +100,12 @@ fn watch_mode(
/// Parses the output values and generates a file for each format specified or
/// found, if told to generate all outputs.
fn output(
fn output<'a>(
engine: &Tera,
context: &Context,
dir: &str,
outputs: &[String],
template_dir: &Path,
template_dir: &'a str,
) -> Result<(), Box<dyn Error>> {
if outputs.contains(&String::from("all")) {
for output in read_dir(template_dir)? {

View file

@ -9,7 +9,6 @@
\usepackage{multirow}
\usepackage{colortbl} % Colored table vlines
\usepackage{graphicx} % Rotate text
\usepackage[hidelinks]{hyperref} % Clickable PDF URLs
% macros which are illegal in .sty (primarily just font awesome stuff)
@ -23,111 +22,93 @@
\setmainfont{Corbert}
% Set up table styles
\arrayrulecolor{AccentColor}
\arrayrulecolor{red}
\setlength\arrayrulewidth{1.2pt}
\begin{tabularx}{\textwidth}{X c l}
\multirow[b]{3}{*}{\name}
& \accent{\glyph{"F0AC}} & \href{
https://{{ config.author.website }}
}{
{{ config.author.website }}
}\\
& \accent{\glyph{"F003}} & \href{
mailto:{{ config.author.email }}
}{
{{ config.author.email }}
} \\
& \accent{\glyph{"F09B}} & \href {
https://github.com/{{ config.author.github }}
}{
{{ config.author.github }}
}
& \accent{\glyph{"F0AC}} & {{ config.author.website }} \\
& \accent{\glyph{"F003}} & {{ config.author.email }} \\
& \accent{\glyph{"F09B}} & {{ config.author.github }}
\end{tabularx}
% Contact info
\begin{tabularx}{\textwidth}{c X c}
{
\begin{tabularx}{\textwidth}{ c | r X r }
\sectiontitle{Education} \\[-8pt]
{% raw -%}
& \widel{ {\large\title{%
{% endraw -%}
{{ config.education.school }}}}\hint{ {{ config.education.location }}}} & {{ config.education.start }}---{{ config.education.end_date }} \\
& \widel{\footnotesize {{ config.education.college }}} \\
{% for row in config.education.list -%}
{% raw -%}
& \hint{%
{% endraw -%}
{{ row.name | title }}:} &
{% raw -%}
\multicolumn{2}{X}{%
{% endraw -%}
{{ row.desc }}} \\
{% endfor -%}
\begin{tabularx}{300pt}{c | r r r }
\sectiontitle{Experiences\;\;}
\spacer
\sectiontitle{Skills} \\[-8pt]
{% for row in config.skills -%}
& \hint{ {{ row.name | title }}:} &
{% raw -%}
\multicolumn{2}{X}{%
{% endraw -%}
{% if row.name == "languages" -%}
\multirow{3}{*}{
\begin{tabularx}{\textwidth}{ r l }
{% for group in row.desc -%}
{% raw -%}
\hint{%
{% endraw -%}
{{ group.level | title }}:} & {{ group.langs }} \\
{% endfor -%}
\end{tabularx}
} \newline \newline % 100% hack pls fix
{% else -%}
{{ row.desc }}
{% endif -%}
}\\
{% endfor -%}
\end{tabularx}
\begin{tabularx}{\textwidth}{c | r X r }
\sectiontitle{Experiences}
{% for experience in config.experiences -%} \\[-8pt]
{% raw -%}
& \widel{\large\title{%
{% endraw -%}
{{ experience.company }}}\hint{ {{experience.title }} }} & {{ experience.start }}---{{ experience.end }} \\
& \widel{\footnotesize {{ experience.location }}
{% if experience.remote -%}
\color[rgb]{.8,.8,.8}{(Remote)}
{% endif -%}
} \\[-8pt]
\\
& \widel{\footnotesize {{ experience.location }}} \\
{% for note in experience.notes -%}
& \bullet
{% raw -%}
& \widex{%
{% endraw -%}
{{note}}
} \\[-8pt]
\\
{{note}}} \\
{% endfor -%}
\\[-8pt]
{% endfor -%}
\end{tabularx}
}
& &
{
\begin{tabularx}{150pt}{ c | X }
\sectiontitle{Degree\;\;} \\[-8pt]
\begin{tabularx}{\textwidth}{c | r X r }
\sectiontitle{Projects}
{% for project in config.projects -%} \\[-8pt]
{% raw -%}
& {\large\title{%
& \widel{\large\title{%
{% endraw -%}
{{ config.education.school }}
}} \\
& \footnotesize{ {{ config.education.location }}} \\
& \hint{Date}\\
& {{ config.education.start }}---{{ config.education.end_date }} \\
{% for row in config.education.list -%}
{{ project.name }}}\hint{ {{ project.lang }} }} \\
{% for note in project.notes -%}
& \bullet
{% raw -%}
& \hint{%
& \widex{%
{% endraw -%}
{{ row.name | title }}} \\
& {{ row.desc }} \\
{{note}}} \\
{% endfor -%}
\\[-8pt]
\\
\spacer
\spacer
\spacer
\spacer
\sectiontitle{Skills and Interests\;\;} \\[-8pt]
{% for row in config.skills -%}
{% raw -%}
& \title{%
{% endraw -%}
{{ row.name | title }}} \\
{% if row.name == "languages" -%}
{% for group in row.desc -%}
{% raw -%}
& \hint{%
{% endraw -%}
{{ group.level | title }}} \\
& {{ group.langs }} \\
{% endfor -%}
{% else -%}
& \begin{flushleft}
{{ row.desc }} \\
\end{flushleft}
{% endif -%}
\\[-8pt]
\\
{% endfor -%}
\end{tabularx}
}
\end{tabularx}
\end{document}

View file

@ -8,11 +8,9 @@
]
\newfontfamily{\fa}{FontAwesome}
\definecolor{AccentColor}{HTML}{238de4}
{% raw %}
% Changes the color of any text inside to the accent color
\renewcommand{\accent}[1] {{\color{AccentColor}{#1}}}
\renewcommand{\accent}[1] {{\color{red}{#1}}}
{% endraw %}
{% raw %}