I did this last week! The process was surprisingly painless. And now I can forget everything I knew about vimscript, which was largely nothing to begin with.
On the up side, now I can rewrite my neovim config from Lua to Fennel! Then I can write a vimscript interpreter in Fennel. And rewrite it all in vimscript again… someone please help…
Can I ask an off-topic question about alt-Lua langs like Fennel, Haxe or Moonscript? If you transpile or interact with Lua, how do you delay or mitigate the interaction with the real world for as long as possible or hold on to a fast feedback loop?
I can imagine compiling/transpiling/whatever from [better lang] to Lua, only to find that it doesn’t work. It reminds me of mobile or web simulation. You want to stay in your happy clean room, iterating fast (with types or tests or [better lang] features) but then when moving to the real world something doesn’t work. Do you put a seam in? Do you automate it away? What does a Fennel workflow look like when the real thing needs to build to lua to manually or automatically test?
Like, let’s say you have your code but then a lua button component in a game you need to interact with. How do avoid writing code in a clean room (unit/function) only to find that the real world is different (shift left)?
Not sure exactly what you mean, and I only really have experience with a couple small projects using Fennel so my perspective is limited. But here goes…
Fennel compiles to Lua, and has essentially transparent FFI with Lua. Its types are Lua types, its functions are Lua functions, etc. You can use Lua modules from Fennel with no intermediate steps, when you run your program it compiles the Fennel code to Lua and then just loads all the Lua modules and executes them. This happens fast enough that for the small projects I’ve done it’s essentially instant. This means that your “happy clean room” already includes whatever real Lua code you’re already using. In my experience this approach can have some serious limitations, but is also part of what makes Fennel in particular Special.
The Fennel compiler is also provided as a library and as a command-line program, so you can precompile all your code if you want and run it through your test suite or whatever. Or if you are operating in another framework you have all the hooks you need to make the process explicit and transparent. You can see what that looks like here. There’s a snippet of Lua code that tells Lua’s module loader “if you find a .fnl file, read it and call fennel.eval() on its contents, then that makes your loaded Lua module”. So in that example, the external Love2D interpreter and such needs to know nothing about Fennel at all, it just sees the Lua modules you hand it.
If you have a lua button component in a game, then it’s going to be a Lua table or something that looks like it (maybe an FFI object exposing methods). You can manipulate it in Fennel exactly like you would in Lua: call constructor, access fields, call methods, etc. You can write a callback in Fennel and it will work transparently.
I did this last night, which is why I posted the above blog post :) It was one of several helpful resources for me. The trick about vim.cmd([[... ]]) being equivalent to any line(s) in your existing init.vim file was definitely handy. I still have a few pieces of configuration in vimscript that I’m not sure how to correctly duplicate in lua - in particular, a custom vimscript function I have bound to C-n, that didn’t seem to override the ordinary behavior of n in Nvim when I used vim.api.nvim_set_keymap to do the binding in Lua.
Any idea why one should switch to Lua for their config?
As far as I know, the reasons are any/all of:
A big part for me was the frustration of learning vimscript while knowing that I will never use this knowledge and code anywhere else. Now when I mess with my nvim configs or writing a new plugin, I’m also practicing my lua which I can use in other projects. :)
Yeah good point. I do know (some) vimscript but have converted (most) of my configs to lua specifically to learn lua.
I would switch in a heartbeat to Lua for my configs in all software I use instead of the usual JSON, YAML, TOML.
Why? Because it allows me to script and abstract things I might want. For the cases I don’t want to abstract anything, I can simply use Lua table notation instead of JSON and serve basically the same purpose.
It also allows software to move from configuration files to initialization files. The change might seem subtle, but with initialization files, you don’t need to outsmart your user and provide all the features they might ever want or need as you do with dumb configuration files. Instead, you can provide a flexible API and let them build initialization files to serve their unique personal needs.
In https://changelog.com/podcast/457 TJ (neovim maintainer) says don’t switch to lua just for the sake of it. Search for “to write your entire configuration”.
I took a snippet of mine that I thought was confusing (to me) in vimscript and ported it over. It didn’t take too long and I had to learn the vim apis to invoke lua etc which was new to me.
This strikes me as accurate. I was able to get most of my existing init.vim ported to lua, with a couple of small bits not working correctly (or at least me not knowing how to make them work correctly yet). As I mentioned in my above comment, I could leave those small pices in vim.cmd([[ ... ]]) blocks in init.lua and have them work the same as they did before, which is fine by me. This podcast was recorded in August 2021, and I’m looking forward to further improvements in the configuration APIs from the neovim contributors.
vim.cmd([[ ... ]])
My own motivation for switching was some mix of wanting to try out this new Lua-in-Neovim thing I’d been hearing about, partially wanting to move to some fancy new post-Neovim-0.5 plugins that all had configuration documentation in Lua, and partially wanting to break up my lengthy init.vim into several smaller files. I don’t actually know if it’s impossible to do that in Vimscript, but it was certainly straightforward in Lua.
Lua is simple and logical, vimscript seems to be the opposite of that.