show timespan in experience entries

This commit is contained in:
Sina Atalay 2023-10-01 21:22:42 +02:00
parent 920cf379cf
commit 0107906480
4 changed files with 57 additions and 60 deletions

View File

@ -3,11 +3,7 @@ This module is a script to run the RenderCV and generate a CV as a PDF.
"""
import os
import json
import logging
import re
from jinja2 import Environment, FileSystemLoader
from ruamel.yaml import YAML

View File

@ -121,38 +121,38 @@ def compute_time_span_string(start_date: Date, end_date: Date) -> str:
str: The time span string.
"""
# calculate the number of days between start_date and end_date:
timeSpanInDays = (end_date - start_date).days
timespan_in_days = (end_date - start_date).days
# calculate the number of years between start_date and end_date:
howManyYears = timeSpanInDays // 365
if howManyYears == 0:
howManyYearsString = None
elif howManyYears == 1:
howManyYearsString = "1 year"
how_many_years = timespan_in_days // 365
if how_many_years == 0:
how_many_years_string = None
elif how_many_years == 1:
how_many_years_string = "1 year"
else:
howManyYearsString = f"{howManyYears} years"
how_many_years_string = f"{how_many_years} years"
# calculate the number of months between start_date and end_date:
howManyMonths = round((timeSpanInDays % 365) / 30)
if howManyMonths == 0:
howManyMonths = 1
how_many_months = round((timespan_in_days % 365) / 30)
if how_many_months == 0:
how_many_months = 1
if howManyMonths == 0:
howManyMonthsString = None
elif howManyMonths == 1:
howManyMonthsString = "1 month"
if how_many_months == 0:
how_many_months_string = None
elif how_many_months == 1:
how_many_months_string = "1 month"
else:
howManyMonthsString = f"{howManyMonths} months"
how_many_months_string = f"{how_many_months} months"
# combine howManyYearsString and howManyMonthsString:
if howManyYearsString is None:
timeSpanString = howManyMonthsString
elif howManyMonthsString is None:
timeSpanString = howManyYearsString
if how_many_years_string is None:
timespan_string = how_many_months_string
elif how_many_months_string is None:
timespan_string = how_many_years_string
else:
timeSpanString = f"{howManyYearsString} {howManyMonthsString}"
timespan_string = f"{how_many_years_string} {how_many_months_string}"
return timeSpanString
return timespan_string
def format_date(date: Date) -> str:
@ -362,6 +362,15 @@ class ClassicThemeOptions(BaseModel):
examples=["1.35 cm", "1 in", "12 pt", "14 mm", "2 ex", "3 em"],
)
show_timespan_in_experience_entries: bool = Field(
default=True,
title="Show Time Span in Experience Entries",
description=(
"If this option is set to true, then the time span of the experience"
" entries will be shown in the date and location column."
),
)
margins: ClassicThemeMargins = Field(
default=ClassicThemeMargins(),
title="Margins",
@ -496,7 +505,7 @@ class Event(BaseModel):
@computed_field
@cached_property
def date_and_location_strings(self) -> list[str]:
def date_and_location_strings_with_timespan(self) -> list[str]:
date_and_location_strings = []
if self.location is not None:
@ -537,18 +546,19 @@ class Event(BaseModel):
@computed_field
@cached_property
def date_and_location_strings_without_time_span(self) -> list[str]:
strings_without_time_span = self.date_and_location_strings
for string in strings_without_time_span:
def date_and_location_strings_without_timespan(self) -> list[str]:
# use copy() to avoid modifying the original list
date_and_location_strings = self.date_and_location_strings_with_timespan.copy()
for string in date_and_location_strings:
if (
"years" in string
or "months" in string
or "year" in string
or "month" in string
):
strings_without_time_span.remove(string)
date_and_location_strings.remove(string)
return strings_without_time_span
return date_and_location_strings
@computed_field
@cached_property
@ -794,13 +804,11 @@ class Section(BaseModel):
),
examples=["view on GitHub", "view on LinkedIn"],
)
entries: list[NormalEntry | OneLineEntry | ExperienceEntry | EducationEntry | PublicationEntry] = (
Field(
title="Entries",
description=(
"The entries of the section. The format depends on the entry type."
),
)
entries: list[
NormalEntry | OneLineEntry | ExperienceEntry | EducationEntry | PublicationEntry
] = Field(
title="Entries",
description="The entries of the section. The format depends on the entry type.",
)
@ -950,7 +958,7 @@ class CurriculumVitae(BaseModel):
"Test Scores",
"Certificates",
"Extracurricular Activities",
"Publications"
"Publications",
]
if self.custom_sections is not None:
# If the user specified custom sections, then add them to the end of the

View File

@ -1,16 +1,10 @@
"""This module implements LaTeX file generation and LaTeX runner utilities for RenderCV.
"""
import os
import subprocess
import os
import json
import logging
import re
from jinja2 import Environment, FileSystemLoader, PackageLoader
import rendercv.templates
from jinja2 import Environment, PackageLoader
def markdown_to_latex(markdown_string: str) -> str:
@ -127,7 +121,7 @@ def make_it_bold(value: str, match_str: str) -> str:
raise ValueError("The string to match should be a string!")
if match_str in value:
value.replace(match_str, "\\textbf{" + match_str + "}")
value = value.replace(match_str, "\\textbf{" + match_str + "}")
return value
else:
return value
@ -182,22 +176,22 @@ def render_template(data):
return output_file_path
def run_latex(latexFilePath):
def run_latex(latex_file_path):
"""
Run TinyTeX with the given LaTeX file and generate a PDF.
Args:
latexFilePath (str): The path to the LaTeX file to compile.
"""
latexFilePath = os.path.normpath(latexFilePath)
latexFile = os.path.basename(latexFilePath)
latex_file_path = os.path.normpath(latex_file_path)
latex_file = os.path.basename(latex_file_path)
if os.name == "nt":
# remove all files except the .tex file
for file in os.listdir(os.path.dirname(latexFilePath)):
for file in os.listdir(os.path.dirname(latex_file_path)):
if file.endswith(".tex"):
continue
os.remove(os.path.join(os.path.dirname(latexFilePath), file))
os.remove(os.path.join(os.path.dirname(latex_file_path), file))
tinytexPath = os.path.join(
os.path.dirname(__file__),
@ -211,12 +205,12 @@ def run_latex(latexFilePath):
f"{tinytexPath}\\latexmk.exe",
"-lualatex",
# "-c",
f"{latexFile}",
f"{latex_file}",
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
],
cwd=os.path.dirname(latexFilePath),
cwd=os.path.dirname(latex_file_path),
)
else:
print("Only Windows is supported for now.")

View File

@ -1,12 +1,8 @@
((* import "components/classic/entry.tex.j2" as entry with context *))
((* macro section_contents(entries, entry_type, link_text=none, disableTimeSpan=True)*))
((* macro section_contents(entries, entry_type, link_text=none)*))
((* for value in entries *))
((* if disableTimeSpan *))
((* set date_and_location_strings = value.date_and_location_strings_without_time_span *))
((* else *))
((* set date_and_location_strings = value.date_and_location_strings *))
((* endif *))
((* set date_and_location_strings = value.date_and_location_strings_without_timespan *))
((* if entry_type == "EducationEntry" *))
<<entry["education"](
study_type=value.study_type,
@ -16,6 +12,9 @@
date_and_location_strings=date_and_location_strings
)|indent(4)>>
((* elif entry_type == "ExperienceEntry" *))
((* if design.show_timespan_in_experience_entries *))
((* set date_and_location_strings = value.date_and_location_strings_with_timespan *))
((* endif *))
<<entry["experience"](
company=value.company,
position=value.position,