8000 Add simple logic to anki export field mappings, `if/else` · Issue #586 · LuteOrg/lute-v3 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add simple logic to anki export field mappings, if/else #586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jzohrab opened this issue Feb 24, 2025 · 1 comment
Open

Add simple logic to anki export field mappings, if/else #586

jzohrab opened this issue Feb 24, 2025 · 1 comment

Comments

@jzohrab
Copy link
Collaborator
jzohrab commented Feb 24, 2025

Sometimes during exports it would be useful to put one field or another in the anki note.

For example, I have two practically identical exports for German pluralization: one that puts the "parent" in the singular field, and another that puts the "term" in the singular field, because for some German words the sing and plural forms are the same.

Possible grammar options:

Like Anki: {#myfield}{ myfield }{/myfield} {^myfield}{ otherfield }{/myfield}

Like Jinja: {% if myfield %}{ myfield }{% else %}{ otherfield }{% endif %}

Like Python: { parents or term }

(No idea how difficult this is going to be, but the request makes sense).

@jzohrab jzohrab added this to Lute-v3 Feb 24, 2025
@jzohrab
Copy link
Collaborator Author
jzohrab commented Feb 24, 2025

Some initial hacking:

from pyparsing import (
    Word, alphas, Suppress, Forward, Group, Optional, Keyword, CharsNotIn, OneOrMore, restOfLine, Regex
)

def evaluate_if_block(parsed, context):
    """Evaluate an if-else block based on a dictionary context."""
    # print(f"if block ...")
    # print(parsed)
    # print(context)
    condition = parsed[0] in context and bool(context[parsed[0]])
    # print(condition)
    ret = ""
    if condition:
        ret = parsed[1]  # Return "then" block
    elif len(parsed) > 2:  # If an "else" block exists, return it
        ret = parsed[2]

    # do substitution here ... eg. replace {term} with the actual value.
    return ret


def parse_template(template, context):
    """Parse and evaluate a template supporting `{% if %} ... {% else %} ... {% endif %}`."""
    print("-----------------------")
    print(template)

    identifier = Word(alphas + "_")  # Variable names (e.g., "term", "another")

    # **Fix:** Capture full text blocks until `{%`
    text_content = Regex(r'.*?(?={%)')

    # If-Else-Endif syntax
    if_stmt = Suppress("{% if") + identifier + Suppress("%}")
    else_stmt = Suppress("{% else %}")
    endif_stmt = Suppress("{% endif %}")

    if_expr = Group(
        if_stmt + text_content + Optional(else_stmt + text_content, default="") + endif_stmt
    )

    template_parser = OneOrMore(if_expr | identifier | text_content)

    parsed_result = template_parser.parse_string(template, parse_all=True)
    # print(parsed_result)

    # Evaluate parsed structure
    output = []
    for item in parsed_result:
        # print(f"evaluating item = {item}")
        if isinstance(item, str):
            # print("is string")
            output.append(context.get(item, item))
        else:
            # print("is array (if block)")
            output.append(evaluate_if_block(item, context))

    print(f"output = {output}")
    return output[0]

# Test Cases
template1 = "{% if term %}{term}{% else %}{parents}{% endif %}"
template2 = "{% if term %}{term}{% endif %}"  # No "else"

context1 = {"term": "world"}
context2 = {}  # "term" is missing

# test cases and what they _should_ print -- final substitutions not happening yet.
print(parse_template(template1, context1))  # "Hello, world!"
print(parse_template(template1, context2))  # "No term found."
print(parse_template(template2, context1))  # "Hello, world!"
print(parse_template(template2, context2))  # "" (empty string)

This prints out:

-----------------------
{% if term %}{term}{% else %}{parents}{% endif %}
output = ['{term}']
{term}
-----------------------
{% if term %}{term}{% else %}{parents}{% endif %}
output = ['{parents}']
{parents}
-----------------------
{% if term %}{term}{% endif %}
output = ['{term}']
{term}
-----------------------
{% if term %}{term}{% endif %}
output = ['']

This is still going to be tough to integrate into the field mapping code, b/c the various conditions would need to be evaluated, e.g. {% if tags:["val1", "val2"] %} stuff here {% endif %}, and need to check for bad outputs too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

1 participant
0