Fix up with anki libraries.

main
Joshua Potter 2022-07-03 06:50:31 -06:00
parent 0b629044a8
commit b716795d96
5 changed files with 122 additions and 23 deletions

13
.githooks/pre-commit Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -e
filesToFormat=$(
git --no-pager diff --name-status --no-color --cached | \
awk '$1 != "D" && $2 ~ /\.py/ {print $NF}'
)
for path in $filesToFormat
do
black --quiet $path
git add $path
done

41
.gitignore vendored Normal file
View File

@ -0,0 +1,41 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# mypy
.mypy_cache/
.dmypy.json
dmypy.json

View File

@ -5,16 +5,16 @@ different options for parts of prompts. This was designed to handle synonyms in
a clean way.
Consider a [total order](https://en.wikipedia.org/wiki/Total_order). What this
is does not matter; what it could also be called does. What some people call a
is does not matter; other names it may have does. What some people call a
"total order", others call a "linear order". Though this example is simple, it
does highlight an issue - remembering the various synonyms used to describe
a concept is important for fluency.
highlights an important issue - remembering the various synonyms used to
describe a concept is necessary for fluency.
As of now, to handle this situation, it is probably best to use two flashcards,
one with prompt "Total Order" and another with prompt "Linear Order". In some
cases though, it'd be nice if the flashcard could *choose* which term it shows
when it shows it. That is, it'd be nice to have a single card and allow Anki to
randomly choose to show "Total Order" *or* "Linear Order".
As of now, to handle this situation, it is probably suggested to use two
flashcards, one with prompt "Total Order" and another with prompt "Linear Order".
In some cases though, it'd be nice if the flashcard could *choose* which term it
shows when it shows it. That is, it'd be nice to have a single card and allow
Anki to randomly choose to show "Total Order" *or* "Linear Order".
To do so, we can install this plugin and write the following:
@ -27,10 +27,26 @@ Here, `'(` is used to indicate the start of a set of choices Anki can display,
end of the set. The result is either "Total Order" or "Linear Order" at time
of prompting.
You can also nest choices if need be:
```
'('(Logical|Valid) Consequence|Entailment)
```
will yield either "Logical Consequence", "Valid Consequence", or "Entailment".
## Configuration
TODO
From "Tools > Add-ons", select the `anki-synonyms` entry and select "Config"
to reveal a dialog with contents:
## Nesting
```json
{
"CHOICE_TAG": "|",
"END_TAG": ")",
"START_TAG": "'("
}
```
TODO
Update these accordingly if the default `'(|)` set of operators do not mesh with
the text in your questions and answers.

View File

@ -1,14 +1,26 @@
from dataclasses import dataclass
from typing import Optional, Union
import copy
import enum
import random
from dataclasses import dataclass
from typing import Optional, Union
START_TAG = "'("
END_TAG = ")"
CHOICE_TAG = "|"
from anki import hooks
from anki.template import TemplateRenderContext, TemplateRenderOutput
from aqt import mw
config = mw.addonManager.getConfig(__name__)
START_TAG: str = config["START_TAG"]
END_TAG: str = config["END_TAG"]
CHOICE_TAG: str = config["CHOICE_TAG"]
assert (
len(set([START_TAG, END_TAG, CHOICE_TAG])) == 3
), "Must have unique start, end, and choice operators."
class Tag(enum.Enum):
@ -106,16 +118,32 @@ def run_parser(arg: str) -> str:
respectively, parsing "'(hello|world)" yields either "hello" or "world".
"""
tokens = _tokenize(arg)
stack: list[list[str]] = [[]]
buffer: list[str] = [""]
stack: list[list[str]] = []
for token in tokens:
if token is Tag.START:
buffer.append("")
stack.append([])
elif token is Tag.END:
stack[-1].append(buffer.pop())
ts = stack.pop()
stack[-1].append(random.choice(ts))
buffer[-1] += random.choice(ts)
elif token is Tag.CHOICE:
pass
stack[-1].append(buffer[-1])
buffer[-1] = ""
else:
stack[-1].append(token)
assert len(stack) == 1, "Stack is larger than a single element"
return "".join(stack[0])
buffer[-1] += token
assert not stack, "Stack should be empty"
assert len(buffer) == 1, "Buffer should only have one element."
return buffer[0]
def on_card_render(
output: TemplateRenderOutput,
_unused_context: TemplateRenderContext,
):
output.question_text = run_parser(output.question_text)
output.answer_text = run_parser(output.answer_text)
hooks.card_did_render.append(on_card_render)

1
config.json Normal file
View File

@ -0,0 +1 @@
{"START_TAG": "'(", "END_TAG": ")", "CHOICE_TAG": "|"}