Skip to content

Commit

Permalink
WIP CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
Theo-Hafsaoui committed Nov 3, 2024
1 parent 5e16a72 commit afb7a62
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 155 deletions.
100 changes: 34 additions & 66 deletions assets/latex/template/template.tex
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
%-------------------------
% Resume in Latex
% Author : Jake Gutierrez
% Based off of: https://github.com/sb2nov/resume
% License : MIT
%------------------------

\documentclass[letterpaper,11pt]{article}

\usepackage{latexsym}
\usepackage[empty]{fullpage}
\usepackage{titlesec}
Expand All @@ -21,34 +16,13 @@
\usepackage{xcolor}
\usepackage[english]{babel}
\usepackage{tabularx}
\definecolor{Nblack}{HTML}{3b4252}
\definecolor{NBLACK}{HTML}{2e3440}
\definecolor{Nwhite}{HTML}{eceff4}
\definecolor{nwhite}{HTML}{e5e9f0}
\definecolor{Nblue}{HTML}{5e81ac}
\definecolor{Nurl}{HTML}{8fbcbb}
\definecolor{nblue}{HTML}{005A92}
\definecolor{nblue}{HTML}{005A92}
\input{glyphtounicode}


%----------FONT OPTIONS----------
% sans-serif
% \usepackage[sfdefault]{FiraSans}
% \usepackage[sfdefault]{roboto}
% \usepackage[sfdefault]{noto-sans}
% \usepackage[default]{sourcesanspro}

% serif
% \usepackage{CormorantGaramond}
% \usepackage{charter}


\pagestyle{fancy}
\fancyhf{} % clear all header and footer fields
\fancyhf{}
\fancyfoot{}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}

% Adjust margins
\addtolength{\oddsidemargin}{-0.5in}
\addtolength{\evensidemargin}{-0.5in}
Expand Down Expand Up @@ -120,43 +94,37 @@

\begin{document}

\begin{center}
\textbf{\Huge \scshape \textcolor{nblue}{Anemon Vincent}} \\ \vspace{1pt}
\small +33 6 26 26 50 07 $|$ \href{mailto:anemon@pm.me}{\underline{anemon@pm.me}} \\
\href{https://linkedin.com/in/anemon/}{\underline{linkedin.com/in/anemon}} $|$
\href{https://github.com/anemon}{\underline{github.com/anemon}}
\end{center}

\begin{center}
\textbf{\Huge \scshape \textcolor{nblue}{Anemon Vincent}} \\ \vspace{1pt}
\small +33 6 26 26 50 07 $|$ \href{mailto:anemon@pm.me}{\underline{anemon@pm.me}} \\
\href{https://linkedin.com/in/anemon/}{\underline{linkedin.com/in/anemon}} $|$
\href{https://github.com/anemon}{\underline{github.com/anemon}}
\end{center}

%-----------EDUCATION-----------
\section{EDUCATION}
\resumeSubHeadingListStart
%EDUCATION_SECTIONS%
\resumeSubHeadingListEnd

%-----------EXPERIENCE-----------
\section{EXPERIENCE}
\resumeSubHeadingListStart
%EXPERIENCE_SECTIONS%
\resumeSubHeadingListEnd

%-----------PROJECTS-----------
\section{Projects}
\resumeSubHeadingListStart
%PROJECTS_SECTIONS%
\resumeSubHeadingListEnd

%-----------PROGRAMMING SKILLS-----------
\section{Technical Skills}
\begin{itemize}[leftmargin=0.15in, label={}]
%SKILL_SECTIONS%
\end{itemize}

%-------------------------------------------

%-----------EDUCATION-----------
\section{EDUCATION}
\resumeSubHeadingListStart
%EDUCATION_SECTIONS%
\resumeSubHeadingListEnd


%-----------EXPERIENCE-----------
\section{EXPERIENCE}
\resumeSubHeadingListStart
%EXPERIENCE_SECTIONS%
\resumeSubHeadingListEnd



%-----------PROJECTS-----------
\section{Projects}
\resumeSubHeadingListStart
%PROJECTS_SECTIONS%
\resumeSubHeadingListEnd



%
%-----------PROGRAMMING SKILLS-----------
\section{Technical Skills}
\begin{itemize}[leftmargin=0.15in, label={}]
%SKILL_SECTIONS%
\end{itemize}

%-------------------------------------------
\end{document}
64 changes: 5 additions & 59 deletions cmd/generate.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package cmd

import (
m_lang "anemon/internal/markup_languages"
"anemon/internal/walker"
"errors"
"anemon/internal/adapters/input"
"os"
"strings"

"github.com/spf13/cobra"
)

Expand All @@ -15,64 +11,14 @@ var generateCmd = &cobra.Command{
Short: "Generate a CV",
Long: `Generate a CV using the Markdown CV directory in the current work directory`,
RunE: func(cmd *cobra.Command, args []string) error{
dir, err := os.Getwd()
if err != nil{
return err
}
CV,err := getSectionMapFrom(dir)
if err != nil {
return err
}
err = createLatexCVFrom(dir,CV)
if err != nil {
return err
}
root, err := os.Getwd()
if err != nil{ return err }
err = input.GenerateCVFromMarkDownToLatex(root)
if err != nil { return err }
return nil
},
}

//Use a CV map created by `getSectionMapFrom` and write for each lang key a latex CV using the given information
func createLatexCVFrom(dir string, CV map[string]map[string]string )(error){
for lang := range CV{
err := m_lang.Init_output(lang+"-CV",dir)
if err != nil{
return err
}
for sec_name := range CV[lang]{
for _,paragraphe := range strings.Split(CV[lang][sec_name], "\n\n"){
if len(paragraphe)<=1 {
continue
}
sec, err := m_lang.Parse(paragraphe)
if err != nil {
return err
}
_,err = m_lang.ApplyToSection(sec,sec_name,dir+"/assets/latex/output/"+lang+"-CV.tex")
if err != nil {
return err
}
}
}
}
return nil
}

//TODO consider struct for this map of map
//Walk throught the CV directory and return a map of lang within each their is a map of section
func getSectionMapFrom(dir string)(map[string]map[string]string,error){
cv_path := dir+"/cv"
_, err := os.Stat(cv_path)
if err != nil{
if os.IsNotExist(err) { return nil, errors.New("No `cv` directory found at:"+cv_path) }
return nil,err
}
result, err := walker.WalkCV(cv_path)
if err != nil{
return nil,err
}
return result,nil
}

func init() {
rootCmd.AddCommand(generateCmd)
}
14 changes: 14 additions & 0 deletions internal/adapters/input/cli.go
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
package input

import (
"anemon/internal/adapters/output"
"anemon/internal/core"
)

//Use the implementation for markdown and latex to generate latex CV from a tree dir of mardown document
func GenerateCVFromMarkDownToLatex(root string)error{
var source core.Source = &MarkdownSource{}
var templateReader core.TemplateReader = &output.LatexReader{}
var templateProccesor core.TemplateProcessor = &output.LatexProccesor{}
service := &core.CVService{}
return service.GenerateTemplates(root,source,templateReader,templateProccesor)
}
22 changes: 10 additions & 12 deletions internal/adapters/input/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ var(
relativePath string
content string
}{
{"eng/education.md", work_input},
{"eng/project.md", work_input},
{"eng/work.md", work_input},
{"eng/skill.md", skill_input},
{"fr/education.md", work_input},
{"fr/work.md", work_input},
{"fr/skill.md", skill_input},
{"cv/eng/education.md", work_input},
{"cv/eng/project.md", work_input},
{"cv/eng/work.md", work_input},
{"cv/eng/skill.md", skill_input},
{"cv/fr/education.md", work_input},
{"cv/fr/work.md", work_input},
{"cv/fr/skill.md", skill_input},
}

)
Expand Down Expand Up @@ -117,8 +117,8 @@ func TestSections(t *testing.T) {
}

t.Run("Should return a valid list of cv", func (t *testing.T) {
got,err := GetCVsFrom(rootDir)
got[1].Print()
source := MarkdownSource{}
got,err := source.GetCVsFrom(rootDir)
if err!=nil{
t.Fatalf("Failed to getCV got %s",err)
}
Expand All @@ -144,9 +144,7 @@ func TestSections(t *testing.T) {
p_t_sec_got := got[len(got)-1].Sections[len(got[len(got)-1].Sections)-1].Paragraphes
p_t_s_want := work_expected_result

if len(p_t_sec_got) != len(p_t_s_want){
t.Fatalf("Should have len %d got %d",len(p_t_s_want),len(p_t_sec_got))
}
if len(p_t_sec_got) != len(p_t_s_want){ t.Fatalf("Should have len %d got %d",len(p_t_s_want),len(p_t_sec_got)) }

if p_t_sec_got[len(p_t_sec_got)-1].H1 != p_t_s_want[len(p_t_s_want)-1].H1{
t.Fatalf("Should have title %s got %s",p_t_s_want[len(p_t_s_want)-1].H1,p_t_sec_got[len(p_t_sec_got)-1].H1)
Expand Down
10 changes: 6 additions & 4 deletions internal/adapters/input/markdown_tree_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,27 @@ import (
"strings"
)

type MarkdownSource struct{}

var hashtagRegex = regexp.MustCompile(`^#+`)

// `GetCVFrom` takes a root directory and extracts Markdown documents to generate a list of CV type.
//
// This function assumes the directory structure is a tree with a depth of 3, where each leaf
// is a Markdown (.md) document. Each document may contain multiple paragraphs, but the headers
// should not repeat within the same document.
func GetCVsFrom(root string) ([]core.CV, error) {
func (*MarkdownSource) GetCVsFrom(root string) ([]core.CV, error) {
cvsPath := root+"/cv"
cvs := make([]core.CV,0)

current_lang := ""
current_sections := make([]core.Section,0)
has_been_inside_dir := false

err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
err := filepath.Walk(cvsPath, func(path string, info os.FileInfo, err error) error {
if err != nil { return err }
if info.IsDir(){
if has_been_inside_dir {
println( cvs[len(cvs)-2].Lang )
cvs[len(cvs)-1].Sections=current_sections
current_sections = make([]core.Section,0)
has_been_inside_dir = false
Expand All @@ -36,7 +39,6 @@ func GetCVsFrom(root string) ([]core.CV, error) {
cvs = append(cvs, core.CV{Lang: current_lang})
}
if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") {
println( len(current_sections) )
has_been_inside_dir = true
if current_lang == "" { return errors.New("markdown file found before lang directory") }
content, err := os.ReadFile(path)
Expand Down
12 changes: 8 additions & 4 deletions internal/adapters/output/latex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ func TestApplySectionToTemplate(t *testing.T) {
\resumeItemListEnd
End`)

got, err := ApplySectionToTemplate(template, headers, items, "Professional")
processor := LatexProccesor{}
got, err := processor.ApplySectionToTemplate(template, headers, items, "Professional")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -50,7 +51,8 @@ End`)
\resumeItemListEnd
End`)

got, err := ApplySectionToTemplate(template, headers, items, "Project")
processor := LatexProccesor{}
got, err := processor.ApplySectionToTemplate(template, headers, items, "Project")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -64,7 +66,8 @@ End`)
headers := []string{"Company Name", "Position", "https://company.com", "Company"}
items := []string{"Task 1", "Task 2"}

_, err := ApplySectionToTemplate(template, headers, items, "UnsupportedSection")
processor := LatexProccesor{}
_, err := processor.ApplySectionToTemplate(template, headers, items, "UnsupportedSection")
if err == nil || err.Error() != "Don't know type UnsupportedSection" {
t.Errorf("expected error 'Don't know type UnsupportedSection', got %v", err)
}
Expand All @@ -85,7 +88,8 @@ End`)
\resumeItemListEnd
End`)

got, err := ApplySectionToTemplate(template, headers, items, "Project")
processor := LatexProccesor{}
got, err := processor.ApplySectionToTemplate(template, headers, items, "Project")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down
17 changes: 9 additions & 8 deletions internal/adapters/output/latex_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@ import (
"os"
)

type LatexReader struct{}
type LatexProccesor struct{}


//Write the template file in the assets directory
func makeNewTemplate(path string, template string, name string)error{
func (*LatexProccesor)MakeNewTemplate(path string, template string, name string)error{
err := os.WriteFile(path+"/assets/latex/output/"+name,
[]byte(template), 0644)
return err
}

//Read the template file in the assets directory from the root dir
func readCVTemplate(root string)(string, error){
func (*LatexReader)ReadCVTemplate(root string)(string, error){
file, err := os.ReadFile(root+"/assets/latex/template/template.tex")
if err != nil {
return "", err
}
return string(file), nil
}

//In the core we will read the template
//iterate by section
//Apply to template
//Write

//Apply a section to a section type on a latex template
func ApplySectionToTemplate(template string, headers []string,item []string, section string) (string,error){
func (*LatexProccesor)ApplySectionToTemplate(template string, headers []string,item []string, section string) (string,error){
if len(section)<2{ return "",errors.New("Don't know type "+section) }
section = strings.ToUpper(string(section[0]))+section[1:]
switch{
case section == "Professional":
template = replaceWithSectionTemplate(template,ProfessionalTemplate,
Expand All @@ -46,6 +46,7 @@ func ApplySectionToTemplate(template string, headers []string,item []string, sec
template = replaceWithSectionTemplate(template,SkillTemplate,
headers,nil)
default:
fmt.Println("Don't know type "+section)
return "",errors.New("Don't know type "+section)
}
return template,nil
Expand Down
Loading

0 comments on commit afb7a62

Please sign in to comment.