From 51070f33511335afe798c330e9bb8432a65f25ed Mon Sep 17 00:00:00 2001 From: kyufie Date: Sun, 26 Jul 2026 14:39:37 +0700 Subject: [PATCH] fix: Remove cd side effect when executing pio commands --- lua/platformio/piocmd.lua | 6 ++-- lua/platformio/piodebug.lua | 4 +-- lua/platformio/piolib.lua | 2 +- lua/platformio/piolsp.lua | 5 ++- lua/platformio/piomon.lua | 4 +-- lua/platformio/piorun.lua | 12 +++---- lua/platformio/utils.lua | 70 ++++++++++++++++++++++--------------- 7 files changed, 52 insertions(+), 51 deletions(-) diff --git a/lua/platformio/piocmd.lua b/lua/platformio/piocmd.lua index 0f5fde5d..19a20c4b 100644 --- a/lua/platformio/piocmd.lua +++ b/lua/platformio/piocmd.lua @@ -6,16 +6,14 @@ function M.piocmd(cmd_table, direction) return end - utils.cd_pioini() - if cmd_table[1] == '' then - utils.ToggleTerminal('', direction) + utils.ToggleTerminal('', direction, nil, utils.get_platformioRootDir()) else local cmd = 'pio ' for _, v in pairs(cmd_table) do cmd = cmd .. ' ' .. v end - utils.ToggleTerminal(cmd, direction) + utils.ToggleTerminal(cmd, direction, nil, utils.get_platformioRootDir()) end end diff --git a/lua/platformio/piodebug.lua b/lua/platformio/piodebug.lua index d3786e54..6bb2df02 100644 --- a/lua/platformio/piodebug.lua +++ b/lua/platformio/piodebug.lua @@ -6,11 +6,9 @@ function M.piodebug(args_table) return end - utils.cd_pioini() - local command = 'pio debug --interface=gdb -- -x .pioinit' -- local command = string.format('pio debug --interface=gdb -- -x .pioinit %s', utils.extra) - utils.ToggleTerminal(command, 'float') + utils.ToggleTerminal(command, 'float', nil, utils.get_platformioRootDir()) end return M diff --git a/lua/platformio/piolib.lua b/lua/platformio/piolib.lua index ee025d4e..e59b8af8 100644 --- a/lua/platformio/piolib.lua +++ b/lua/platformio/piolib.lua @@ -42,7 +42,7 @@ function M.piolib(lib_arg_list) local command = 'pio pkg install --library "' .. pkg_name .. '"' utils.ToggleTerminal(command, 'float', function() vim.cmd(':PioLSP') - end) + end, utils.get_platformioRootDir()) end) else vim.notify( diff --git a/lua/platformio/piolsp.lua b/lua/platformio/piolsp.lua index fac211ed..0e64ed15 100644 --- a/lua/platformio/piolsp.lua +++ b/lua/platformio/piolsp.lua @@ -106,13 +106,12 @@ function M.piolsp() if not utils.pio_install_check() then return end - utils.cd_pioini() if config.lsp == 'clangd' and config.clangd_source == 'compiledb' then - utils.shell_cmd_blocking('pio run -t compiledb') + utils.shell_cmd_blocking({ 'pio', 'run', '-t', 'compiledb' }, utils.get_platformioRootDir()) gitignore_lsp_configs('compile_commands.json') else - utils.shell_cmd_blocking('pio project init --ide=vim') + utils.shell_cmd_blocking({ 'pio', 'project', 'init', '--ide=vim' }, utils.get_platformioRootDir()) if config.lsp == 'clangd' then M.gen_clangd_config() diff --git a/lua/platformio/piomon.lua b/lua/platformio/piomon.lua index 0917abd3..09c5a6e1 100644 --- a/lua/platformio/piomon.lua +++ b/lua/platformio/piomon.lua @@ -6,8 +6,6 @@ function M.piomon(args_table) return end - utils.cd_pioini() - local command = nil if #args_table == 0 then command = 'pio device monitor' @@ -23,7 +21,7 @@ function M.piomon(args_table) if command == nil then vim.notify('Usage: Piomon ', vim.log.levels.ERROR) else - utils.ToggleTerminal(command, 'horizontal') + utils.ToggleTerminal(command, 'horizontal', nil, utils.get_platformioRootDir()) end end diff --git a/lua/platformio/piorun.lua b/lua/platformio/piorun.lua index 89020f20..5a2c8b3a 100644 --- a/lua/platformio/piorun.lua +++ b/lua/platformio/piorun.lua @@ -3,27 +3,23 @@ local M = {} local utils = require('platformio.utils') function M.piobuild() - utils.cd_pioini() local command = 'pio run' -- .. utils.extra - utils.ToggleTerminal(command, 'float') + utils.ToggleTerminal(command, 'float', nil, utils.get_platformioRootDir()) end function M.pioupload() - utils.cd_pioini() local command = 'pio run --target upload' -- .. utils.extra - utils.ToggleTerminal(command, 'float') + utils.ToggleTerminal(command, 'float', nil, utils.get_platformioRootDir()) end function M.piouploadfs() - utils.cd_pioini() local command = 'pio run --target uploadfs' -- .. utils.extra - utils.ToggleTerminal(command, 'float') + utils.ToggleTerminal(command, 'float', nil, utils.get_platformioRootDir()) end function M.pioclean() - utils.cd_pioini() local command = 'pio run --target clean' -- .. utils.extra - utils.ToggleTerminal(command, 'float') + utils.ToggleTerminal(command, 'float', nil, utils.get_platformioRootDir()) end function M.piorun(arg_table) diff --git a/lua/platformio/utils.lua b/lua/platformio/utils.lua index 83f86089..ed32498c 100644 --- a/lua/platformio/utils.lua +++ b/lua/platformio/utils.lua @@ -19,10 +19,6 @@ function M.check_prefix(str, prefix) return str:sub(1, #prefix) == prefix end -local function pathmul(n) - return '..' .. string.rep('/..', n) -end - ------------------------------------------------------ local is_windows = jit.os == 'Windows' @@ -115,7 +111,7 @@ end ------------------------------------------------------ -- INFO: ToggleTerminal -function M.ToggleTerminal(command, direction, exit_callback) +function M.ToggleTerminal(command, direction, exit_callback, working_dir) if type(exit_callback) ~= 'function' then exit_callback = function() end end @@ -129,6 +125,8 @@ function M.ToggleTerminal(command, direction, exit_callback) local title = '' local pioOpts = {} + pioOpts.dir = working_dir or vim.fn.getcwd() + -- INFO: set orig_window to current window, or if available get current toggleterm previous window local prev = getPreviousWindow(vim.api.nvim_get_current_win()) local orig_window = prev.orig_window @@ -320,8 +318,6 @@ end ---------------------------------------------------------------------------------------- -local paths = { '.', '..', pathmul(1), pathmul(2), pathmul(3), pathmul(4), pathmul(5) } - function M.file_exists(name) local f = io.open(name, 'r') if f ~= nil then @@ -332,22 +328,22 @@ function M.file_exists(name) end end -function M.set_platformioRootDir() - if vim.g.platformioRootDir ~= nil then - return - end - for _, path in pairs(paths) do - if M.file_exists(path .. '/platformio.ini') then - vim.g.platformioRootDir = path - return +function M.get_platformioRootDir() + if vim.g.platformioRootDir == nil then + local path = vim.api.nvim_buf_get_name(0) + if path == '' then + path = vim.fn.getcwd() + end + local match = vim.fs.find({ 'platformio.ini' }, { upward = true, path = path }) + if #match > 0 then + vim.g.platformioRootDir = vim.fs.dirname(match[1]) end - end - vim.notify('Could not find platformio.ini, run :Pioinit to create a new project', vim.log.levels.ERROR) -end -function M.cd_pioini() - M.set_platformioRootDir() - vim.cmd('cd ' .. vim.g.platformioRootDir) + if vim.g.platformioRootDir == nil then + vim.notify('Could not find platformio.ini, run :Pioinit to create a new project', vim.log.levels.ERROR) + end + end + return vim.g.platformioRootDir end function M.pio_install_check() @@ -385,16 +381,32 @@ function M.async_shell_cmd(cmd, callback) }) end -function M.shell_cmd_blocking(command) - local handle = io.popen(command, 'r') - if not handle then - return nil, 'failed to run command' - end +function M.shell_cmd_blocking(args, working_dir) + if vim.system then + local ok, res = pcall(function() + return vim.system(args, { cwd = working_dir, text = true }):wait() + end) + if not ok then + return nil, 'failed to spawn command: ' .. tostring(res) + end + return res.stdout + else + -- Fallback for Neovim < 0.10.0 using vim.fn.system + local cmd_str = table.concat(args, ' ') + local old_dir = nil + if working_dir then + old_dir = vim.fn.getcwd() + vim.cmd('cd ' .. vim.fn.fnameescape(working_dir)) + end + + local stdout = vim.fn.system(cmd_str) - local result = handle:read('*a') - handle:close() + if old_dir then + vim.cmd('cd ' .. vim.fn.fnameescape(old_dir)) + end - return result + return stdout + end end return M