Added new articles.
# -*- coding: utf-8 -*-
"""Anki card writer from gaphrase format"""
import re
import hashlib
import os
import io
import sys
import tempfile
import shutil
from gadialog import Parser
import anki
from anki.exporting import AnkiPackageExporter
FINAME = None
FONAME = None
FDELNAME = None
ARG_NAME_RE = re.compile("-name=(.+)")
ARG_DELFILE_RE = re.compile("-delfile=(.+)")
look_for_files = False
for idx in range(1, len(sys.argv)):
arg = sys.argv[idx]
if arg == "--":
look_for_files = True
continue
if not look_for_files:
m = ARG_NAME_RE.match(arg)
if m:
NAME = m.group(1)
continue
m = ARG_DELFILE_RE.match(arg)
if m:
FDELNAME = m.group(1)
continue
if arg.startswith("-"):
raise Exception("Unsupported option format: '{:s}'".format(arg))
if not FINAME:
FINAME = arg
continue
if not FONAME:
FONAME = arg
continue
raise Exception("Unnecessary argument: '{:s}'".format(arg))
if not FINAME:
raise Exception("Input file name is not passed...")
if FONAME is None:
raise Exception("Output file name is not passed...")
if not NAME:
NAME, _ = os.path.splitext(os.path.basename(FINAME))
# if FDELNAME:
# FDEL = io.open(FDELNAME, mode='r', buffering=1, encoding="utf-8")
# else:
# FDEL = None
################################################################
FIN = io.open(FINAME, mode='r', buffering=1, encoding="utf-8")
PARSER = Parser()
try:
DOM = PARSER.parse(FIN)
finally:
FIN.close()
################################################################
MODEL_CSS = """
.card {
font-family: arial;
font-size: 20px;
text-align: left;
color: black;
background-color: white;
}
.line {
margin-bottom: 0.5em;
}
.odd {
color: #004000;
}
.even {
color: #000080;
}
"""
class AnkiDbBuilder:
def __init__(self, tmpdir, name):
self.tmpdir = tmpdir
self.name = name
self.collection = collection = anki.Collection(os.path.join(self.tmpdir, 'collection.anki2'))
deck_id = collection.decks.id(self.name)
# It is essential to keep model['id'] unchanged between upgrades!!
model_id = int(hashlib.sha1(self.name.encode('utf-8')).hexdigest(), 16) % (2**63)
################################################################
# One face card model.
model = collection.models.new(self.name + "_front")
model['did'] = deck_id
model['css'] = MODEL_CSS
collection.models.addField(model, collection.models.newField('Front'))
tmpl = collection.models.newTemplate('Front')
tmpl['qfmt'] = '<div class="front">{{Front}}</div>'
tmpl['afmt'] = '{{FrontSide}}'
collection.models.addTemplate(model, tmpl)
model['id'] = model_id
collection.models.update(model)
collection.models.save(model)
self.model = model
def guid(self, num):
h = hashlib.md5(":".join((self.name, str(num))).encode('utf-8'))
return h.hexdigest()
def add_note(self, num, front):
note = anki.notes.Note(self.collection, self.model)
note['Front'] = front
note.guid = self.guid(num)
self.collection.addNote(note)
def export(self, fname):
export = AnkiPackageExporter(self.collection)
export.exportInto(fname)
def close(self):
self.collection.close()
def write_lines(buf, lines):
odd = True
for line in lines:
if odd:
buf.append("<div class='line odd'>")
else:
buf.append("<div class='line even'>")
buf.append("- ")
buf.append(line)
buf.append("</div>")
odd = not odd
# Looks like anki libs change working directory to media directory of current deck
# Therefore absolute path should be stored before creating temporary deck
FONAME = os.path.abspath(FONAME)
TMPDIR = tempfile.mkdtemp(dir=os.path.dirname(FONAME))
try:
BUILDER = AnkiDbBuilder(TMPDIR, NAME)
for num, lines in DOM.items():
buf = []
write_lines(buf, lines)
front = "".join(buf)
BUILDER.add_note(num, front)
BUILDER.export(FONAME)
finally:
BUILDER.close()
shutil.rmtree(TMPDIR, ignore_errors=True)