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. a clean way.
Consider a [total order](https://en.wikipedia.org/wiki/Total_order). What this 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 "total order", others call a "linear order". Though this example is simple, it
does highlight an issue - remembering the various synonyms used to describe highlights an important issue - remembering the various synonyms used to
a concept is important for fluency. describe a concept is necessary for fluency.
As of now, to handle this situation, it is probably best to use two flashcards, As of now, to handle this situation, it is probably suggested to use two
one with prompt "Total Order" and another with prompt "Linear Order". In some flashcards, one with prompt "Total Order" and another with prompt "Linear Order".
cases though, it'd be nice if the flashcard could *choose* which term it shows In some cases though, it'd be nice if the flashcard could *choose* which term it
when it shows it. That is, it'd be nice to have a single card and allow Anki to shows when it shows it. That is, it'd be nice to have a single card and allow
randomly choose to show "Total Order" *or* "Linear Order". Anki to randomly choose to show "Total Order" *or* "Linear Order".
To do so, we can install this plugin and write the following: 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 end of the set. The result is either "Total Order" or "Linear Order" at time
of prompting. of prompting.
You can also nest choices if need be:
```
'('(Logical|Valid) Consequence|Entailment)
```
will yield either "Logical Consequence", "Valid Consequence", or "Entailment".
## Configuration ## 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 copy
import enum import enum
import random import random
from dataclasses import dataclass
from typing import Optional, Union
START_TAG = "'(" from anki import hooks
END_TAG = ")" from anki.template import TemplateRenderContext, TemplateRenderOutput
CHOICE_TAG = "|" 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): class Tag(enum.Enum):
@ -106,16 +118,32 @@ def run_parser(arg: str) -> str:
respectively, parsing "'(hello|world)" yields either "hello" or "world". respectively, parsing "'(hello|world)" yields either "hello" or "world".
""" """
tokens = _tokenize(arg) tokens = _tokenize(arg)
stack: list[list[str]] = [[]] buffer: list[str] = [""]
stack: list[list[str]] = []
for token in tokens: for token in tokens:
if token is Tag.START: if token is Tag.START:
buffer.append("")
stack.append([]) stack.append([])
elif token is Tag.END: elif token is Tag.END:
stack[-1].append(buffer.pop())
ts = stack.pop() ts = stack.pop()
stack[-1].append(random.choice(ts)) buffer[-1] += random.choice(ts)
elif token is Tag.CHOICE: elif token is Tag.CHOICE:
pass stack[-1].append(buffer[-1])
buffer[-1] = ""
else: else:
stack[-1].append(token) buffer[-1] += token
assert len(stack) == 1, "Stack is larger than a single element" assert not stack, "Stack should be empty"
return "".join(stack[0]) 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": "|"}