Playdate Development with Neovim

I have been using Vim/Neovim as my editor for two years now, but I haven’t made an effort to dive into the topic that is LSPLanguage Server Protocol. Since I also want to get into game development for the Playdate, I figured I’d marry those two topics and see how far I can get making Neovim my Playdate IDE (integrated development environment).

Others have tried that before and have shared their approach in the Neovim central thread on the Playdate forum.

Add LSP Features to Neovim

Neovim supports LSP by acting as an LSP client. I decided not to go with a one-stop shop solution like LSP Zero to learn a bit more about the underlying mechanics. There is abundant material on (Neo)Vim and LSP online, but everyone does it a tiny bit different which makes it tricky to piece everything together. My advice: Take the time to learn Lua and learn from other people’s configuration files.

Some resources that have helped me shape my understanding:

After doing my research and understanding the vocabulary of the LSP landscape, I decided to go with these well-established plugins:

My Neovim configuration is on Sourcehut. The other listed dependencies are necessary for plugins to play nice with each other and to extend the autocompletion capabilities.

Playdate-Specific Configurations

After working through the Playdate documentation for Lua and installing the SDK (software development kit), I wanted to add Playdate-specific settings to my LSP configuration. All possible settings can be found in the wiki of the Lua language server.

I changed my settings to achieve the following:

It was not enough to add $PLAYDATE_SDK_PATH/CoreLibs as a library; I would get some autocompletion but not everything. For example, the global playdate did not get picked up along with all fields as it seems. playdate-luacats is doing a much better job! In the end, I decided to add both: $PLAYDATE_SDK_PATH (without the /CoreLibs) to complete CoreLibs imports, and playdate-luacats for everything else.

2025-02-21: Compiler Plugin

The Playdate SDK comes with its own compiler pdc. Since leaving Vim to build my code and going back into Vim to make necessary changes is a cumbersome workflow, I started to look into ways of compiling my code inside the editor. Vim offers a couple of solutions for that.

The naïve approach is running executables via Vim’s command line, for example :!pdc % build/out.pdx where % is a shorthand for the filepath of the active buffer. I am calling it naïve because there are two flaws: (1) the compiler output is gone as soon as I hit a key, and (2) the compiling happens synchronously, i.e. I can’t operate Vim while waiting for the compilation to finish.

The first point can be addressed by creating a compiler plugin. Vim ships with many compiler plugins out of the box—use :compiler <tab> to cycle through them—but not for pdc. Luckily, creating one myself comes down to only setting two options: makeprg for the executable I want to run my code against, and errorformat to tell Vim how to parse compiler output into the quickfix list.

if vim.g.current_compiler ~= nil then
  return
end
vim.g.current_compiler = "pdc"

-- Create build folder
local cwd = vim.fn.getcwd()
local project = vim.fn.fnamemodify(cwd, ":t")
vim.fn.mkdir(cwd .. "/build", "p") -- If exists, exits silently

local errorformat = {
  "%t%*[^:]: %f:%l:%m"
}

vim.o.makeprg = "pdc " .. cwd .. "/source " .. cwd .. "/build/" .. project .. ".pdx"
vim.o.errorformat = table.concat(errorformat, ",")

This code also created a dedicated build folder to keep things clean in my project directory. Now I can tell Vim to use my compiler plugin for Playdate Lua files with :compiler pdc and run :make to compile my code. If there are any issues, Vim will populate the quickfix list with entries that take me to the respective lines.

To solve the second nuisance—synchronous compilation that blocks me—I installed the plugin vim-dispatch. This extension adds the command :Make which compiles my code asynchronously and automatically opens the quickfix list should there be any issues. Nice!

On Vim compiler plugins, the quickfix list, and vim-dispatch:

2025-02-27: More Convenience

Spoiler: I am madly in love with my current Playdate development setup in Neovim!

What did I do? First, I created an ftplugin for Lua that sets pdc as the compiler and adds a keyboard shortcut for :Make if there is a source/main.lua file in the working directory. I use that—admittedly somewhat flimsy—check (derived from Playdate’s suggested project structure) to detect whether a Lua project is also a Playdate project. I might change that to checking for a pdxinfo file at the project root.

Second, I extended my makeprg command to include a call to the Playdate simulator after compiling the code. Thanks to the added support for Neovim’s terminal emulator via the dispatch-neovim plugin, I get all the console output of the simulator straight into my editor. Build and run at the press of a button!

Code, compilation, simulator, debug output—everything happens or is triggered inside Neovim.