Skip to main content

Lua and Python Setup

Lua Setup (for Neovim Config Development)

Lua is Neovim's native config language, so proper Lua IDE support is critical for maintaining your own config.

Required LSP Server

# lua_ls (Lua Language Server) — installed via Mason
:MasonInstall lua-language-server

Lua LSP Configuration

In your LSP config:
lspconfig.lua_ls.setup({
on_attach = on_attach,
capabilities = capabilities,
settings = {
Lua = {
runtime = { version = "LuaJIT" },
diagnostics = {
globals = { "vim" }, -- don't warn about 'vim' global
},
workspace = {
library = vim.api.nvim_get_runtime_file("", true),
checkThirdParty = false,
},
completion = {
callSnippet = "Replace",
},
telemetry = { enable = false },
},
},
})

neodev.nvim — Better Neovim API Completions

Add as dependency to nvim-lspconfig:
{
"folke/neodev.nvim",
opts = {
library = {
enabled = true,
runtime = true,
types = true,
plugins = true, -- include installed plugins in completion
},
},
},

Lua Formatter

# Install stylua
cargo install stylua
# or:
brew install stylua
none-ls source:
null_ls.builtins.formatting.stylua,

.stylua.toml Config

.stylua.toml
indent_type = "Spaces"
indent_width = 2
column_width = 100
quote_style = "AutoPreferDouble"

Python Setup

Required Tools

# LSP server
pip install pyright # or: :MasonInstall pyright

# Formatters
pip install black isort

# Linters
pip install flake8 pylint

# Type stubs (for better completions)
pip install types-requests types-PyYAML

Python LSP Configuration

lspconfig.pyright.setup({
on_attach = on_attach,
capabilities = capabilities,
settings = {
python = {
analysis = {
typeCheckingMode = "basic", -- "off" | "basic" | "strict"
autoSearchPaths = true,
useLibraryCodeForTypes = true,
diagnosticMode = "workspace", -- analyze entire project
autoImportCompletions = true,
},
},
},
})

Python Formatters and Linters (none-ls)

null_ls.setup({
sources = {
-- Formatters
null_ls.builtins.formatting.black.with({
extra_args = { "--line-length", "88" },
}),
null_ls.builtins.formatting.isort.with({
extra_args = { "--profile", "black" },
}),

-- Linters
null_ls.builtins.diagnostics.flake8.with({
extra_args = { "--max-line-length", "88", "--extend-ignore", "E203" },
}),
},
})

.flake8 Config

.flake8
[flake8]
max-line-length = 88
extend-ignore = E203, W503
exclude = .git, __pycache__, .venv, dist

Virtual Environment Awareness

lua/config/autocmds.lua
-- Auto-activate Python venv
vim.api.nvim_create_autocmd("BufEnter", {
pattern = "*.py",
callback = function()
local venv = vim.fn.finddir(".venv", vim.fn.getcwd() .. ";")
if venv ~= "" then
local python = venv .. "/bin/python"
if vim.fn.executable(python) == 1 then
vim.g.python3_host_prog = python
end
end
end,
})

What's Next