py/gaphrase_srs_anki.py
changeset 1203 c767b62ec786
parent 1149 ca622f07a40b
equal deleted inserted replaced
1202:649b6e7f46c5 1203:c767b62ec786
    63 
    63 
    64 class Parser:
    64 class Parser:
    65 
    65 
    66     COMMENT_RE = re.compile("^; ")
    66     COMMENT_RE = re.compile("^; ")
    67     NUM_RE = re.compile(u"^# ([1-9][0-9]*)$")
    67     NUM_RE = re.compile(u"^# ([1-9][0-9]*)$")
    68     PHRASE_START_RE = re.compile(u"^- (.*)")
       
    69 
    68 
    70     def __init__(self):
    69     def __init__(self):
    71         pass
    70         pass
    72 
    71 
    73     def readline(self):
    72     def readline(self):
    84                 break
    83                 break
    85 
    84 
    86     def parse(self, stream):
    85     def parse(self, stream):
    87         self.lineno = 0
    86         self.lineno = 0
    88         self.stream = stream
    87         self.stream = stream
    89         self.dom = dict()
    88         self.dom = dict()                   # num => phrase
    90         self.eof = False
    89         self.eof = False
    91         try:
    90         try:
    92             self.parse_prelude()
    91             self.parse_prelude()
    93             while not self.eof:
    92             while not self.eof:
    94                 self.parse_article()
    93                 self.parse_article()
   111 
   110 
   112     def parse_article(self):
   111     def parse_article(self):
   113         """Assume we are at ``# NUM`` line."""
   112         """Assume we are at ``# NUM`` line."""
   114         num = self.num
   113         num = self.num
   115         phrase_buf = []
   114         phrase_buf = []
   116         phrases = []
       
   117         while True:
   115         while True:
   118             self.readline()
   116             self.readline()
   119             if self.eof:
   117             if self.eof:
   120                 if len(phrase_buf) > 0:
       
   121                     phrases.append(" ".join(phrase_buf))
       
   122                 break
   118                 break
   123             m = self.NUM_RE.match(self.line)
   119             m = self.NUM_RE.match(self.line)
   124             if m:
   120             if m:
   125                 if len(phrase_buf) > 0:
       
   126                     phrases.append(" ".join(phrase_buf))
       
   127                 self.num = m.group(1)
   121                 self.num = m.group(1)
   128                 break
   122                 break
   129             m = self.PHRASE_START_RE.match(self.line)
   123             phrase_buf.append(self.line)
   130             if m:
   124         if len(phrase_buf) == 0:
   131                 if len(phrase_buf) > 0:
       
   132                     phrases.append(" ".join(phrase_buf))
       
   133                 phrase_buf = [m.group(1)]
       
   134             else:
       
   135                 phrase_buf.append(self.line)
       
   136         if len(phrases) == 0:
       
   137             raise ParseException("""There are no any phrases...""")
   125             raise ParseException("""There are no any phrases...""")
   138         if num in self.dom:
   126         if num in self.dom:
   139             raise ParseException("""Conflicting key: {}...""".format(num))
   127             raise ParseException("""Conflicting key: {}...""".format(num))
   140         self.dom[num] = phrases
   128         self.dom[num] = " ".join(phrase_buf)
   141 
   129 
   142 FIN = io.open(FINAME, mode='r', buffering=1, encoding="utf-8")
   130 FIN = io.open(FINAME, mode='r', buffering=1, encoding="utf-8")
   143 
   131 
   144 PARSER = Parser()
   132 PARSER = Parser()
   145 try:
   133 try:
   158   background-color: white;
   146   background-color: white;
   159 }
   147 }
   160 .line {
   148 .line {
   161   margin-bottom: 0.5em;
   149   margin-bottom: 0.5em;
   162 }
   150 }
   163 .odd {
       
   164   color: #004000;
       
   165 }
       
   166 .even {
       
   167   color: #000080;
       
   168 }
       
   169 """
   151 """
   170 
   152 
   171 class AnkiDbBuilder:
   153 class AnkiDbBuilder:
   172 
   154 
   173     def __init__(self, tmpdir, name):
   155     def __init__(self, tmpdir, name):
   214         export.exportInto(fname)
   196         export.exportInto(fname)
   215 
   197 
   216     def close(self):
   198     def close(self):
   217         self.collection.close()
   199         self.collection.close()
   218 
   200 
   219 def write_lines(buf, lines):
       
   220     odd = True
       
   221     for line in lines:
       
   222         if odd:
       
   223             buf.append("<div class='line odd'>")
       
   224         else:
       
   225             buf.append("<div class='line even'>")
       
   226         buf.append("- ")
       
   227         buf.append(line)
       
   228         buf.append("</div>")
       
   229         odd = not odd
       
   230 
       
   231 # Looks like anki libs change working directory to media directory of current deck
   201 # Looks like anki libs change working directory to media directory of current deck
   232 # Therefore absolute path should be stored before creating temporary deck
   202 # Therefore absolute path should be stored before creating temporary deck
   233 FONAME = os.path.abspath(FONAME)
   203 FONAME = os.path.abspath(FONAME)
   234 TMPDIR = tempfile.mkdtemp(dir=os.path.dirname(FONAME))
   204 TMPDIR = tempfile.mkdtemp(dir=os.path.dirname(FONAME))
   235 
   205 
   236 try:
   206 try:
   237     BUILDER = AnkiDbBuilder(TMPDIR, NAME)
   207     BUILDER = AnkiDbBuilder(TMPDIR, NAME)
   238 
   208 
   239     for num, lines in DOM.items():
   209     for num, phrase in DOM.items():
   240         buf = []
   210         buf = []
   241         write_lines(buf, lines)
   211         buf.append("<div class='line'>")
       
   212         buf.append(phrase)
       
   213         buf.append("</div>")
   242         front = "".join(buf)
   214         front = "".join(buf)
   243         BUILDER.add_note(num, front)
   215         BUILDER.add_note(num, front)
   244     BUILDER.export(FONAME)
   216     BUILDER.export(FONAME)
   245 finally:
   217 finally:
   246     BUILDER.close()
   218     BUILDER.close()