diff --git a/neovim/.config/nvim/init.lua b/neovim/.config/nvim/init.lua index 86ab53c8..7ab0d4f3 100644 --- a/neovim/.config/nvim/init.lua +++ b/neovim/.config/nvim/init.lua @@ -262,62 +262,124 @@ _G.dap_status = function() return "" end +local runners = { + python = function(file_path, root_dir, is_test) + local python_executable = "python3" + if vim.uv.fs_stat(vim.fs.joinpath(root_dir, ".pixi")) ~= nil then + python_executable = vim.fs.joinpath(root_dir, ".pixi", "envs", "default", "bin", "python") + end + if is_test then + if not file_path:match("^test_") and not file_path:match("_test%.py$") then + vim.notify( + string.format( + "Test file '%s' doesn't start/end with 'test_'/'_test' and will be ignored by pytest", + file_path + ), + vim.log.levels.WARN + ) + end + return { + python_executable, + "-m", + "pytest", + "--capture=no", + file_path, + } + end + return { + python_executable, + file_path, + } + end, + bash = function(file_path, _, _) + return { + "bash", + file_path, + } + end, + fish = function(file_path, _, _) + return { + "fish", + file_path, + } + end, + xml = function(_, _, _) + return { + "curl", + "-X", + "POST", + "http://127.0.0.1:7777/set_reload_request", + } + end, + lua = function(file_path, _, _) + vim.cmd.source(file_path) + end, + rust = function(file_path, root_dir, is_test) + if not vim.uv.fs_stat(vim.fs.joinpath(root_dir, "Cargo.toml")) then + vim.notify(root_dir .. " is not a Cargo project", vim.log.levels.WARN) + end + local cmd_output = vim + .system({ "cargo", "metadata", "--format-version=1" }, { cwd = root_dir, text = true }) + :wait() + if cmd_output.code ~= 0 then + vim.notify("Failed with code " .. cmd_output.code, vim.log.levels.WARN) + return + end + + local metadata = vim.json.decode(cmd_output.stdout) + + for _, package in ipairs(metadata.packages) do + for _, target in ipairs(package.targets) do + if target.kind[1] == "lib" and is_test then + return { "cargo", "test", "--lib" } + end + if file_path == target.src_path then + if target.kind[1] == "bin" then + return { "cargo", "run", "--bin", target.name } + elseif target.kind[1] == "example" then + return { "cargo", "run", "--example", target.name } + else + vim.notify("Unsupported target kind " .. vim.inspect(target.kind), vim.log.levels.WARN) + return + end + end + end + end + vim.notify("Can't find a target for " .. file_path, vim.log.levels.WARN) + end, +} +runners.sh = runners.bash + local run_file = function(is_test) local filetype = vim.api.nvim_get_option_value("filetype", {}) if not filetype or filetype == "" then return end + local runner = runners[filetype] + if not runner then + vim.notify("No runner found for filetype: '" .. filetype .. "'", vim.log.levels.WARN) + return + end + local dirname = vim.fn.expand("%:p:h") local root_dir = root_dirs[filetype] - if root_dir then - root_dir = root_dir(dirname) or dirname - else - root_dir = dirname - for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do - if vim.env.HOME == dir then - break - end - if vim.fn.isdirectory(dir .. "/.vscode") == 1 then - root_dir = dir - break - end + or function(startpath) + return vim.fs.root(startpath, { ".git" }) end - end + root_dir = root_dir(dirname) or dirname if not vim.api.nvim_buf_get_option(0, "readonly") and vim.api.nvim_buf_get_option(0, "modified") then vim.cmd.write() end - local args = { - "--workspace-folder", - root_dir, - "--filetype", - filetype, - "--file-path", - vim.fn.expand("%:p"), - } - local cmd = "build_project.py" - if filetype ~= "python" then - cmd = "pixi" - for _, v in - ipairs(vim.fn.reverse({ - "run", - "--manifest-path", - "~/myconfigs/pixi.toml", - "--frozen", - "python3", - "~/.local/bin/build_project.py", - })) - do - table.insert(args, 1, v) - end - end - if is_test then - table.insert(args, "--test") + + local cmd = runner(vim.fn.expand("%:p"), root_dir, is_test) + if not cmd then + return end - term.run(cmd, args, { cwd = root_dir, auto_close = false }) + term.run(cmd[1], vim.list_slice(cmd, 2), { cwd = root_dir, auto_close = false }) end ---------------- diff --git a/scripts/.local/bin/build_project.py b/scripts/.local/bin/build_project.py index 1e669f39..009ccdef 100755 --- a/scripts/.local/bin/build_project.py +++ b/scripts/.local/bin/build_project.py @@ -12,154 +12,11 @@ from typing import Final import argcomplete -from utils import call, run_command +from utils import run_command CMAKE_REPLY_DIR: Final = Path(".cmake") / "api" / "v1" / "reply" -def lua(file: Path, args: list, cwd: Path, extra_args: dict, *, is_test: bool) -> None: - """Run a lua file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Whether the file is a test or not - """ - env = os.environ.copy() - env.pop("NVIMRUNNING", None) - run_command( - ["nvim", "--headless", "-n", "-c", "source", str(file), "-c", "qall!", *args], - dry_run=False, - cwd=cwd, - env=env, - ) - - -def bash(file: Path, args: list, cwd: Path, extra_args: dict, *, is_test: bool) -> None: - """Run a sh file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Whether the file is a test or not - """ - run_command(["bash", str(file), *args], dry_run=False, cwd=cwd) - - -def fish(file: Path, args: list, cwd: Path, extra_args: dict, *, is_test: bool) -> None: - """Run a fish file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Whether the file is a test or not - """ - run_command(["fish", str(file), *args], dry_run=False, cwd=cwd) - - -def python( - file: Path, - args: list, - cwd: Path, - extra_args: dict, - *, - is_test: bool, -) -> None: - """Run a python file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Whether the file is a test or not - """ - cmd = [] - python_path = "python3" - if (pixi_prefix := find_rootdir(".pixi")(file)) is not None: - python_path = pixi_prefix / ".pixi" / "envs" / "default" / "bin" / "python" - if is_test: - if not file.name.startswith("test_") and not file.name.endswith("_test.py"): - logging.error( - f"Test file '{file}' doesn't start/end with 'test_'/'_test' and will be ignored by pytest", - ) - return - cmd.extend([python_path, "-m", "pytest", "--capture=no", str(file.name)]) - cwd = file.parent - else: - cmd.extend([python_path, str(file)]) - run_command(cmd + args, dry_run=False, cwd=cwd) - - -def rust(file: Path, args: list, cwd: Path, extra_args: dict, *, is_test: bool) -> None: - """Run a rust file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Whether the file is a test or not - """ - if (cwd / "Cargo.toml").exists(): - output = call( - ["cargo", "metadata", "--format-version=1"], - cwd=file.parent.resolve(), - ) - output = json.loads(output) - resolved_file_path = str(file.resolve()) - workspace_root = output["workspace_root"] - for package in output["packages"]: - for target in package["targets"]: - if target["kind"] == ["lib"] and is_test: - run_command( - ["cargo", "test", "--lib", *args], - dry_run=False, - cwd=workspace_root, - ) - return - if resolved_file_path == target["src_path"]: - match target["kind"]: - case ["bin"]: - run_command( - ["cargo", "run", "--bin", target["name"], *args], - dry_run=False, - cwd=workspace_root, - ) - case ["example"]: - run_command( - ["cargo", "run", "--example", target["name"], *args], - dry_run=False, - cwd=workspace_root, - ) - case _: - logging.error(f"Unsupported target kind {target['kind']}") - return - logging.error(f"Can't find a target for {file.resolve()}") - return - if ( - run_command( - ["rustc", str(file), "-o", str(file.with_suffix(".out"))], - dry_run=False, - cwd=cwd, - ) - != 0 - ): - logging.error(f"Failed to build '{file}'") - return - run_command( - [str(file.with_suffix(".out")), *args], - dry_run=False, - cwd=cwd, - ) - - def find_rootdir(filename: Path) -> Path: """Find the root directory of a file. @@ -293,38 +150,8 @@ def cmake(file: Path, args: list, cwd: Path, extra_args: dict) -> None: return True -def xacro( - file: Path, - args: list, - cwd: Path, - extra_args: dict, - *, - is_test: bool, -) -> None: - """Run a urdf/xaacro file. - - Args: - file: File to run - args: Arguments to pass to the file when running it - cwd: Current working directory - extra_args: Generic arguments to be used by the runner - is_test: Weather the file is a test or not - """ - run_command( - ["curl", "-X", "POST", "http://127.0.0.1:7777/set_reload_request"], - dry_run=False, - ) - - runners: Final = { - "lua": lua, - "python": python, - "rust": rust, "cpp": cpp, - "fish": fish, - "xml": xacro, - "sh": bash, - "bash": bash, }