-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
[WIP] Add vim.create_command for defining commands that callback Lua directly #11613
Conversation
XFREE_CLEAR(cmd->uc_rep); | ||
XFREE_CLEAR(cmd->uc_compl_arg); | ||
if (cmd->uc_argt & EX_LUA_CB) { | ||
lua_State* L = executor_enter_lua(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can use executor_free_luaref()
if (eap->forceit == 1) { | ||
lua_pushliteral(L, "bang"); | ||
lua_pushboolean(L, eap->forceit == 1); | ||
lua_rawset(L, -3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can use lua_setfield()
here (it invokes metamethods, but is safe for a freshly created table)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not put this logic in lua/executor.c
instead of exposing executor_enter_lua
?
lua_do_ucmd(eap);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends on how many places I expected to need lua. With bfredl's recommendation for using executor_free_luaref()
, I would only need to use executor_enter_lua()
once now, which means I could replace it with a single function.
Architecturally, I don't find exposing the ability to do arbitrary Lua elsewhere to be terrible as long as it's used responsibly if it was the choice between that and a bunch of little utility functions.
In this case I think it's fine, but I'm also looking at adding Lua functions for keymappings and autocmds (I know there's an existing PR out there which I'm hoping to pick up). So I'll say for sure after spending more time with that.
But good point, nonetheless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, a "bunch of functions" in lua/executor.c
seems like a better tradeoff than managing Lua state all over the project. That keeps lua/executor.c
encapsulated.
lua_pushboolean(L, eap->forceit == 1); | ||
lua_rawset(L, -3); | ||
} | ||
lua_pcall(L, 2, 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the `nlua_error" pattern can be used here:
if (lua_pcall(...)) {
nlua_error(L, "E5108: Error executing lua: %.*s");
}
@@ -91,6 +91,7 @@ typedef struct ucmd { | |||
int uc_addr_type; // The command's address type | |||
sctx_T uc_script_ctx; // SCTX where the command was defined | |||
char_u *uc_compl_arg; // completion argument if any | |||
LuaRef lua_cb; // A lua callback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Articles are generally noise, and steal title-case from more important words (though "Lua" should be capitalized usually anyways).
LuaRef lua_cb; // A lua callback | |
LuaRef lua_cb; // Lua callback |
see :help dev-doc
} | ||
} | ||
|
||
void define_lua_command(const char *name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use the module common prefix.
void define_lua_command(const char *name, | |
void uc_define_lua_command(const char *name, |
Can we call it
Agreed.
Vimscript |
I would advocate for defaulting vim.create_command(name, callback, {force = true}) I don't know about others, by I've never found guarding against overwriting a command by emitting an error to be a useful feature as a user or a plugin author. So what motivates this suggestion is:
|
This is good but will this work for Python? @justinmk |
Superseded by #16752. |
Functioning example of
vim.create_command(name, callback, force, options)
which allows you to define an ex command which is backed by a Lua callback.callback(arg: string, options: table)
is the current signature, wherearg
is the argument passed to the command directly without any kind of tokenization or further parsing. The options are things like whetherbang
was specified or a range or whatnot.options
in the original will be things likebang
orrange
, etc.The only things to bikeshed are the exact design and I have to read more on the existing ucmd interface and all of the options available, because it's quite thick.
I think that passing the
eap->arg
as-is to the callback isn't a bad idea as compared to supporting options like<f-args>
or<q-args>
because the expectation should be that achieving those things from Lua should be doable and ergonomic. We already havevim.split
andvim.gsplit
which makes it possible to tokenize the argument as you please.TODO: