Need help porting two add-ons to newer version (>2.1.44)

Hello,

I’m trying to upgrade two similar add-ons, but I couldn’t figure out how hooks work in the newer versions of Anki. The add-ons are the followings:

  • ABC notation to MP3 (music integration) for Anki 2.1.x (add-on number 203713821)
  • LilyPond Integration (Sheet Music Typesetter) for Anki 2.1.x (add-on number 123418104)

I have a hook that looks like this (mungeFields is my callback function and “mungeFields” is the hook):

addHook("mungeFields", mungeFields)

It seems that it is never called. What should I do instead?

For the other portions of code to port, I figured out to replace the depreciated API, but PyCharme - whitch is advised to use - wasn’t so helpful. For instance, the autocompletion proposed “stripHTML” instead of the new “strip_html”… so I’ll prefer to use a simple text editor in the future.

Greetings,
Luca

This is apparently a really old hook that is no longer called. You can try replacing it with editor_will_munge_html. Hooks are defined and documented in the following two pages: genhooks_gui.py, genhooks.py.

Did you install the latest versions of the anki/aqt PyPI packages? I usually use VS Code and it suggests strip_html if I have recent packages.

Hello @abdo
Thanks for helping.

I wasn’t sure about editor_will_munge_html hook, but now I feel confident. I’ll try it asap.
Is it still ok to use addHook()?

I don’t know if I’ve installed the latest versions of anki/aqt PyPI packages, but I followed the instructions on the documentation. No worries, I prefer a simple text editor, even if I wouldn’t complain about autocompletion :sweat_smile:.

Another question: how to deal with internationalisation gettext _()?
I based my work on an add-on for Anki 2.0 and it contained i18n text like _(‘Edit’) and some longer sentences. I don’t know if Anki translate all that content, but I would like to keep this functionality.
What should I replace _() with?
Does Anki now uses i18n python module and i18n.t() instead of _()?

Thanks again and Happy New Year! Best wishes for 2023!
Luca

Hello again @abdo
I’ve tried the code below, but it seems that the hook isn’t called at all when the card is displayed. Any idea?

def mungeFields(fields, model, data, col):
    '''Parse lilypond tags before they are displayed.'''
    print("******* mungeFields **********")
    # Ignore duplicated mungeFields call for the answer side.
    if 'FrontSide' in fields:
        return fields

    for fld in model['flds']:
        field = fld['name']

        # check field name
        match = lilypondFieldRegexp.search(field)

        if match \
                and fields[field] != "(%s)" % (field,) \
                and fields[field] != "ankiflag":
            fields[field] = _imgLink(col, match.group(2), _lyFromHtml(fields[field]))

            # autofill field for web:
            imgfield = field.replace("lilypond", "lilypondimg", 1)
            if imgfield in fields and fields[field] != fields[imgfield]:
                fields[imgfield] = fields[field]
                col.findReplace((data[1],), "^.*$", fields[field], regex=True, field=imgfield)
            continue

        # check field contents
        for match in lilypondRegexp.finditer(fields[field]):
            fields[field] = fields[field].replace(
                match.group(), _imgLink(col, match.group(2), _lyFromHtml(match.group(3)))
            )

    return fields

addHook("editor_will_munge_html", mungeFields)

Best greetings,
Luca

editor hooks are called while the editor is shown. If you’re trying to do something during review, that’s not going to work. Some other hooks are mentioned on Changes in 2.1.20 to 29 - Changes that may or may not work for you.

Regarding translations, please see For Developers - Anki Translation Guide

Hello @dae
Thanks for your answer.
It seems that the hook isn’t called even when the editor is shown (I tried to add a new card and to browse cards in the deck). I’ll do a further test today, and I’ll come back to report.
I couldn’t find a hook similar to the old mungeFields in the links you and @abdo provided me, except for editor_will_munge_html.
Best regards,
Luca

Hello again @dae
I should have specified that I have Qt5 Anki 2.1.54 installed on linux. Is there any difference between Qt6 and Qt5 versions?

I’ve done more tests and I found that the hook editor_will_munge_html isn’t called when I edit a card (regardless if I create a new card or edit an existing one).

I have noticed that there are inconsistencies in naming conventions:

  • profileLoaded hook still works,
  • new hooks use underscore and small caps (like editor_will_munge_html),
  • stripHTML function is now strip_html, but addHook don’t use this convention.

Is there a chance that the names will change again in the future? The question is mainly about profileLoaded hook.

Best regards,
Luca

it works for me. You’re using it incorrectly. It should be used like this because it’s a new-style hook:

aqt.gui_hooks.editor_will_munge_html.append(my_func)

editor_will_munge_html is not the right hook for your case though, because the add-on needs to change the rendered display when reviewing rather than the the edited field contents in the editor. card_did_render may work.

1 Like

Hello @abdo
Thanks for you answer!

I’ve made the change you suggested according to the new system of hooks. Unfortunately, it seems that the hook card_did_render doesn’t exist (2.1.54 Qt5).

output-3-1-20223

I installed last version of Anki (2.1.55 Qt6) and I obtained the same error.

I found another hook card_will_show, but then I don’t know how to use it. Because the old fashion hook requires these arguments: fields, model, data, col; but the new one requires only one argument: card. I don’t know if it is the right hook to use. I don’t know how to handle its argument (i.e. card) and recover what I need (i.e. fields, model, data, col). Any idea?

I’m struggling with this port: I’m not a programmer, and I did only adapt an existing no-updated add-on for Anki 2.0. I appreciate all your support and help, it means a lot. Thank you!

Greetings,
Luca

card_did_render is defined under anki.hooks rather than aqt.gui_hooks (new hooks are defined in two places). anki.hooks.card_did_render should work.

Probably the add-on’s behavior need to be changed a bit for it to be possible to port it to Anki 2.1, since it apparently needs to modify individual fields, the thing which card_did_render doesn’t provide. I can’t help here, because I’m not familiar with the add-on and don’t have the time to look into it at the moment.

1 Like

Thank you @abdo !
The hook is found now.
I’ll figure out the arguments needed and change the functionality of the callback function. I guess I have to scale down the add-on’s capabilities, if we can’t change the fields, and if we can only change the card rendering.
Best regards,
Luca

Hello,
I finally found a solution.

LilyPond (sheet music typesetting) integration by Andreas Klauer (add-on 1080109152) do exactly what I want. In fact, it’s his prior code for anki 2.0 that I updated for Anki 2.1 and adapted for ABC notation sound generation as well (for 2.0, then for 2.1).

I’m going to adapt my add-on for LilyPond (because it adds a menu for templates to Andreas’ add-on) and I’ll update the add-on for ABC sound generation with an similar code.

Thank you!
Best regards,
Luca

2 Likes

Could you share the solution you said you found? The code for the add-on on github is still using mungeFields which, as you discuss above, is never called.