Hi, I just discovered your post. I agree with most of your point, but I have some doubts.
However, we are discussing read-only global configuration tables here. It’s common knowledge among developers, even those with little experience, that mutating global variables is a bad idea.
How exactly would you achieve a read only vim.g
table that would let the user overwrite the defaults of a plugin without rewriting every value and still have all the option you need in you plugin?
Hey
That sentence was poorly phrased. I’ve just updated the post to phrase it more clearly:
However, we are discussing global configuration tables which we only read from.
Nothing in Lua is read-only. You can try to achieve that with metatables, but it’s always possible to write to them using rawset
.
What I meant in my post is that we should only read from vim.g
configuration tables in our plugins.
There are two scenarios (that I plan on writing about in more detail in a follow-up):
- Configs that should be set once, at initialisation, and never modified again.
- Configs that can be changed safely (by the user), on the fly.
For the first scenario, I prefer to separate the configs into a public module (containing only luadoc @class
definitions where all fields are optional, which defines the vim.g
table for the user) and an internal module, which has a default configuration table (different luadoc @class
definitions with non-optional fields for internal use).
When the internal module is require
d, I merge the vim.g.
table into the default, validate the result, and from then on treat the resulting config as read-only (of course this can’t be enforced at the type level, but I trust myself to uphold this rule).
Here’s an example of how I’ve applied it.
I haven’t encountered the second scenario in any of my plugins yet, but HiPhish has an interesting article on how to solve that in an elegant way, using metatables. And here’s one of his applications.