Skip to content

Load dictionary asynchronously#3

Open
Iron-E wants to merge 9 commits into
swaits:mainfrom
Iron-E:main
Open

Load dictionary asynchronously#3
Iron-E wants to merge 9 commits into
swaits:mainfrom
Iron-E:main

Conversation

@Iron-E
Copy link
Copy Markdown
Contributor

@Iron-E Iron-E commented Feb 24, 2026

This MR updates the dictionary loading logic so that it runs asynchronously.

Motivation

The README says:

It also loads the dictionary in the background, so it doesn't delay startup time.

However, when starting Neovim, there is a noticeable stutter (naive profiling shows about 1-2s) while loading the abbreviations. Here is my Lazy config:

{
	"swaits/thethethe.nvim",
	config = true,
	event = "InsertEnter",
}

With this MR, the loading happens truly asynchronously, and responsiveness is not affected (that I can tell).

Changes

The bulk of the performance improvements come from three areas:

  1. Converting the dictionary to Lua.

    Not having to parse the raw string into a table prevents extra work each startup. Though, I am unfamiliar with the reason why a string was chosen originally, so it could be there was a strong reason to use a string.

  2. Using coroutines to arrange creation of iabbrevs.

    This is what actually makes it async.

    On this MR, iabbrevs (now nvim_set_keymap, see point 3) is vim.scheduled. This allows the event loop to process
    other events in-between ours, making the editor more responsive during initialization.

    Each scheduled iabbrev contains an instruction to schedule the next iabbrev, until all are loaded. This way,
    we do not fire off a large number of vim.schedule calls right away.

    To facilitate this, I used coroutines, since this makes it easier to arrange this type of behavior.

  3. Switching to nvim_set_keymap from vim.cmd.

    The nvim_set_keymap API call supports an "ia" mode, wihch is equivalent to iabbrev AFAICT.

    I looked on the README for a compatibility promise for Neovim versions (e.g. "0.8+"), but didn't notice one. There is a chance this has repercussions on backwards compatibility, but without knowing the supported versions, I can't say for sure.


Let me know if you have any comments/concerns 🙂

I would be happy to make this a toggle if needed, so that users can opt-in to the async behavior.

Iron-E and others added 5 commits February 5, 2024 20:28
* NOne -> None (common in Rust code)
* defualt -> default (common in C# code)
* Locatoin -> Location
It was previously just a big string, which needed to be parsed.
This is computationally expensive compared to just returning a table.
The README says this loads in the background, but I found that
what it really does is "defer" execution, and then do it in bulk.
This leads to a 1s+ long stutter when opening Neovim.

This commit refactors this, so that abbreviations are actually loaded in
the background. I can now type smoothly without interruptions.
If there is a problem, I think we should report it properly as an `error`
in `load_abbreviations`. However, we should also not make a bad user
experience, and so we should use `vim.notify` to tell the user something
bad happened (instead of letting the error propagate).
This has the same responsiveness characteristics,
but is easier to handle (and takes much less code).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants