# Emacs-style shortcuts with "Ctrl+T, ..." in the editor in 45+

**URL:** <https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280>\
**Category:** Development\
**Created:** [August 13, 2021, 4:41pm UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280 "2021-08-13T16:41:05Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ijgnd](https://avatars.discourse-cdn.com/v4/letter/i/bbe5ce/32.png) [@ijgnd](https://forums.ankiweb.net/u/ijgnd)\
**Post date:** [August 13, 2021, 4:41pm UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/1 "2021-08-13T16:41:05Z")

</div>

With emacs-style I mean a two part shortcut like “Ctrl+T, T”.

The following minimal add-on worked in 2.1.44 but in 2.1.45+ it breaks the built-in shortcuts for latex such as “Ctrl+T, T” (E/M):

```python
from aqt import gui_hooks
from aqt.utils import tooltip

def shortcut_test(cuts, editor):
    cuts.append(("Ctrl+T, D", lambda: tooltip("test")))
gui_hooks.editor_did_init_shortcuts.append(shortcut_test)

```

As far as I see my code is similar to what other add-ons do.

My code seems to have broken with the changes in the editor from the beginning of May.

Is the problem my code or is it in Anki?

This is relevant for me because I use two part shortcuts as a default in my add-on [Extended Tag Add/Edit Dialog](https://ankiweb.net/shared/info/1135507717). I’d like to keep a combination starting with Ctrl+T because Arthur also has a tag related add-on for med students named [high yield tags](https://ankiweb.net/shared/info/1918380616) that uses two part shortcuts that start with ctrl+t (actually after talking with ankingmed we decided to switch to these similar shortcuts at the same time last year).

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [August 15, 2021, 6:36am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/2 "2021-08-15T06:36:43Z")

</div>

The editor shortcuts are handled in JS now, so for shortcuts that share a common prefix, you’d need to listen for them in JS to avoid Qt swallowing the shortcut. AFAIK, this is not super easy at the moment as Anki is not exposing a utility to handle the multiple keystrokes.

@hengiesel I presume we won’t be able to export WithShortcut in the near future; but maybe we could expose registerShortcut for now?

---

<div class="post-metadata">

**Author:** ![hengiesel](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/hengiesel/32/920_2.png) [@hengiesel](https://forums.ankiweb.net/u/hengiesel)\
**Post date:** [August 15, 2021, 6:57am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/3 "2021-08-15T06:57:03Z")

</div>

I think we can export `registerShortcut()` generally. Not every shortcut needs to be bound to an UI element.  
Maybe we could export new functions over the `anki` module exclusively though, making that transition smoother.

---

<div class="post-metadata">

**Author:** ![ijgnd](https://avatars.discourse-cdn.com/v4/letter/i/bbe5ce/32.png) [@ijgnd](https://forums.ankiweb.net/u/ijgnd)\
**Post date:** [August 15, 2021, 10:30am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/4 "2021-08-15T10:30:22Z")

</div>

Some more background info. Maybe my minimal example was too minimal. I actually didn’t use a hook but instead directly set the qt shortcut by wrapping a built-in function from addcards like this:

```auto
from anki.hooks import wrap
from aqt import mw
from aqt.addcards import AddCards
from aqt.utils import tooltip
from aqt.qt import *

# addHook("setupEditorShortcuts", SetupShortcuts) doesn't work when editor
# is not focused, e.g. if focus is on tag line.
def addAddshortcut(self, mw):
    shortcut = QShortcut(QKeySequence("Ctrl+T, D"), self)
    shortcut.activated.connect(lambda: tooltip("Hello"))
AddCards. __init__ = wrap(AddCards. __init__ , addAddshortcut)

```

I thought that this should still work in 45+. I grepped the source code for “ctrl+t” and only found it in editor.py So I thought that the advancd dropdown menu is still drawn with pyqt, see [here](https://github.com/ankitects/anki/blob/2265bfe71da0dff6756c8d4d9109aaaae259e645/qt/aqt/editor.py#L1015) and that this would mean that setting a qt shortcut directly should work.

I don’t want to say that Anki should support this approach for add-ons. It’s just what I did. Maybe that’s relevant info for you.

---

<div class="post-metadata">

**Author:** ![ijgnd](https://avatars.discourse-cdn.com/v4/letter/i/bbe5ce/32.png) [@ijgnd](https://forums.ankiweb.net/u/ijgnd)\
**Post date:** [August 15, 2021, 7:06pm UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/5 "2021-08-15T19:06:46Z")

</div>

In the meantime I’ve found TemplateButtons.svelte …

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [August 16, 2021, 8:46am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/6 "2021-08-16T08:46:59Z")

</div>

I don’t think onAdvanced() in editor.py is used anymore. I presume Henrik left it in to avoid add-ons throwing errors, though we should probably at least convert the functions to stubs and add a comment at one point to avoid leading people up the wrong path.

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [August 25, 2021, 2:15am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/7 "2021-08-25T02:15:31Z")

</div>

The old code has had deprecation warnings placed on it, and WithShortcut is now available for use in add-ons, but the API is not stable yet: [Using Svelte editor components from Anki - what causes "TypeError: ctx[3] is not a constructor"? - #5 by dae](https://forums.ankiweb.net/t/using-svelte-editor-components-from-anki-what-causes-typeerror-ctx-3-is-not-a-constructor/12387/5)

---

<div class="post-metadata">

**Author:** ![ijgnd](https://avatars.discourse-cdn.com/v4/letter/i/bbe5ce/32.png) [@ijgnd](https://forums.ankiweb.net/u/ijgnd)\
**Post date:** [December 5, 2021, 10:09am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/8 "2021-12-05T10:09:43Z")

</div>

@dae: If in the meantime if you consider WithShortcuts as stable could you add a short example to [https://addon-docs.ankiweb.net/](https://addon-docs.ankiweb.net/) about how to use it from an add-on? This should be relevant for more people than just me.

I checked the published add-ons yesterday and didn’t find another add-on that I could take as an inspiration.

As I wrote earlier: This is relevant for me because I use two part shortcuts as a default in my add-on [Extended Tag Add/Edit Dialog](https://ankiweb.net/shared/info/1135507717). I’d like to keep a combination starting with Ctrl+T because Arthur also has a tag related add-on for med students named [high yield tags](https://ankiweb.net/shared/info/1918380616) that uses two part shortcuts that start with ctrl+t. And my Bettersearch/filter dialog search add-on also uses Ctrl+T,… by default. Actually after talking with ankingmed we decided to switch to these similar shortcuts at the same time last year.

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [December 6, 2021, 7:36am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/9 "2021-12-06T07:36:08Z")

</div>

I’m not sure whether we’re ready to be publicising it yet (@hengiesel is most familiar with this code), but I think it is exported, and something like the following may work:

```auto
function myCallback(event) { ... }

require("anki/shortcuts").registerShortcut(myCallback, "Control+T, X");

```

---

<div class="post-metadata">

**Author:** ![ijgnd](https://avatars.discourse-cdn.com/v4/letter/i/bbe5ce/32.png) [@ijgnd](https://forums.ankiweb.net/u/ijgnd)\
**Post date:** [December 7, 2021, 6:03pm UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/10 "2021-12-07T18:03:46Z")

</div>

So to setup a shortcut in the editor from my python add-on code that’s meant to call some other python command I’d have to use pycmd, e.g. like this?

```python
def handle_js_message(handled, message, context: Editor):
    if message == "1135507717_shorcut":
        ...
    else:
        return handled

def add_editor_shortcut(editor):
    jsstring = """
function extended_tag_shortcut_callback(event) {
    event.preventDefault();
    pycmd("1135507717_shorcut");
}
require("anki/shortcuts").registerShortcut(extended_tag_shortcut_callback, "Control+T, D");
"""
    editor.web.eval(jsstring)

gui_hooks.editor_did_init.append(add_editor_shortcut)
gui_hooks.webview_did_receive_js_message.append(handle_js_message)

```

Or do I miss something? Thanks.

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [December 7, 2021, 11:38pm UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/11 "2021-12-07T23:38:40Z")

</div>

That looks about right - I can’t think of a simpler solution.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex002/uploads/anki2/original/1X/8f1279ababc5879d54e4838989f606cfe55af8c7.jpeg) [@system](https://forums.ankiweb.net/u/system)\
**Post date:** [May 1, 2023, 3:16am UTC](https://forums.ankiweb.net/t/emacs-style-shortcuts-with-ctrl-t-in-the-editor-in-45/12280/12 "2023-05-01T03:16:40Z")

</div>


