Compare commits

..

No commits in common. "main" and "v2025-03-11" have entirely different histories.

80 changed files with 58 additions and 78 deletions

View file

@ -36,7 +36,7 @@ def process_line(
slug = slug.replace(' ', '-') slug = slug.replace(' ', '-')
base_filename = deckpath / slug base_filename = deckpath / slug
for i, c in enumerate(columns): for i, c in enumerate(columns):
with (base_filename.parent / (base_filename.name + f'.{i}.html')).open('w') as fp: with (base_filename.parent / (base_filename.name + f'.{i}.md')).open('w') as fp:
fp.write(c) fp.write(c)
if not c.endswith('\n'): if not c.endswith('\n'):
fp.write('\n') fp.write('\n')

View file

@ -9,7 +9,7 @@ import random
import re import re
RE_DIRNAME = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)$') RE_DIRNAME = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)$')
RE_FILENAME = re.compile(r'^(.*)\.([0-9]+)\.(md|html)$') RE_FILENAME = re.compile(r'^(.*)\.([0-9]+)\.md$')
class MyNote(genanki.Note): class MyNote(genanki.Note):
pass pass
@ -20,25 +20,20 @@ def load_notes(
model: genanki.Model, model: genanki.Model,
) -> list[genanki.Note]: ) -> list[genanki.Note]:
files_loaded = [] files_loaded = []
final_files: dict[str, list[tuple[pathlib.Path, int, bool]]] = {} final_files: dict[str, list[tuple[pathlib.Path, int]]] = {}
for dirpath, _, filenames in path.walk(): for dirpath, _, filenames in path.walk():
files_loaded += [dirpath / x for x in filenames] files_loaded += [dirpath / x for x in filenames]
for f in files_loaded: for f in files_loaded:
match = RE_FILENAME.match(f.name) match = RE_FILENAME.match(f.name)
if match: if match:
final_files.setdefault(match.group(1), []).append( final_files.setdefault(match.group(1), []).append((f, int(match.group(2))))
(f, int(match.group(2)), match.group(3) == 'html'),
)
notes: list[genanki.Note] = [] notes: list[genanki.Note] = []
for v in final_files.values(): for v in final_files.values():
note_files: list[tuple[pathlib.Path, bool]] = [(v_[0], v_[2]) for v_ in sorted(v, key=lambda x: x[1])] note_files: list[pathlib.Path] = [v_[0] for v_ in sorted(v, key=lambda x: x[1])]
note_str: list[str] = [] note_str: list[str] = []
for f, is_html in note_files: for f in note_files:
with f.open() as fp: with f.open() as fp:
if is_html: html_str = markdown.markdown(fp.read())
html_str = fp.read()
else:
html_str = markdown.markdown(fp.read())
note_str += [html_str] note_str += [html_str]
notes += [MyNote(model=model, fields=note_str, guid=genanki.guid_for(note_str[0]))] notes += [MyNote(model=model, fields=note_str, guid=genanki.guid_for(note_str[0]))]
return notes return notes
@ -55,8 +50,7 @@ def load_notes(
@click.option('--destructive/--no-destructive', 'destructive', type=bool, default=False, help='Perform write operations, which may end in data loss') @click.option('--destructive/--no-destructive', 'destructive', type=bool, default=False, help='Perform write operations, which may end in data loss')
@click.option('--autogenerate/--no-autogenerate', 'autogenerate', type=bool, default=False, help='Generate missing ids, should probably be used with --destructive, to always use the same ones.') @click.option('--autogenerate/--no-autogenerate', 'autogenerate', type=bool, default=False, help='Generate missing ids, should probably be used with --destructive, to always use the same ones.')
@click.option('--debug/--no-debug', 'debug', type=bool, default=False, help="Debug mode, don't write files") @click.option('--debug/--no-debug', 'debug', type=bool, default=False, help="Debug mode, don't write files")
@click.option('--multi', 'multi', type=click.Path(path_type=pathlib.Path)) @click.argument('path', type=click.Path(path_type=pathlib.Path, dir_okay=True))
@click.argument('paths', type=click.Path(path_type=pathlib.Path, dir_okay=True), nargs=-1)
def main( def main(
*, *,
name: str | None, name: str | None,
@ -70,62 +64,54 @@ def main(
destructive: bool, destructive: bool,
autogenerate: bool, autogenerate: bool,
debug: bool, debug: bool,
multi: pathlib.Path | None, path: pathlib.Path,
paths: list[pathlib.Path],
): ):
decks = [] match = RE_DIRNAME.match(path.name)
for path in paths: if match:
match = RE_DIRNAME.match(path.name) model_name = model_name or match.group(1)
if match: name = name or match.group(1)
model_name = model_name or match.group(1) model_id = model_id or int(match.group(2))
name = name or match.group(1) deck_id = deck_id or int(match.group(3))
model_id = model_id or int(match.group(2)) else:
deck_id = deck_id or int(match.group(3)) model_name = model_name or path.name
else: name = name or path.name
model_name = model_name or path.name if model_id is None:
name = name or path.name if autogenerate:
if model_id is None: model_id = random.randrange(1 << 30, 1 << 31)
if autogenerate: else:
model_id = random.randrange(1 << 30, 1 << 31) raise click.ClickException('model_id could not be derived from directory name and is not explicitly set, or autogenerate enabled')
else: if deck_id is None:
raise click.ClickException('model_id could not be derived from directory name and is not explicitly set, or autogenerate enabled') if autogenerate:
if deck_id is None: deck_id = random.randrange(1 << 30, 1 << 31)
if autogenerate: else:
deck_id = random.randrange(1 << 30, 1 << 31) raise click.ClickException('deck_id could not be derived from directory name and is not explicitly set, or autogenerate enabled')
else: if destructive:
raise click.ClickException('deck_id could not be derived from directory name and is not explicitly set, or autogenerate enabled') new_path = path.parent / f'{path.name}.{model_id}.{deck_id}'
if destructive: if not debug:
new_path = path.parent / f'{path.name}.{model_id}.{deck_id}' path.rename(new_path)
if not debug: path = new_path
path.rename(new_path) model = genanki.Model(
path = new_path model_id,
model = genanki.Model( model_name,
model_id, fields=[dict(name=x) for x in fields],
model_name, templates=[
fields=[dict(name=x) for x in fields], {
templates=[ 'name': template_name,
{ 'qfmt': question_format,
'name': template_name, 'afmt': answer_format,
'qfmt': question_format, },
'afmt': answer_format, ],
}, )
], notes: list[genanki.Note] = load_notes(path=path, model=model)
) deck = genanki.Deck(
notes: list[genanki.Note] = load_notes(path=path, model=model) deck_id,
deck = genanki.Deck( name,
deck_id, )
name, for n in notes:
) deck.add_note(n)
for n in notes: click.echo(f'added {len(notes)} notes')
deck.add_note(n) if not debug:
click.echo(f'added {len(notes)} notes') genanki.Package(deck).write_to_file(path.parent / (path.name + '.apkg'))
decks += [deck]
if not debug:
genanki.Package(deck).write_to_file(path.parent / (path.name + '.apkg'))
if not debug and multi:
if multi.suffix != '.apkg':
click.echo('WARNING: destination file does not have extension ".apkg"')
genanki.Package(decks).write_to_file(multi)

View file

@ -1 +0,0 @@
Was ist<br><br>[$]\left(\mathbf{a}\cdot\nabla\right)\mathbf{r}[/$]

View file

@ -1 +0,0 @@
Was ist<br><br>[$]\nabla\times\mathbf{r}[/$]

View file

@ -1 +0,0 @@
Was ist<br><br>[$]\nabla\cdot\mathbf{r}[/$]

View file

@ -1 +0,0 @@
[$$](\mathbf{a} \times \mathbf{b}) \cdot (\mathbf{c} \times \mathbf{d}) = (\mathbf{a} \cdot \mathbf{c})(\mathbf{b} \cdot \mathbf{d}) - (\mathbf{b} \cdot \mathbf{c})(\mathbf{a} \cdot \mathbf{d})[/$$]<br><br>mit Spezialfall<br><br>[$$]|\mathbf{a} \times \mathbf{b}|^2 = |\mathbf{a}|^2 |\mathbf{b}|^2 - (\mathbf{a} \cdot \mathbf{b})^2[/$$]

View file

@ -0,0 +1 @@
"[$$](\mathbf{a} \times \mathbf{b}) \cdot (\mathbf{c} \times \mathbf{d}) = (\mathbf{a} \cdot \mathbf{c})(\mathbf{b} \cdot \mathbf{d}) - (\mathbf{b} \cdot \mathbf{c})(\mathbf{a} \cdot \mathbf{d})[/$$]<br><br>mit Spezialfall<br><br>[$$]<span style=""white-space-collapse: preserve;"">|\mathbf{a} \times \mathbf{b}|^2 = |\mathbf{a}|^2 |\mathbf{b}|^2 - (\mathbf{a} \cdot \mathbf{b})^2</span>[/$$]"

View file

@ -1 +1 @@
[$$]\mathbf{F}=Q\left(\mathbf{E}+\mathbf{v}\times\mathbf{B}\right)[/$$] [$$]\mathbf{F}=Q\left(\mathbf{E}+\mathbf{v}\times\mathbf{B}\right)[$$/]

View file

@ -0,0 +1 @@
[$$]\mathbf{F}=I\cdot l \times \mathbf{B}[/$$]