I just decided to give Haxe a try to build neovim plugins using Lua. I am very frustrated about how easy si to make silly mistakes in Lua, and being a reasonML developer, Haxe is the closest thing that I can find.
Reading several comments here and there, I ended having the following setup. A build.hxml file that looks like this
My folder structure looks like this
And you, after installing it with packer use it like this:
local module = require("danielo_nvim")
This works great, and I am able to require and execute the lua modules from within neovim, fantastic.
However, the default Haxe export is a bit heavy, specially because I don’t want users of the library to have to instantiate any classes, I just want to expose namespaces with functions.
I achieved this using the
@:expose('name') inside each static function of a class. Is it possible to make this the default behaviour? or maybe a simpler way? A macro?
Finally, I would love to know if there are any neovim api bindings. Will be fantastic to not have to write them myself
I think you can create the api bindings by exporting the api with
nvim --api-info > nvim-api.msgpack and then use a macro to generate the type definitions.
For msgpack reading: https://lib.haxe.org/p/msgpack-haxe/ or convert it to json beforehand with another tool.
Oh wow, that may really cur down the initial manual work.
But I don’t think a macro is a good fit, I prefer a codegen approach. The reason is that the vim api is not very type safe, and require a lot from the programmer in order to properly use it, and I want to add proper type safety on top of it.
Maybe I can make the macro generate private classes and add my own bindings on top of them? not sure how doable that actually is.
But in any case, the idea of exporting the msg-pack to reduce the manual work is awesome, thank you.
Here is the api in json format exported from nvim v0.8.1: Nvim api definition in json format · GitHub
I managed to get haxe-msgpack working quite quickly. Thanks for the recomendation.
Now I’m not sure what to do next. Integrating the build process of the API in my main project, or make it a separate one and consume that by adding the extra safety measures on top…
For hxelectron i am using a macro to build the haxe types from a json file, but then save it to disk using haxe.macro.Printer.
This ensures full type safety, but doesn’t need to run on every build of your project.
So yes, i would make a separate library.
Btw i am currently using nvim for haxe development and am also interested in using haxe for nvim plugin development. Let me know about any progress, maybe i can help.
Oh, you are very welcome to make any contribution, even if it is just a great Idea like the one you already suggested. After your proposal of using the msgpack export to generate the API with a macro I got a lot of help from Rudy on discord (and that means that he did the entire macro) and we already have dozens of methods available within Haxe.
The next step is to (probably) savage some stuff from neodev.nvim to also add documentation on to them.
I am building this inside my personal dotfiles repository, and I am already using it to configure my new additions to my config, and I have to say that it’s being a lovely experience.
It is already paying off in terms of preventing my usual dumb mistakes (that is not a string bro, that is an array, within an array containing a string… the compiler said)
So, if any is interested into the state of the project, I already have all the
vim.api.xxx methods already generated, with a bit nicer types than the ones available at lua.
I am now in the process of parsing all the annotations of neodev and turn those into Haxe types.
This has the advantage of contain documentation, some with even examples, and some types are even specified to be optional (something official Api doesn’t seem to be able to do).
I am self-consuming this bindings, so at least you know they are usable
Will keep you posted!