tests and terminal
This commit is contained in:
@@ -5,6 +5,10 @@ keymap.set("n", "<leader>h", "<C-w>h", { noremap = true, silent = true, desc = "
|
|||||||
keymap.set("n", "<leader>j", "<C-w>j", { noremap = true, silent = true, desc = "Window down" })
|
keymap.set("n", "<leader>j", "<C-w>j", { noremap = true, silent = true, desc = "Window down" })
|
||||||
keymap.set("n", "<leader>k", "<C-w>k", { noremap = true, silent = true, desc = "Window up" })
|
keymap.set("n", "<leader>k", "<C-w>k", { noremap = true, silent = true, desc = "Window up" })
|
||||||
keymap.set("n", "<leader>l", "<C-w>l", { noremap = true, silent = true, desc = "Window right" })
|
keymap.set("n", "<leader>l", "<C-w>l", { noremap = true, silent = true, desc = "Window right" })
|
||||||
|
keymap.set("t", "<leader>h", [[<C-\><C-n><C-w>h]], { noremap = true, silent = true, desc = "Window left" })
|
||||||
|
keymap.set("t", "<leader>j", [[<C-\><C-n><C-w>j]], { noremap = true, silent = true, desc = "Window down" })
|
||||||
|
keymap.set("t", "<leader>k", [[<C-\><C-n><C-w>k]], { noremap = true, silent = true, desc = "Window up" })
|
||||||
|
keymap.set("t", "<leader>l", [[<C-\><C-n><C-w>l]], { noremap = true, silent = true, desc = "Window right" })
|
||||||
|
|
||||||
local reload = require("utils.reload")
|
local reload = require("utils.reload")
|
||||||
|
|
||||||
@@ -38,6 +42,113 @@ keymap.set("n", "<leader>xr", "<cmd>Trouble lsp_references toggle<CR>", { norema
|
|||||||
keymap.set("n", "<leader>xs", "<cmd>Trouble symbols toggle focus=false<CR>", { noremap = true, silent = true, desc = "Problems document symbols" })
|
keymap.set("n", "<leader>xs", "<cmd>Trouble symbols toggle focus=false<CR>", { noremap = true, silent = true, desc = "Problems document symbols" })
|
||||||
keymap.set("n", "<leader>xS", "<cmd>Trouble lsp toggle focus=false win.position=right<CR>", { noremap = true, silent = true, desc = "Problems workspace symbols" })
|
keymap.set("n", "<leader>xS", "<cmd>Trouble lsp toggle focus=false win.position=right<CR>", { noremap = true, silent = true, desc = "Problems workspace symbols" })
|
||||||
|
|
||||||
|
local function with_toggleterm(fn)
|
||||||
|
local ok, toggleterm = pcall(require, "plugins.config.toggleterm")
|
||||||
|
if not ok then
|
||||||
|
pcall(function()
|
||||||
|
require("lazy").load({ plugins = { "toggleterm.nvim" } })
|
||||||
|
end)
|
||||||
|
ok, toggleterm = pcall(require, "plugins.config.toggleterm")
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
vim.notify("toggleterm is not available", vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
fn(toggleterm)
|
||||||
|
end
|
||||||
|
|
||||||
|
keymap.set("n", "<leader>mm", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.toggle_shell()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Build terminal" })
|
||||||
|
keymap.set("t", "<leader>mm", [[<C-\><C-n><cmd>lua require("plugins.config.toggleterm").toggle_shell()<CR>]], { noremap = true, silent = true, desc = "Build terminal" })
|
||||||
|
keymap.set("n", "<leader>mc", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.rerun_last()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Build rerun last" })
|
||||||
|
keymap.set("n", "<leader>m1", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.toggle_build_terminal()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Build toggle terminal" })
|
||||||
|
keymap.set("t", "<leader>m1", [[<C-\><C-n><cmd>lua require("plugins.config.toggleterm").toggle_build_terminal()<CR>]], { noremap = true, silent = true, desc = "Build toggle terminal" })
|
||||||
|
keymap.set("n", "<leader>m2", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.toggle_test_terminal()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Build test terminal" })
|
||||||
|
keymap.set("t", "<leader>m2", [[<C-\><C-n><cmd>lua require("plugins.config.toggleterm").toggle_test_terminal()<CR>]], { noremap = true, silent = true, desc = "Build test terminal" })
|
||||||
|
|
||||||
|
local function with_neotest(fn)
|
||||||
|
local ok, neotest = pcall(require, "neotest")
|
||||||
|
if not ok then
|
||||||
|
vim.notify("neotest is not available", vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
fn(neotest)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function project_root_for_tests()
|
||||||
|
local current_file = vim.api.nvim_buf_get_name(0)
|
||||||
|
local start_path = current_file ~= "" and vim.fs.dirname(current_file) or vim.loop.cwd()
|
||||||
|
local markers = { "CMakePresets.json", "CMakeLists.txt", ".git" }
|
||||||
|
local found = vim.fs.find(markers, { upward = true, path = start_path })[1]
|
||||||
|
|
||||||
|
if found then
|
||||||
|
return vim.fs.dirname(found)
|
||||||
|
end
|
||||||
|
|
||||||
|
return vim.loop.cwd()
|
||||||
|
end
|
||||||
|
|
||||||
|
keymap.set("n", "<leader>tt", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.run.run()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests run nearest" })
|
||||||
|
keymap.set("n", "<leader>tf", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.run.run(vim.fn.expand("%"))
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests run file" })
|
||||||
|
keymap.set("n", "<leader>ta", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.run.run(project_root_for_tests())
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests run all" })
|
||||||
|
keymap.set("n", "<leader>tg", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.run_tests()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests run via ctest" })
|
||||||
|
keymap.set("n", "<leader>td", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.run.run({ strategy = "dap" })
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests debug nearest" })
|
||||||
|
keymap.set("n", "<leader>to", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.output.open({ enter = true, auto_close = true })
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests open output" })
|
||||||
|
keymap.set("n", "<leader>tp", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.output_panel.toggle()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests toggle output panel" })
|
||||||
|
keymap.set("n", "<leader>ts", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.summary.toggle()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests toggle summary" })
|
||||||
|
keymap.set("n", "<leader>tS", function()
|
||||||
|
with_neotest(function(neotest)
|
||||||
|
neotest.run.stop()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "Tests stop" })
|
||||||
|
|
||||||
vim.keymap.set("n", "gn", vim.diagnostic.goto_next, { noremap = true, silent = true })
|
vim.keymap.set("n", "gn", vim.diagnostic.goto_next, { noremap = true, silent = true })
|
||||||
|
|
||||||
local function with_dap(fn)
|
local function with_dap(fn)
|
||||||
@@ -163,7 +274,11 @@ keymap.set("n", "<leader>dR", "<cmd>Telescope dap configurations<CR>", { noremap
|
|||||||
keymap.set("n", "<leader>dK", "<cmd>Telescope dap list_breakpoints<CR>", { noremap = true, silent = true, desc = "Debug breakpoints" })
|
keymap.set("n", "<leader>dK", "<cmd>Telescope dap list_breakpoints<CR>", { noremap = true, silent = true, desc = "Debug breakpoints" })
|
||||||
|
|
||||||
keymap.set("n", "<leader>cg", "<cmd>CMakeGenerate<CR>", { noremap = true, silent = true, desc = "CMake generate" })
|
keymap.set("n", "<leader>cg", "<cmd>CMakeGenerate<CR>", { noremap = true, silent = true, desc = "CMake generate" })
|
||||||
keymap.set("n", "<leader>cb", "<cmd>CMakeBuild<CR>", { noremap = true, silent = true, desc = "CMake build" })
|
keymap.set("n", "<leader>cb", function()
|
||||||
|
with_toggleterm(function(toggleterm)
|
||||||
|
toggleterm.run_build()
|
||||||
|
end)
|
||||||
|
end, { noremap = true, silent = true, desc = "CMake build (terminal)" })
|
||||||
keymap.set("n", "<leader>cB", "<cmd>CMakeBuild!<CR>", { noremap = true, silent = true, desc = "CMake clean build" })
|
keymap.set("n", "<leader>cB", "<cmd>CMakeBuild!<CR>", { noremap = true, silent = true, desc = "CMake clean build" })
|
||||||
keymap.set("n", "<leader>cc", "<cmd>CMakeClean<CR>", { noremap = true, silent = true, desc = "CMake clean" })
|
keymap.set("n", "<leader>cc", "<cmd>CMakeClean<CR>", { noremap = true, silent = true, desc = "CMake clean" })
|
||||||
keymap.set("n", "<leader>ct", "<cmd>CMakeSelectBuildTarget<CR>", { noremap = true, silent = true, desc = "CMake select build target" })
|
keymap.set("n", "<leader>ct", "<cmd>CMakeSelectBuildTarget<CR>", { noremap = true, silent = true, desc = "CMake select build target" })
|
||||||
|
|||||||
65
lua/plugins/config/neotest.lua
Normal file
65
lua/plugins/config/neotest.lua
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
local lib = require("neotest.lib")
|
||||||
|
|
||||||
|
local has_cpp_parser = false
|
||||||
|
local ok_parsers, parsers = pcall(require, "nvim-treesitter.parsers")
|
||||||
|
if ok_parsers and parsers.has_parser then
|
||||||
|
has_cpp_parser = parsers.has_parser("cpp")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not has_cpp_parser then
|
||||||
|
vim.schedule(function()
|
||||||
|
vim.notify(
|
||||||
|
"neotest-gtest needs Treesitter cpp parser. Run :TSInstall cpp",
|
||||||
|
vim.log.levels.WARN
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
require("neotest").setup({
|
||||||
|
adapters = {
|
||||||
|
require("neotest-gtest").setup({
|
||||||
|
root = lib.files.match_root_pattern(
|
||||||
|
"CMakeLists.txt",
|
||||||
|
".git"
|
||||||
|
),
|
||||||
|
debug_adapter = "codelldb",
|
||||||
|
is_test_file = function(file)
|
||||||
|
local normalized = file:gsub("\\", "/")
|
||||||
|
local is_in_tests_dir = normalized:match("/tests/") ~= nil
|
||||||
|
local has_test_suffix = normalized:match("_test%.cpp$")
|
||||||
|
or normalized:match("_test%.cc$")
|
||||||
|
or normalized:match("_test%.cxx$")
|
||||||
|
or normalized:match("_test%.c%+%+$")
|
||||||
|
|
||||||
|
return is_in_tests_dir and has_test_suffix ~= nil
|
||||||
|
end,
|
||||||
|
filter_dir = function(name, rel_path)
|
||||||
|
if rel_path == "" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local blocked = {
|
||||||
|
[".git"] = true,
|
||||||
|
[".cache"] = true,
|
||||||
|
["build"] = true,
|
||||||
|
["out"] = true,
|
||||||
|
["_deps"] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if blocked[name] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if rel_path:match("^build/") or rel_path:match("^out/") then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
mappings = {
|
||||||
|
configure = "C",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
117
lua/plugins/config/toggleterm.lua
Normal file
117
lua/plugins/config/toggleterm.lua
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
local toggleterm = require("toggleterm")
|
||||||
|
local Terminal = require("toggleterm.terminal").Terminal
|
||||||
|
|
||||||
|
toggleterm.setup({
|
||||||
|
start_in_insert = true,
|
||||||
|
insert_mappings = true,
|
||||||
|
terminal_mappings = true,
|
||||||
|
persist_size = true,
|
||||||
|
persist_mode = true,
|
||||||
|
close_on_exit = false,
|
||||||
|
direction = "horizontal",
|
||||||
|
size = 14,
|
||||||
|
})
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local runners = {
|
||||||
|
build = {
|
||||||
|
cmd = "cmake --build --preset debug-with-tidy",
|
||||||
|
title = "Build",
|
||||||
|
},
|
||||||
|
test = {
|
||||||
|
cmd = "ctest --test-dir build --output-on-failure",
|
||||||
|
title = "Tests",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local terminals = {
|
||||||
|
shell = Terminal:new({
|
||||||
|
hidden = true,
|
||||||
|
close_on_exit = false,
|
||||||
|
direction = "horizontal",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
local last_runner = nil
|
||||||
|
|
||||||
|
local function run_in_terminal(term, cmd)
|
||||||
|
term:open()
|
||||||
|
vim.defer_fn(function()
|
||||||
|
term:send(cmd .. "\r", false)
|
||||||
|
end, 20)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function project_root()
|
||||||
|
local current_file = vim.api.nvim_buf_get_name(0)
|
||||||
|
local start_path = current_file ~= "" and vim.fs.dirname(current_file) or vim.loop.cwd()
|
||||||
|
local markers = { "CMakePresets.json", "CMakeLists.txt", ".git" }
|
||||||
|
local found = vim.fs.find(markers, { upward = true, path = start_path })[1]
|
||||||
|
|
||||||
|
if found then
|
||||||
|
return vim.fs.dirname(found)
|
||||||
|
end
|
||||||
|
|
||||||
|
return vim.loop.cwd()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_runner_term(name)
|
||||||
|
if terminals[name] then
|
||||||
|
return terminals[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
terminals[name] = Terminal:new({
|
||||||
|
hidden = true,
|
||||||
|
close_on_exit = false,
|
||||||
|
direction = "horizontal",
|
||||||
|
display_name = runners[name].title,
|
||||||
|
})
|
||||||
|
|
||||||
|
return terminals[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.toggle_shell()
|
||||||
|
terminals.shell.dir = project_root()
|
||||||
|
terminals.shell:toggle()
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.run_build()
|
||||||
|
local term = get_runner_term("build")
|
||||||
|
term.dir = project_root()
|
||||||
|
run_in_terminal(term, runners.build.cmd)
|
||||||
|
last_runner = "build"
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.run_tests()
|
||||||
|
local term = get_runner_term("test")
|
||||||
|
term.dir = project_root()
|
||||||
|
run_in_terminal(term, runners.test.cmd)
|
||||||
|
last_runner = "test"
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.rerun_last()
|
||||||
|
if not last_runner then
|
||||||
|
vim.notify("No build/test command has been run yet", vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if last_runner == "build" then
|
||||||
|
M.run_build()
|
||||||
|
else
|
||||||
|
M.run_tests()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.toggle_build_terminal()
|
||||||
|
local term = get_runner_term("build")
|
||||||
|
term.dir = project_root()
|
||||||
|
term:toggle()
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.toggle_test_terminal()
|
||||||
|
local term = get_runner_term("test")
|
||||||
|
term.dir = project_root()
|
||||||
|
term:toggle()
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
require'nvim-treesitter.configs'.setup {
|
require'nvim-treesitter.configs'.setup {
|
||||||
-- A list of parser names, or "all" (the listed parsers MUST always be installed)
|
-- A list of parser names, or "all" (the listed parsers MUST always be installed)
|
||||||
ensure_installed = { "c", "lua", "vim", "vimdoc", "query", "markdown", "markdown_inline", "zig" },
|
ensure_installed = { "c", "cpp", "lua", "vim", "vimdoc", "query", "markdown", "markdown_inline", "zig" },
|
||||||
|
|
||||||
-- Install parsers synchronously (only applied to `ensure_installed`)
|
-- Install parsers synchronously (only applied to `ensure_installed`)
|
||||||
sync_install = false,
|
sync_install = false,
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ if wk.add then
|
|||||||
{ "<leader>c", group = "CMake" },
|
{ "<leader>c", group = "CMake" },
|
||||||
{ "<leader>d", group = "Debug" },
|
{ "<leader>d", group = "Debug" },
|
||||||
{ "<leader>f", group = "Find" },
|
{ "<leader>f", group = "Find" },
|
||||||
|
{ "<leader>m", group = "Build" },
|
||||||
{ "<leader>o", group = "OpenCode" },
|
{ "<leader>o", group = "OpenCode" },
|
||||||
|
{ "<leader>t", group = "Tests" },
|
||||||
{ "<leader>x", group = "Problems" },
|
{ "<leader>x", group = "Problems" },
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
@@ -30,7 +32,9 @@ else
|
|||||||
c = { name = "+CMake" },
|
c = { name = "+CMake" },
|
||||||
d = { name = "+Debug" },
|
d = { name = "+Debug" },
|
||||||
f = { name = "+Find" },
|
f = { name = "+Find" },
|
||||||
|
m = { name = "+Build" },
|
||||||
o = { name = "+OpenCode" },
|
o = { name = "+OpenCode" },
|
||||||
|
t = { name = "+Tests" },
|
||||||
x = { name = "+Problems" },
|
x = { name = "+Problems" },
|
||||||
}, { prefix = "<leader>" })
|
}, { prefix = "<leader>" })
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -85,6 +85,12 @@ return {
|
|||||||
require("plugins.config.trouble")
|
require("plugins.config.trouble")
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"akinsho/toggleterm.nvim",
|
||||||
|
config = function()
|
||||||
|
require("plugins.config.toggleterm")
|
||||||
|
end,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"folke/which-key.nvim",
|
"folke/which-key.nvim",
|
||||||
config = function()
|
config = function()
|
||||||
@@ -103,6 +109,17 @@ return {
|
|||||||
require("plugins.config.dap")
|
require("plugins.config.dap")
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"nvim-neotest/neotest",
|
||||||
|
dependencies = {
|
||||||
|
"nvim-neotest/nvim-nio",
|
||||||
|
"nvim-lua/plenary.nvim",
|
||||||
|
"alfaix/neotest-gtest",
|
||||||
|
},
|
||||||
|
config = function()
|
||||||
|
require("plugins.config.neotest")
|
||||||
|
end,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Civitasv/cmake-tools.nvim",
|
"Civitasv/cmake-tools.nvim",
|
||||||
config = function()
|
config = function()
|
||||||
|
|||||||
Reference in New Issue
Block a user