-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathkickstart-python.lua
339 lines (304 loc) · 11.4 KB
/
kickstart-python.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
-- BOOTSTRAP the plugin manager `lazy.nvim` https://lazy.folke.io/installation
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
local lazyLocallyAvailable = vim.uv.fs_stat(lazypath) ~= nil
if not lazyLocallyAvailable then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }):wait()
if out.code ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
--------------------------------------------------------------------------------
-- define what key is used for `<leader>`. Here, we use `,`.
-- (`:help mapleader` for information what the leader key is)
vim.g.mapleader = ","
local plugins = {
-- TOOLING: COMPLETION, DIAGNOSTICS, FORMATTING
-- MASON
-- * Manager for external tools (LSPs, linters, debuggers, formatters)
-- * auto-install those external tools
{
"WhoIsSethDaniel/mason-tool-installer.nvim",
dependencies = {
{ "williamboman/mason.nvim", opts = true },
{ "williamboman/mason-lspconfig.nvim", opts = true },
},
opts = {
ensure_installed = {
"pyright", -- LSP for python
"ruff", -- linter & formatter (includes flake8, pep8, black, isort, etc.)
"debugpy", -- debugger
"taplo", -- LSP for toml (e.g., for pyproject.toml files)
},
},
},
-- Setup the LSPs
-- `gd` and `gr` for goto definition / references
-- `<C-f>` for formatting
-- `<leader>c` for code actions (organize imports, etc.)
{
"neovim/nvim-lspconfig",
keys = {
{ "gd", vim.lsp.buf.definition, desc = "Goto Definition" },
{ "gr", vim.lsp.buf.references, desc = "Goto References" },
{ "<leader>c", vim.lsp.buf.code_action, desc = "Code Action" },
{ "<C-f>", vim.lsp.buf.format, desc = "Format File" },
},
init = function()
-- this snippet enables auto-completion
local lspCapabilities = vim.lsp.protocol.make_client_capabilities()
lspCapabilities.textDocument.completion.completionItem.snippetSupport = true
-- setup pyright with completion capabilities
require("lspconfig").pyright.setup({
capabilities = lspCapabilities,
})
-- setup taplo with completion capabilities
require("lspconfig").taplo.setup({
capabilities = lspCapabilities,
})
-- ruff uses an LSP proxy, therefore it needs to be enabled as if it
-- were a LSP. In practice, ruff only provides linter-like diagnostics
-- and some code actions, and is not a full LSP yet.
require("lspconfig").ruff.setup({
-- disable ruff as hover provider to avoid conflicts with pyright
on_attach = function(client) client.server_capabilities.hoverProvider = false end,
})
end,
},
-- COMPLETION
{
"saghen/blink.cmp",
version = "v0.*", -- blink.cmp requires a release tag for its rust binary
opts = {
-- 'default' for mappings similar to built-in vim completion
-- 'super-tab' for mappings similar to vscode (tab to accept, arrow keys to navigate)
-- 'enter' for mappings similar to 'super-tab' but with 'enter' to accept
keymap = { preset = "default" },
highlight = {
-- sets the fallback highlight groups to nvim-cmp's highlight groups
-- useful for when your theme doesn't support blink.cmp
use_nvim_cmp_as_default = true,
},
-- set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
-- adjusts spacing to ensure icons are aligned
nerd_font_variant = "mono",
},
},
-----------------------------------------------------------------------------
-- PYTHON REPL
-- A basic REPL that opens up as a horizontal split
-- * use `<leader>i` to toggle the REPL
-- * use `<leader>I` to restart the REPL
-- * `+` serves as the "send to REPL" operator. That means we can use `++`
-- to send the current line to the REPL, and `+j` to send the current and the
-- following line to the REPL, like we would do with other vim operators.
{
"Vigemus/iron.nvim",
keys = {
{ "<leader>i", vim.cmd.IronRepl, desc = " Toggle REPL" },
{ "<leader>I", vim.cmd.IronRestart, desc = " Restart REPL" },
-- these keymaps need no right-hand-side, since that is defined by the
-- plugin config further below
{ "+", mode = { "n", "x" }, desc = " Send-to-REPL Operator" },
{ "++", desc = " Send Line to REPL" },
},
-- since irons's setup call is `require("iron.core").setup`, instead of
-- `require("iron").setup` like other plugins would do, we need to tell
-- lazy.nvim which module to via the `main` key
main = "iron.core",
opts = {
keymaps = {
send_line = "++",
visual_send = "+",
send_motion = "+",
},
config = {
-- This defines how the repl is opened. Here, we set the REPL window
-- to open in a horizontal split to the bottom, with a height of 10.
repl_open_cmd = "horizontal bot 10 split",
-- This defines which binary to use for the REPL. If `ipython` is
-- available, it will use `ipython`, otherwise it will use `python3`.
-- since the python repl does not play well with indents, it's
-- preferable to use `ipython` or `bypython` here.
-- (see: https://github.com/Vigemus/iron.nvim/issues/348)
repl_definition = {
python = {
command = function()
local ipythonAvailable = vim.fn.executable("ipython") == 1
local binary = ipythonAvailable and "ipython" or "python3"
return { binary }
end,
},
},
},
},
},
-----------------------------------------------------------------------------
-- SYNTAX HIGHLIGHTING & COLORSCHEME
-- treesitter for syntax highlighting
-- * auto-installs the parser for python
{
"nvim-treesitter/nvim-treesitter",
-- automatically update the parsers with every new release of treesitter
build = ":TSUpdate",
-- since treesitter's setup call is `require("nvim-treesitter.configs").setup`,
-- instead of `require("nvim-treesitter").setup` like other plugins do, we
-- need to tell lazy.nvim which module to via the `main` key
main = "nvim-treesitter.configs",
opts = {
highlight = { enable = true }, -- enable treesitter syntax highlighting
indent = { enable = true }, -- better indentation behavior
ensure_installed = {
-- auto-install the Treesitter parser for python and related languages
"python",
"toml",
"rst",
"ninja",
"markdown",
"markdown_inline",
},
},
},
-- COLORSCHEME
-- In neovim, the choice of color schemes is unfortunately not purely
-- aesthetic – treesitter-based highlighting or newer features like semantic
-- highlighting are not always supported by a color scheme. It's therefore
-- recommended to use one of the popular, and actively maintained ones to get
-- the best syntax highlighting experience:
-- https://dotfyle.com/neovim/colorscheme/top
{
"folke/tokyonight.nvim",
-- ensure that the color scheme is loaded at the very beginning
priority = 1000,
-- enable the colorscheme
config = function() vim.cmd.colorscheme("tokyonight") end,
},
-----------------------------------------------------------------------------
-- DEBUGGING
-- DAP Client for nvim
-- * start the debugger with `<leader>dc`
-- * add breakpoints with `<leader>db`
-- * terminate the debugger `<leader>dt`
{
"mfussenegger/nvim-dap",
keys = {
{
"<leader>dc",
function() require("dap").continue() end,
desc = "Start/Continue Debugger",
},
{
"<leader>db",
function() require("dap").toggle_breakpoint() end,
desc = "Add Breakpoint",
},
{
"<leader>dt",
function() require("dap").terminate() end,
desc = "Terminate Debugger",
},
},
},
-- UI for the debugger
-- * the debugger UI is also automatically opened when starting/stopping the debugger
-- * toggle debugger UI manually with `<leader>du`
{
"rcarriga/nvim-dap-ui",
dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" },
keys = {
{
"<leader>du",
function() require("dapui").toggle() end,
desc = "Toggle Debugger UI",
},
},
-- automatically open/close the DAP UI when starting/stopping the debugger
config = function()
local listener = require("dap").listeners
listener.after.event_initialized["dapui_config"] = function() require("dapui").open() end
listener.before.event_terminated["dapui_config"] = function() require("dapui").close() end
listener.before.event_exited["dapui_config"] = function() require("dapui").close() end
end,
},
-- Configuration for the python debugger
-- * configures debugpy for us
-- * uses the debugpy installation from mason
{
"mfussenegger/nvim-dap-python",
dependencies = "mfussenegger/nvim-dap",
config = function()
-- fix: E5108: Error executing lua .../Local/nvim-data/lazy/nvim-dap-ui/lua/dapui/controls.lua:14: attempt to index local 'element' (a nil value)
-- see: https://github.com/rcarriga/nvim-dap-ui/issues/279#issuecomment-1596258077
require("dapui").setup()
-- uses the debugypy installation by mason
local debugpyPythonPath = require("mason-registry").get_package("debugpy"):get_install_path()
.. "/venv/bin/python3"
require("dap-python").setup(debugpyPythonPath, {}) ---@diagnostic disable-line: missing-fields
end,
},
-----------------------------------------------------------------------------
-- EDITING SUPPORT PLUGINS
-- some plugins that help with python-specific editing operations
-- Docstring creation
-- * quickly create docstrings via `<leader>a`
{
"danymat/neogen",
opts = true,
keys = {
{
"<leader>a",
function() require("neogen").generate() end,
desc = "Add Docstring",
},
},
},
-- f-strings
-- * auto-convert strings to f-strings when typing `{}` in a string
-- * also auto-converts f-strings back to regular strings when removing `{}`
{
"chrisgrieser/nvim-puppeteer",
dependencies = "nvim-treesitter/nvim-treesitter",
},
}
--------------------------------------------------------------------------------
-- tell lazy.nvim to load and configure all the plugins
require("lazy").setup(plugins)
--------------------------------------------------------------------------------
-- SETUP BASIC PYTHON-RELATED OPTIONS
-- The filetype-autocmd runs a function when opening a file with the filetype
-- "python". This method allows you to make filetype-specific configurations. In
-- there, you have to use `opt_local` instead of `opt` to limit the changes to
-- just that buffer. (As an alternative to using an autocmd, you can also put those
-- configurations into a file `/after/ftplugin/{filetype}.lua` in your
-- nvim-directory.)
vim.api.nvim_create_autocmd("FileType", {
pattern = "python", -- filetype for which to run the autocmd
callback = function()
-- use pep8 standards
vim.opt_local.expandtab = true
vim.opt_local.shiftwidth = 4
vim.opt_local.tabstop = 4
vim.opt_local.softtabstop = 4
-- folds based on indentation https://neovim.io/doc/user/fold.html#fold-indent
-- if you are a heavy user of folds, consider using `nvim-ufo`
vim.opt_local.foldmethod = "indent"
local iabbrev = function(lhs, rhs) vim.keymap.set("ia", lhs, rhs, { buffer = true }) end
-- automatically capitalize boolean values. Useful if you come from a
-- different language, and lowercase them out of habit.
iabbrev("true", "True")
iabbrev("false", "False")
-- we can also fix other habits we might have from other languages
iabbrev("--", "#")
iabbrev("null", "None")
iabbrev("none", "None")
iabbrev("nil", "None")
iabbrev("function", "def")
end,
})