2025-08-30.18.27.52.mp4
lazy.nvim
Example Config
return {
---@module 'python'
{
"joshzcold/python.nvim",
dependencies = {
{ "mfussenegger/nvim-dap" },
{ "mfussenegger/nvim-dap-python" },
{ "neovim/nvim-lspconfig" },
{ "L3MON4D3/LuaSnip" },
{ "nvim-neotest/neotest" },
{ "nvim-neotest/neotest-python" },
},
---@type python.Config
opts = { ---@diagnostic disable-line: missing-fields`
}
}
}Include Snippets by enabling python_lua_snippets and adding LuaSnip as a dependency
return {
---@module 'python'
{
"joshzcold/python.nvim",
dependencies = {
{ "mfussenegger/nvim-dap" },
{ "mfussenegger/nvim-dap-python" },
{ "neovim/nvim-lspconfig" },
{ "L3MON4D3/LuaSnip" },
{ "nvim-neotest/neotest" },
{ "nvim-neotest/neotest-python" },
},
---@type python.Config
opts = { ---@diagnostic disable-line: missing-fields`
python_lua_snippets = true
},
}
}vim.pack
Example Config
vim.pack.add("https://github.com/joshzcold/python.nvim")
vim.pack.add("https://github.com/mfussenegger/nvim-dap")
vim.pack.add("https://github.com/mfussenegger/nvim-dap-python")
vim.pack.add("https://github.com/neovim/nvim-lspconfig")
vim.pack.add("https://github.com/L3MON4D3/LuaSnip")
vim.pack.add("https://github.com/nvim-neotest/neotest")
vim.pack.add("https://github.com/nvim-neotest/neotest-python")Configuration Options
return {
---@module 'python'
{
"joshzcold/python.nvim",
---@type python.Config
opts = {
-- Should return a list of tables with a `name` and a `path` entry each.
-- Gets the argument `venvs_path` set below.
-- By default just lists the entries in `venvs_path`.
---@return VEnv[]
get_venvs = function(venvs_path)
return require("python.venv").get_venvs(venvs_path)
end,
-- Path for venvs picker
venvs_path = vim.fn.expand("~/.virtualenvs"),
-- Something to do after setting an environment
post_set_venv = nil,
-- base path for creating new venvs
auto_create_venv_path = function(parent_dir)
return vim.fs.joinpath(parent_dir, ".venv")
end,
-- Patterns for autocmd LspAttach that trigger the auto venv logic
-- Add onto this list if you depend on venvs for other file types
-- like .yaml, .yml for ansible
auto_venv_lsp_attach_patterns = { "*.py" },
-- Buffer patterns to activate commands for python.nvim
command_setup_buf_pattern = { "*.py" },
-- Load python.nvim python snippets
python_lua_snippets = false,
-- List of text actions to take on InsertLeave, TextChanged
-- Put in empty table or nil to disable
enabled_text_actions = {
"f-strings", -- When inserting {}, put in an f-string
},
-- Adjust when enabled_text_actions is triggered
enabled_text_actions_autocmd_events = { "InsertLeave" },
treesitter = {
functions = {
-- Wrap treesitter identifier under cursor using substitute_options
wrapper = {
-- Substitute options for PythonTSWrapWithFunc
substitute_options = {
"print(%s)",
"log.debug(%s)",
"log.info(%s)",
"log.warning(%s)",
"log.error(%s)",
"np.array(%s)",
},
-- Look for tree-sitter types to wrap
find_types = {
"tuple",
"string",
"true",
"false",
"list",
"call",
"parenthesized_expression",
"expression_statement",
"integer",
},
},
},
},
-- Load python keymaps. Everything starting with <leader>p...
keymaps = {
-- following nvim_set_keymap() mode, lhs, rhs, opts
mappings = {
["<leader>pv"] = { "n", "<cmd>Python venv pick<cr>", { desc = "python.nvim: pick venv" } },
["<leader>pi"] = { "n", "<cmd>Python venv install<cr>", { desc = "python.nvim: python venv install" } },
["<leader>pd"] = { "n", "<cmd>Python dap<cr>", { desc = "python.nvim: python run debug program" } },
-- Test Actions
["<leader>ptt"] = { "n", "<cmd>Python test test<cr>", { desc = "python.nvim: python run test suite" } },
["<leader>ptm"] = { "n", "<cmd>Python test test_method<cr>", { desc = "python.nvim: python run test method" } },
["<leader>ptf"] = { "n", "<cmd>Python test test_file<cr>", { desc = "python.nvim: python run test file" } },
["<leader>ptdd"] = { "n", "<cmd>Python test test_debug<cr>", { desc = "python.nvim: run test suite in debug mode." } },
["<leader>ptdm"] = {
"n",
"<cmd>Python test test_method_debug<cr>",
{ desc = "python.nvim: run test method in debug mode." },
},
["<leader>ptdf"] = {
"n",
"<cmd>Python test_file_debug<cr>",
{ desc = "python.nvim: run test file in debug mode." },
},
-- VEnv Actions
["<leader>ped"] = {
"n",
"<cmd>Python venv delete_select<cr>",
{ desc = "python.nvim: select and delete a known venv." },
},
["<leader>peD"] = { "n", "<cmd>Python venv delete<cr>", { desc = "python.nvim: delete current venv set." } },
-- Language Actions
["<leader>ppe"] = {
"n",
"<cmd>Python treesitter toggle_enumerate<cr>",
{ desc = "python.nvim: turn list into enumerate" },
},
["<leader>ppw"] = {
"n",
"<cmd>Python treesitter wrap_cursor<cr>",
{ desc = "python.nvim: wrap treesitter identifier with pattern" },
},
["<leader>pw"] = {
"v",
":Python treesitter wrap_cursor<cr>",
{ desc = "python.nvim: wrap treesitter identifier with pattern" },
},
},
},
-- Settings regarding ui handling
ui = {
-- Amount of time to pause closing of ui after a finished task
ui_close_timeout = 5000,
-- Default ui style for interfaces created by python.nvim
---@alias python_ui_default_style "'popup'|'split'|nil"
default_ui_style = "popup",
-- Customize the position and behavior of the ui style
popup = {
win_opts = {
-- border = "rounded",
-- relative = "win",
-- focusable = true,
-- title = "python.nvim",
-- anchor = "SE",
-- zindex = 999,
-- width = 40,
-- height = 20,
-- row = vim.o.lines - 3,
-- col = vim.o.columns -2,
},
},
split = {
win_opts = {
-- split = 'below',
-- win = 0,
-- width = 40,
-- height = 10,
-- focusable = true,
},
},
},
-- Tell neotest-python which test runner to use
test = {
test_runner = "pytest",
},
}
}
}
-
Switch between virtual envs interactively
-
Interactively create virtual envs and install dependencies
- Reload all the common python LSP servers if found to be running
- Lot of commands to control venvs
-
Keep track of envs/pythons per project in state
-
Easier setup of python debugging
- Automatically install debugpy into venv
- Interactively create a DAP config for a program, saving configuration.
-
Utility features
- Function to swap type checking mode for pyright, basedpyright
- Function to launch test method, class, etc. in DAP
- Functions to install python interpreters via hatch
-
Optional Python Snippets through luasnip
Enable with
python_lua_snippetsin config -
Integration with neotest. Commands to easily run tests through venv setup with
python.nvimSee
testin config and:PythonTest*commands -
Treesitter integration
-
Functions utilizing treesitter for helpful code actions
-
Auto insert fstrings while typing
{}See
enabled_text_actionsin config -
Toggle a list into an
enumerate()list with indexTry
:Python treesitter toggle_enumerateon afor x in listlist -
Wrap treesitter objects with a pattern.
Try
:Python treesitter wrap_cursoron a list or tuple. Check config for options Can turn[1, 2, 3]->np.array([1, 2, 3])Supply a pattern to immediately wrap like:Python treesitter wrap_cursor np.array(%s)Select in visual mode and execute:'<'>Python treesitter wrap_cursor
| Default KeyMap | Command | Functionality |
|---|---|---|
<leader>pi |
:Python venv install |
Create a venv and install dependencies if a supported python package format is found |
<leader>pd |
:Python dap |
Create and save a new Dap configuration |
<leader>ptt |
:Python test test |
Run Suite of tests with neotest |
<leader>ptm |
:Python test test_method |
Run test function/method with neotest |
<leader>ptf |
:Python test test_file |
Run test file with neotest |
<leader>ppe |
:Python treesitter toggle_enumerate |
Turn a regular list into enumerate() list and back |
<leader>ppw |
:Python treesitter wrap_cursor |
Wrap treesitter indentifiers in a pattern for quick injection. |
visual mode <leader>pw |
:Python treesitter wrap_cursor |
Wrap treesitter indentifiers in visual mode |
| Default KeyMap | Command | Functionality |
|---|---|---|
<leader>ped |
:Python venv delete_select |
Select a venv to delete from python.nvim state |
<leader>peD |
:Python venv delete |
Delete current selected venv in project in python.nvim state |
<leader>ptdd |
:Python test test_debug |
Run Suite of tests with neotest in dap mode with dap-python |
<leader>ptdm |
:Python test test_method_debug |
Run test function/method with neotest in dap mode with dap-python |
<leader>ptdf |
:Python test test_file_debug |
Run test file with neotest in dap mode with dap-python |
none |
:Python hatch list |
List python interpreters installed by hatch |
none |
:Python hatch install |
Install a python interpreter using hatch |
none |
:Python hatch delete |
Delete a python interpreter from hatch |
none |
:Python uv install_python |
Delete a python interpreter from uv |
none |
:Python uv delete_python |
Delete a python interpreter from uv |
none |
:UV <command> |
Pass through commands to uv with command line completion |
| Manager | Install File | Install Method |
|---|---|---|
| uv | uv.lock | uv sync --active --frozen |
| uv | /// script block |
uv sync --sync --script % --active |
| pdm | pdm.lock | pdm sync |
| poetry | poetry.lock | poetry sync --no-root |
| pip | pyproject.toml | pip install . |
| pip | dev-requirements.txt | pip install -r |
| pip | requirements.txt | pip install -r |
| conda | - | When using the environment picker. python.nvim saves the environment you last used in state. |
-
Linux
-
MacOS
- I am detecting python interpreters in homebrew and hatch and uv. Testing in ci.
-
Windows (Un tested)
- Need to test this plugin on a windows machine to verify. I have seen online that neovim users are deciding on WezTerm + WSL to handle support for neovim plugins.
swenv.nvim For almost all of the logic in selecting virtual envs. Use this plugin if you want a more simple venv management plugin for your workflow.
go.nvim for inspiration.
nvim-puppeteer for treesitter action on inserting f-strings