mirror of https://github.com/eyhc1/rendercv.git
show timespan in experience entries
This commit is contained in:
parent
920cf379cf
commit
0107906480
|
@ -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
|
||||
|
||||
|
|
|
@ -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(
|
||||
entries: list[
|
||||
NormalEntry | OneLineEntry | ExperienceEntry | EducationEntry | PublicationEntry
|
||||
] = Field(
|
||||
title="Entries",
|
||||
description=(
|
||||
"The entries of the section. The format depends on the entry type."
|
||||
),
|
||||
)
|
||||
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
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue