Revert "feat: add .NET development plugins and improve LSP navigation fallbacks"
This reverts commit 20b41844de.
This commit is contained in:
parent
20b41844de
commit
a18d7270b6
58
init.lua
58
init.lua
|
|
@ -416,15 +416,6 @@ require('lazy').setup({
|
|||
group = vim.api.nvim_create_augroup('telescope-lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local buf = event.buf
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
|
||||
local goto_declaration = function()
|
||||
if client and client:supports_method('textDocument/declaration', buf) then
|
||||
vim.lsp.buf.declaration()
|
||||
else
|
||||
builtin.lsp_definitions()
|
||||
end
|
||||
end
|
||||
|
||||
-- Find references for the word under your cursor.
|
||||
vim.keymap.set('n', 'grr', builtin.lsp_references, { buffer = buf, desc = '[G]oto [R]eferences' })
|
||||
|
|
@ -436,9 +427,7 @@ require('lazy').setup({
|
|||
-- Jump to the definition of the word under your cursor.
|
||||
-- This is where a variable was first declared, or where a function is defined, etc.
|
||||
-- To jump back, press <C-t>.
|
||||
vim.keymap.set('n', 'gd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' })
|
||||
vim.keymap.set('n', 'grd', builtin.lsp_definitions, { buffer = buf, desc = '[G]oto [D]efinition' })
|
||||
vim.keymap.set('n', 'gD', goto_declaration, { buffer = buf, desc = '[G]oto [D]eclaration' })
|
||||
|
||||
-- Fuzzy find all the symbols in your current document.
|
||||
-- Symbols are things like variables, functions, types, etc.
|
||||
|
|
@ -491,15 +480,7 @@ require('lazy').setup({
|
|||
-- Automatically install LSPs and related tools to stdpath for Neovim
|
||||
-- Mason must be loaded before its dependents so we need to set it up here.
|
||||
-- NOTE: `opts = {}` is the same as calling `require('mason').setup({})`
|
||||
{
|
||||
'mason-org/mason.nvim',
|
||||
opts = {
|
||||
registries = {
|
||||
'github:mason-org/mason-registry',
|
||||
'github:Crashdummyy/mason-registry',
|
||||
},
|
||||
},
|
||||
},
|
||||
{ 'mason-org/mason.nvim', opts = {} },
|
||||
{ 'mason-org/mason-lspconfig.nvim', opts = {} },
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
|
||||
|
|
@ -542,8 +523,6 @@ require('lazy').setup({
|
|||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }),
|
||||
callback = function(event)
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
|
||||
-- NOTE: Remember that Lua is a real programming language, and as such it is possible
|
||||
-- to define small helper and utility functions so you don't have to repeat yourself.
|
||||
--
|
||||
|
|
@ -558,28 +537,20 @@ require('lazy').setup({
|
|||
-- Most Language Servers support renaming across files, etc.
|
||||
map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
|
||||
|
||||
-- Show documentation for the symbol under your cursor.
|
||||
map('K', vim.lsp.buf.hover, 'Hover Documentation')
|
||||
|
||||
-- Execute a code action, usually your cursor needs to be on top of an error
|
||||
-- or a suggestion from your LSP for this to activate.
|
||||
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
|
||||
|
||||
-- WARN: This is not Goto Definition, this is Goto Declaration.
|
||||
-- For example, in C this would take you to the header.
|
||||
map('grD', function()
|
||||
if client and client:supports_method('textDocument/declaration', event.buf) then
|
||||
vim.lsp.buf.declaration()
|
||||
else
|
||||
vim.lsp.buf.definition()
|
||||
end
|
||||
end, '[G]oto [D]eclaration')
|
||||
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
|
||||
|
||||
-- The following two autocommands are used to highlight references of the
|
||||
-- word under your cursor when your cursor rests there for a little while.
|
||||
-- See `:help CursorHold` for information about when this is executed
|
||||
--
|
||||
-- When you move your cursor, the highlights will be cleared (the second autocommand).
|
||||
local client = vim.lsp.get_client_by_id(event.data.client_id)
|
||||
if client and client:supports_method('textDocument/documentHighlight', event.buf) then
|
||||
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false })
|
||||
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
|
||||
|
|
@ -882,25 +853,12 @@ require('lazy').setup({
|
|||
|
||||
{ -- Highlight, edit, and navigate code
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
build = ':TSUpdate',
|
||||
config = function()
|
||||
local filetypes = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }
|
||||
require('nvim-treesitter').install(filetypes)
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = {
|
||||
'bash',
|
||||
'c',
|
||||
'cs',
|
||||
'diff',
|
||||
'html',
|
||||
'lua',
|
||||
'markdown',
|
||||
'query',
|
||||
'vim',
|
||||
'help',
|
||||
},
|
||||
callback = function(args)
|
||||
local lang = vim.treesitter.language.get_lang(args.match) or args.match
|
||||
pcall(vim.treesitter.start, args.buf, lang)
|
||||
end,
|
||||
pattern = filetypes,
|
||||
callback = function() vim.treesitter.start() end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
|
@ -925,7 +883,7 @@ require('lazy').setup({
|
|||
-- This is the easiest way to modularize your config.
|
||||
--
|
||||
-- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going.
|
||||
{ import = 'custom.plugins' },
|
||||
-- { import = 'custom.plugins' },
|
||||
--
|
||||
-- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec`
|
||||
-- Or use telescope!
|
||||
|
|
|
|||
|
|
@ -1,486 +0,0 @@
|
|||
-- =============================================================================
|
||||
-- .NET / C# Development Setup
|
||||
-- =============================================================================
|
||||
-- This file wires up everything needed for a productive .NET experience in
|
||||
-- Neovim: Roslyn LSP, GitHub Copilot (via blink.cmp), DAP debugging with
|
||||
-- netcoredbg, and Neotest for running xUnit/NUnit/MSTest tests.
|
||||
--
|
||||
-- PREREQUISITES (install once on your system):
|
||||
-- - .NET SDK: https://dotnet.microsoft.com/download
|
||||
-- - Node.js > 20 (for Copilot): https://nodejs.org
|
||||
-- - On first launch run: :Copilot auth (one-time GitHub login)
|
||||
-- - Mason will auto-install: netcoredbg, csharpier
|
||||
-- - roslyn.nvim downloads its own language server on first use
|
||||
--
|
||||
-- QUICK REFERENCE — KEY BINDINGS
|
||||
-- (language-agnostic binds work everywhere; .NET-specific are noted)
|
||||
-- =============================================================================
|
||||
--
|
||||
-- ── LSP NAVIGATION ────────────────────────────────────────────────────────────
|
||||
-- grd Go to Definition (jump to where a symbol is defined)
|
||||
-- grD Go to Declaration (e.g. interface declaration)
|
||||
-- gri Go to Implementation (jump to concrete implementation)
|
||||
-- grr Find All References (list all usages in Telescope)
|
||||
-- grt Go to Type Definition (jump to the type of a variable)
|
||||
-- gO Document Symbols (fuzzy search symbols in this file)
|
||||
-- gW Workspace Symbols (fuzzy search symbols in whole project)
|
||||
-- K Hover Documentation (show docs / type info under cursor)
|
||||
-- grn Rename Symbol (rename across the whole project)
|
||||
-- gra Code Actions (fix suggestions, extract method, etc.)
|
||||
-- <leader>f Format Buffer (run csharpier on the current file)
|
||||
-- <leader>th Toggle Inlay Hints (show/hide parameter name hints)
|
||||
-- [d / ]d Previous / Next Diagnostic
|
||||
-- <leader>q Diagnostic Quickfix List
|
||||
-- <leader>sd Search Diagnostics (Telescope)
|
||||
--
|
||||
-- ── COMPLETION (blink.cmp) ────────────────────────────────────────────────────
|
||||
-- <C-Space> Open completion menu (or open docs if menu is open)
|
||||
-- <C-n> / <C-p> Next / Previous item (also <Up> / <Down>)
|
||||
-- <C-y> Accept completion (auto-imports if LSP supports it)
|
||||
-- <C-e> Dismiss menu
|
||||
-- <C-k> Toggle signature help (see function parameter hints)
|
||||
-- <Tab>/<S-Tab> Move through snippet expansions
|
||||
--
|
||||
-- ── GITHUB COPILOT ────────────────────────────────────────────────────────────
|
||||
-- Copilot suggestions appear in the blink.cmp completion menu automatically.
|
||||
-- They are ranked alongside LSP completions — just navigate with <C-n>/<C-p>.
|
||||
-- :Copilot auth Re-authenticate with GitHub (run once on first setup)
|
||||
-- :Copilot status Check if Copilot is active
|
||||
--
|
||||
-- ── DEBUGGING (nvim-dap + netcoredbg) ─────────────────────────────────────────
|
||||
-- <leader>dc Continue / Start debug session
|
||||
-- <leader>db Toggle Breakpoint (set/unset on current line)
|
||||
-- <leader>dB Conditional Breakpoint (prompt for a condition expression)
|
||||
-- <leader>ds Step Over (F10 equivalent)
|
||||
-- <leader>di Step Into (F11 equivalent)
|
||||
-- <leader>do Step Out (Shift-F11 equivalent)
|
||||
-- <leader>dr Open REPL (interactive debug console)
|
||||
-- <leader>dl Re-run Last Session (repeat last debug config)
|
||||
-- <leader>du Toggle Debug UI (show/hide the dap-ui panels)
|
||||
-- <leader>de Evaluate Expression (hover eval under cursor)
|
||||
-- <leader>dE Evaluate (input prompt) (type an expression to evaluate)
|
||||
--
|
||||
-- The debug UI opens automatically when a session starts and shows:
|
||||
-- Left panel: Scopes · Breakpoints · Call Stack · Watches
|
||||
-- Bottom panel: REPL · Console output
|
||||
--
|
||||
-- ── TESTING (neotest + neotest-dotnet) ────────────────────────────────────────
|
||||
-- <leader>nn Run Nearest Test (test method under cursor)
|
||||
-- <leader>nf Run File Tests (all tests in current file)
|
||||
-- <leader>na Run All Tests (entire project/solution)
|
||||
-- <leader>ns Toggle Test Summary (tree view of all tests + status)
|
||||
-- <leader>no Show Test Output (output of last test run)
|
||||
-- <leader>np Show Short Output (condensed output panel)
|
||||
-- <leader>nd Debug Nearest Test (run test under cursor with DAP)
|
||||
-- <leader>nw Watch Nearest Test (re-run on file save)
|
||||
-- <leader>nx Stop Running Tests
|
||||
--
|
||||
-- =============================================================================
|
||||
|
||||
return {
|
||||
|
||||
-- ===========================================================================
|
||||
-- 1. ROSLYN LSP (seblj/roslyn.nvim)
|
||||
-- ===========================================================================
|
||||
-- The same Roslyn language server that powers Visual Studio and Rider.
|
||||
-- Downloads Microsoft.CodeAnalysis.LanguageServer automatically on first use.
|
||||
-- Provides: IntelliSense, go-to-definition, find-references, rename,
|
||||
-- code actions (extract method, add using, etc.), inlay hints,
|
||||
-- and full project/solution awareness.
|
||||
{
|
||||
'seblj/roslyn.nvim',
|
||||
ft = { 'cs', 'vb' },
|
||||
dependencies = {
|
||||
'mason-org/mason.nvim', -- ensures mason is loaded first
|
||||
},
|
||||
opts = {
|
||||
-- roslyn.nvim finds and downloads the language server into stdpath('data').
|
||||
-- Set exe to override with a custom path if you manage the server yourself.
|
||||
config = {
|
||||
-- Pass extra capabilities from blink.cmp so the LSP knows we support
|
||||
-- snippet completions, resolve, etc.
|
||||
capabilities = vim.tbl_deep_extend(
|
||||
'force',
|
||||
vim.lsp.protocol.make_client_capabilities(),
|
||||
-- blink.cmp may not be loaded yet at spec parse time; we wrap in a
|
||||
-- function via on_attach / capabilities below instead.
|
||||
{}
|
||||
),
|
||||
},
|
||||
-- In larger repos / monoliths this helps Roslyn search a bit wider for
|
||||
-- the correct solution or project root.
|
||||
broad_search = true,
|
||||
-- Allow target switching when multiple solutions exist in the repo.
|
||||
lock_target = false,
|
||||
},
|
||||
config = function(_, opts)
|
||||
-- Inject blink.cmp capabilities now that blink is guaranteed loaded.
|
||||
local ok, blink = pcall(require, 'blink.cmp')
|
||||
if ok then
|
||||
opts.config = opts.config or {}
|
||||
opts.config.capabilities = blink.get_lsp_capabilities(opts.config.capabilities)
|
||||
end
|
||||
|
||||
require('roslyn').setup(opts)
|
||||
end,
|
||||
},
|
||||
|
||||
-- ===========================================================================
|
||||
-- 2. GITHUB COPILOT (zbirenbaum/copilot.lua + blink-cmp-copilot)
|
||||
-- ===========================================================================
|
||||
-- copilot.lua runs the Copilot LSP in the background.
|
||||
-- We disable the built-in ghost-text / panel UI and instead surface
|
||||
-- completions through blink.cmp so everything comes from one menu.
|
||||
{
|
||||
'zbirenbaum/copilot.lua',
|
||||
event = 'InsertEnter',
|
||||
opts = {
|
||||
-- Disable copilot.lua's own UI — blink.cmp owns the completion menu.
|
||||
suggestion = { enabled = false },
|
||||
panel = { enabled = false },
|
||||
-- Explicitly enable C# (and a few other useful filetypes).
|
||||
filetypes = {
|
||||
cs = true,
|
||||
lua = true,
|
||||
python = true,
|
||||
javascript = true,
|
||||
typescript = true,
|
||||
-- Disable noisy filetypes.
|
||||
markdown = false,
|
||||
help = false,
|
||||
gitcommit = false,
|
||||
},
|
||||
-- Node.js must be > 20.
|
||||
copilot_node_command = 'node',
|
||||
},
|
||||
},
|
||||
|
||||
-- blink-cmp-copilot bridges copilot.lua into blink.cmp as a source provider.
|
||||
-- Copilot completions appear in the menu with a icon and "Copilot" label.
|
||||
{
|
||||
'giuxtaposition/blink-cmp-copilot',
|
||||
dependencies = { 'zbirenbaum/copilot.lua' },
|
||||
-- blink.cmp is already configured in init.lua; we patch its sources table
|
||||
-- here so we don't have to touch the existing config.
|
||||
specs = {
|
||||
{
|
||||
'saghen/blink.cmp',
|
||||
optional = true,
|
||||
opts = {
|
||||
sources = {
|
||||
default = { 'lsp', 'path', 'snippets', 'copilot' },
|
||||
providers = {
|
||||
copilot = {
|
||||
name = 'copilot',
|
||||
module = 'blink-cmp-copilot',
|
||||
-- Show Copilot items after LSP items in the menu.
|
||||
score_offset = -1,
|
||||
async = true,
|
||||
-- Give it a recognisable icon in the completion menu.
|
||||
transform_items = function(_, items)
|
||||
for _, item in ipairs(items) do
|
||||
item.kind_icon = ''
|
||||
item.kind_name = 'Copilot'
|
||||
end
|
||||
return items
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- ===========================================================================
|
||||
-- 3. DEBUGGING (nvim-dap + nvim-dap-ui + mason-nvim-dap)
|
||||
-- ===========================================================================
|
||||
-- netcoredbg is the open-source .NET debugger that understands the DAP
|
||||
-- protocol. mason-nvim-dap installs it automatically.
|
||||
{
|
||||
'mfussenegger/nvim-dap',
|
||||
dependencies = {
|
||||
-- Automatic installer / bridge between mason and dap adapters.
|
||||
{
|
||||
'jay-babu/mason-nvim-dap.nvim',
|
||||
dependencies = { 'mason-org/mason.nvim' },
|
||||
opts = {
|
||||
-- Let mason-nvim-dap install and configure netcoredbg.
|
||||
ensure_installed = { 'netcoredbg' },
|
||||
automatic_installation = true,
|
||||
handlers = {}, -- use default handlers for installed adapters
|
||||
},
|
||||
},
|
||||
|
||||
-- A full debug UI: scopes, locals, call stack, breakpoints, REPL.
|
||||
{
|
||||
'rcarriga/nvim-dap-ui',
|
||||
dependencies = { 'nvim-neotest/nvim-nio' },
|
||||
config = function()
|
||||
local dap = require 'dap'
|
||||
local dapui = require 'dapui'
|
||||
|
||||
dapui.setup {
|
||||
-- Layout: left sidebar + bottom panel — mirrors a typical IDE layout.
|
||||
layouts = {
|
||||
{
|
||||
-- Left sidebar: variables, call stack, breakpoints, watches.
|
||||
position = 'left',
|
||||
size = 40,
|
||||
elements = {
|
||||
{ id = 'scopes', size = 0.35 },
|
||||
{ id = 'stacks', size = 0.35 },
|
||||
{ id = 'breakpoints', size = 0.15 },
|
||||
{ id = 'watches', size = 0.15 },
|
||||
},
|
||||
},
|
||||
{
|
||||
-- Bottom tray: REPL for live evaluation + program console output.
|
||||
position = 'bottom',
|
||||
size = 12,
|
||||
elements = {
|
||||
{ id = 'repl', size = 0.5 },
|
||||
{ id = 'console', size = 0.5 },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Auto-open the UI when a debug session starts.
|
||||
dap.listeners.after.event_initialized['dapui_config'] = function()
|
||||
dapui.open()
|
||||
end
|
||||
-- Auto-close the UI when the session ends or terminates.
|
||||
dap.listeners.before.event_terminated['dapui_config'] = function()
|
||||
dapui.close()
|
||||
end
|
||||
dap.listeners.before.event_exited['dapui_config'] = function()
|
||||
dapui.close()
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
-- Virtual text shows variable values inline while stepping through code.
|
||||
{
|
||||
'theHamsta/nvim-dap-virtual-text',
|
||||
opts = {
|
||||
-- Show the value of the variable at the current scope inline.
|
||||
display_callback = function(variable, _, _, _, options)
|
||||
if #variable.value > 60 then
|
||||
return ' ' .. string.sub(variable.value, 1, 57) .. '...'
|
||||
end
|
||||
return ' ' .. variable.value
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
config = function()
|
||||
local dap = require 'dap'
|
||||
|
||||
-- ── Adapter ─────────────────────────────────────────────────────────────
|
||||
-- mason-nvim-dap installs netcoredbg into mason's bin directory.
|
||||
-- We resolve the path at runtime so it works on any machine.
|
||||
local mason_bin = vim.fn.stdpath 'data' .. '/mason/bin'
|
||||
local netcoredbg_cmd = mason_bin .. '/netcoredbg'
|
||||
-- On Windows mason wraps executables in .cmd files.
|
||||
if vim.fn.has 'win32' == 1 then
|
||||
netcoredbg_cmd = mason_bin .. '/netcoredbg.cmd'
|
||||
end
|
||||
|
||||
dap.adapters.coreclr = {
|
||||
type = 'executable',
|
||||
command = netcoredbg_cmd,
|
||||
args = { '--interpreter=vscode' },
|
||||
}
|
||||
|
||||
-- ── Helper: prompt for / remember DLL path ───────────────────────────
|
||||
-- On first launch you'll be asked for the path to the compiled DLL.
|
||||
-- The answer is cached for the rest of the session; you're only re-asked
|
||||
-- if you confirm you want to change it.
|
||||
local function get_dll_path()
|
||||
if vim.g.dotnet_last_dll_path == nil then
|
||||
vim.g.dotnet_last_dll_path = vim.fn.input(
|
||||
'Path to DLL: ',
|
||||
vim.fn.getcwd() .. '/bin/Debug/',
|
||||
'file'
|
||||
)
|
||||
else
|
||||
local change = vim.fn.confirm(
|
||||
'Reuse last DLL?\n' .. vim.g.dotnet_last_dll_path,
|
||||
'&Yes\n&No',
|
||||
1
|
||||
)
|
||||
if change == 2 then
|
||||
vim.g.dotnet_last_dll_path = vim.fn.input(
|
||||
'Path to DLL: ',
|
||||
vim.g.dotnet_last_dll_path,
|
||||
'file'
|
||||
)
|
||||
end
|
||||
end
|
||||
return vim.g.dotnet_last_dll_path
|
||||
end
|
||||
|
||||
-- ── Helper: optional pre-build ───────────────────────────────────────
|
||||
local function maybe_build()
|
||||
local build = vim.fn.confirm('Build project first?', '&Yes\n&No', 2)
|
||||
if build == 1 then
|
||||
local proj = vim.fn.input(
|
||||
'Path to .csproj/.sln: ',
|
||||
vim.g.dotnet_last_proj_path or (vim.fn.getcwd() .. '/'),
|
||||
'file'
|
||||
)
|
||||
vim.g.dotnet_last_proj_path = proj
|
||||
vim.notify('Building ' .. proj .. ' …', vim.log.levels.INFO)
|
||||
local result = os.execute('dotnet build -c Debug "' .. proj .. '" > /dev/null 2>&1')
|
||||
if result == 0 then
|
||||
vim.notify('Build succeeded', vim.log.levels.INFO)
|
||||
else
|
||||
vim.notify('Build FAILED — check :messages', vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ── Launch configurations ────────────────────────────────────────────
|
||||
-- Shared across cs and fsharp.
|
||||
local dotnet_launch = {
|
||||
{
|
||||
type = 'coreclr',
|
||||
name = 'Launch .NET (netcoredbg)',
|
||||
request = 'launch',
|
||||
program = function()
|
||||
maybe_build()
|
||||
return get_dll_path()
|
||||
end,
|
||||
},
|
||||
{
|
||||
-- Attach to a running process (e.g. an already-running web server).
|
||||
type = 'coreclr',
|
||||
name = 'Attach to process',
|
||||
request = 'attach',
|
||||
processId = require('dap.utils').pick_process,
|
||||
},
|
||||
}
|
||||
|
||||
dap.configurations.cs = dotnet_launch
|
||||
dap.configurations.fsharp = dotnet_launch
|
||||
|
||||
-- ── Keybinds ─────────────────────────────────────────────────────────
|
||||
-- See the header comment at the top of this file for full descriptions.
|
||||
local map = function(keys, func, desc)
|
||||
vim.keymap.set('n', keys, func, { desc = 'Debug: ' .. desc })
|
||||
end
|
||||
|
||||
map('<leader>dc', dap.continue, '[C]ontinue / Start')
|
||||
map('<leader>db', dap.toggle_breakpoint, 'Toggle [B]reakpoint')
|
||||
map('<leader>dB', function()
|
||||
dap.set_breakpoint(vim.fn.input 'Breakpoint condition: ')
|
||||
end, 'Conditional [B]reakpoint')
|
||||
map('<leader>ds', dap.step_over, '[S]tep Over')
|
||||
map('<leader>di', dap.step_into, 'Step [I]nto')
|
||||
map('<leader>do', dap.step_out, 'Step [O]ut')
|
||||
map('<leader>dr', dap.repl.open, 'Open [R]EPL')
|
||||
map('<leader>dl', dap.run_last, 'Run [L]ast')
|
||||
map('<leader>du', function() require('dapui').toggle() end, 'Toggle [U]I')
|
||||
map('<leader>de', function() require('dapui').eval() end, '[E]val under cursor')
|
||||
map('<leader>dE', function()
|
||||
require('dapui').eval(vim.fn.input 'Expression: ')
|
||||
end, '[E]val expression')
|
||||
|
||||
-- Register the <leader>d group name with which-key (if loaded).
|
||||
local ok, wk = pcall(require, 'which-key')
|
||||
if ok then
|
||||
wk.add { { '<leader>d', group = '[D]ebug' } }
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
-- ===========================================================================
|
||||
-- 4. TESTING (nvim-neotest + neotest-dotnet)
|
||||
-- ===========================================================================
|
||||
-- neotest-dotnet discovers xUnit, NUnit, and MSTest tests automatically by
|
||||
-- scanning for [Fact], [Theory], [Test], [TestCase], etc. attributes.
|
||||
{
|
||||
'nvim-neotest/neotest',
|
||||
dependencies = {
|
||||
'nvim-lua/plenary.nvim',
|
||||
'antoinemadec/FixCursorHold.nvim', -- required by neotest
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
-- .NET adapter — supports xUnit, NUnit, MSTest.
|
||||
'Issafalcon/neotest-dotnet',
|
||||
},
|
||||
config = function()
|
||||
require('neotest').setup {
|
||||
adapters = {
|
||||
require('neotest-dotnet') {
|
||||
-- dap integration: <leader>nd will attach the debugger to the test.
|
||||
dap = { justMyCode = false },
|
||||
-- Discover tests using the dotnet CLI runner.
|
||||
-- Set to 'omnisharp' if you prefer the OmniSharp test runner.
|
||||
dotnet_additional_args = {},
|
||||
},
|
||||
},
|
||||
-- Show pass/fail icons in the gutter next to each test.
|
||||
status = { enabled = true, signs = true, virtual_text = false },
|
||||
-- Open the output panel automatically for short failures.
|
||||
output = { enabled = true, open_on_run = 'short' },
|
||||
-- Use a bottom split for the output panel.
|
||||
output_panel = {
|
||||
enabled = true,
|
||||
open = 'botright split | resize 15',
|
||||
},
|
||||
}
|
||||
|
||||
-- ── Keybinds ─────────────────────────────────────────────────────────
|
||||
-- See the header comment at the top of this file for full descriptions.
|
||||
local nt = require 'neotest'
|
||||
local map = function(keys, func, desc)
|
||||
vim.keymap.set('n', keys, func, { desc = 'Test: ' .. desc })
|
||||
end
|
||||
|
||||
map('<leader>nn', function() nt.run.run() end, 'Run [N]earest test')
|
||||
map('<leader>nf', function() nt.run.run(vim.fn.expand '%') end, 'Run [F]ile tests')
|
||||
map('<leader>na', function() nt.run.run(vim.fn.getcwd()) end, 'Run [A]ll tests')
|
||||
map('<leader>ns', function() nt.summary.toggle() end, 'Toggle [S]ummary panel')
|
||||
map('<leader>no', function() nt.output.open { enter = true } end, 'Show [O]utput')
|
||||
map('<leader>np', function() nt.output_panel.toggle() end, 'Toggle output [P]anel')
|
||||
map('<leader>nd', function() nt.run.run { strategy = 'dap' } end, '[D]ebug nearest test')
|
||||
map('<leader>nw', function() nt.watch.toggle(vim.fn.expand '%') end, '[W]atch file tests')
|
||||
map('<leader>nx', function() nt.run.stop() end, 'Stop running tests')
|
||||
|
||||
-- Register the <leader>n group name with which-key (if loaded).
|
||||
local ok, wk = pcall(require, 'which-key')
|
||||
if ok then
|
||||
wk.add { { '<leader>n', group = '[N]eotest' } }
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
-- ===========================================================================
|
||||
-- 5. CSHARPIER (formatter, installed via Mason)
|
||||
-- ===========================================================================
|
||||
-- csharpier is the opinionated C# formatter (like gofmt/prettier for C#).
|
||||
-- It is installed by mason-tool-installer below and wired into conform.nvim.
|
||||
{
|
||||
-- Re-use mason-tool-installer (already set up in init.lua) to ensure
|
||||
-- csharpier is installed. We declare it as a separate spec here so this
|
||||
-- file is self-contained; lazy.nvim merges duplicate plugin specs.
|
||||
'WhoIsSethDaniel/mason-tool-installer.nvim',
|
||||
optional = true,
|
||||
opts = function(_, opts)
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, { 'csharpier', 'roslyn' })
|
||||
end,
|
||||
},
|
||||
{
|
||||
-- Patch conform.nvim to format C# files with csharpier.
|
||||
-- This merges cleanly with the existing conform setup in init.lua.
|
||||
'stevearc/conform.nvim',
|
||||
optional = true,
|
||||
opts = function(_, opts)
|
||||
opts.formatters_by_ft = opts.formatters_by_ft or {}
|
||||
opts.formatters_by_ft.cs = { 'csharpier' }
|
||||
end,
|
||||
},
|
||||
}
|
||||
Loading…
Reference in New Issue