- Format:
stylua . - Format check:
stylua --check . - Lint:
luarocks install luacheck && luacheck . - Test all:
vusted ./test - Test single:
vusted ./test/plugin_spec.lua
lua/
micropython_nvim/ # Internal modules
config.lua # Configuration defaults and state
run.lua # Run/upload code to device
setup.lua # Configure port, baud, stubs
repl.lua # REPL access
project.lua # Project initialization
utils.lua # File I/O, config, helpers
micropython_nvim.lua # Main entry point, public API
plugin/
micropython_nvim.lua # Vim commands, lazy-loads plugin
test/
plugin_spec.lua # vusted test suite
doc/
micropython.nvim.txt # Help documentation
-- Every module follows this structure
local M = {}
-- Private state
local state = {}
-- Private functions (local, underscore prefix)
local function _helper() end
-- Public methods
function M.public_func() end
return M| Type | Convention | Example |
|---|---|---|
| Functions | snake_case | get_port, upload_current |
| Private funcs | underscore prefix | local function _helper() |
| Variables | snake_case | ampy_port, file_path |
| Constants | UPPER_CASE | M.BAUD_RATES, M.DEFAULT_IGNORE_LIST |
| Module table | M |
local M = {} |
| Requires | PascalCase | local Config = require(...) |
Required on all public functions and classes:
---@class MicroPython.Config
---@field port? string Device port
---@field baud? number Baud rate
---@field debug? boolean Enable debug logging
---@param opts? MicroPython.Config
function M.setup(opts) end
---@return string
function M.get_port() end-- pcall for external calls
local ok, handle = pcall(io.popen, command)
if not ok or not handle then
vim.notify("Command failed", vim.log.levels.WARN, { title = "micropython.nvim" })
return {}
end
-- Validate user input in callbacks
vim.ui.select(options, { prompt = "Select:" }, function(choice)
if not choice then
return
end
-- proceed with choice
end)- Formatter: stylua (100 char line width, 2 space indent, AutoPreferSingle quotes)
- Use
local M = {}module pattern, returnMat end - Use
vim.ui.selectfor user interaction - Use
vim.notifywithvim.log.levelsand{ title = "micropython.nvim" } - Template strings using
[[...]]for multi-line content
-- lua/micropython_nvim/config.lua
local defaults = {
port = "/dev/ttyUSB0",
baud = 115200,
debug = false,
}
---@param opts? MicroPython.Config
function M.setup(opts)
M.config = vim.tbl_deep_extend("force", defaults, opts or {})
endrequire("micropython_nvim").setup({
port = "/dev/ttyACM0",
baud = 115200,
debug = true,
})vusted
describe("feature", function()
before_each(function()
-- Reset state
end)
it("does thing", function()
assert.same(expected, actual)
end)
end)-- lua/micropython_nvim.lua exposes clean API, delegates to internal modules
local M = {}
function M.setup(opts)
require("micropython_nvim.config").setup(opts)
require("micropython_nvim.utils").read_ampy_config()
end
function M.run()
require("micropython_nvim.run").run()
end
return MAll public API methods use lazy requires:
function M.run()
require("micropython_nvim.run").run()
end-- plugin/micropython_nvim.lua
vim.api.nvim_create_user_command("MPRun", function()
require("micropython_nvim").run()
end, { desc = "Run current buffer on MicroPython device" })local function _async_job(command, command_name)
vim.fn.jobstart(command, {
on_exit = function(_, exit_status, _)
if exit_status == 0 then
vim.notify(command_name .. " completed", vim.log.levels.INFO, { title = "micropython.nvim" })
end
end,
})
end- Create
lua/micropython_nvim/feature.lua - Add type annotations with
---@ - Export from
lua/micropython_nvim.luaif public - Add command in
plugin/micropython_nvim.lua - Add tests in
test/plugin_spec.lua
- Add to defaults in
config.lua - Add
---@fieldannotation toMicroPython.Config - Document in README
-- plugin/micropython_nvim.lua
vim.api.nvim_create_user_command("MPNewCommand", function(opts)
require("micropython_nvim").feature(opts.args)
end, { nargs = "?", desc = "Description" })- Config state: Use
config.luamodule instead of_Gtable - Command assembly: Use
string.format()for ampy/rshell commands - Terminal usage: Use
Snacks.terminal(command)for floating terminals - Async operations: Use
vim.fn.jobstart()withon_exitcallback - File operations: Use
vim.fnfunctions for file I/O in user-facing code,io.*for internals - Project root: All operations assume Neovim opened at project root
- Config sync: Update both config module state and
.ampyfile
- Always validate user input in
vim.ui.selectcallbacks (check fornil) - Use
2>&1in terminal commands to capture errors - Verify file readability with
vim.fn.filereadable()before operations - Handle
nilreturns from file operations gracefully - Use
pcallfor external command execution with graceful degradation