From 9a48939669431f681505a1a51216b69cee3cb242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tautvydas=20S=CC=8Cidlauskas?= Date: Mon, 28 Sep 2026 09:55:22 +0300 Subject: [PATCH] feat(run): stop the flutter process when exiting nvim Send SIGTERM to the CLI runner's `flutter run` job on VimLeavePre so the tool stops the app (or detaches, when attached) instead of lingering. The DAP runner is already handled by nvim-dap's ExitPre hook. Closes #401 --- lua/flutter-tools.lua | 1 + lua/flutter-tools/commands.lua | 5 +++++ lua/flutter-tools/runners/job_runner.lua | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/lua/flutter-tools.lua b/lua/flutter-tools.lua index a24530f7..8756e7fe 100644 --- a/lua/flutter-tools.lua +++ b/lua/flutter-tools.lua @@ -130,6 +130,7 @@ local function setup_autocommands() pattern = { "*" }, callback = function() dev_tools.stop() + if package.loaded["flutter-tools.commands"] then commands.on_exit() end if package.loaded["flutter-tools.widget_preview"] then widget_preview.on_exit() end end, }) diff --git a/lua/flutter-tools/commands.lua b/lua/flutter-tools/commands.lua index 2fa060f8..9e9a909d 100644 --- a/lua/flutter-tools/commands.lua +++ b/lua/flutter-tools/commands.lua @@ -28,6 +28,7 @@ local current_device = nil ---@field cleanup fun(funner: flutter.Runner) ---@field send fun(runner: flutter.Runner, cmd:string, quiet: boolean?, on_response: fun(response: any)|nil) ---@field attach fun(runner: flutter.Runner, paths:table, args:table, cwd:string, on_run_data:fun(is_err:boolean, data:string), on_run_exit:fun(data:string[], args: table, project_conf: flutter.ProjectConfig?,launch_config: dap.Configuration?)) +---@field stop? fun(runner: flutter.Runner) ---@type flutter.Runner? local runner = nil @@ -65,6 +66,10 @@ function M.current_device() return current_device end function M.is_running() return runner ~= nil and runner:is_running() end +function M.on_exit() + if runner and runner.stop then runner:stop() end +end + local function match_error_string(line) if not line then return false end -- match the error string if no devices are setup diff --git a/lua/flutter-tools/runners/job_runner.lua b/lua/flutter-tools/runners/job_runner.lua index 73c796d9..d070c6a0 100644 --- a/lua/flutter-tools/runners/job_runner.lua +++ b/lua/flutter-tools/runners/job_runner.lua @@ -74,6 +74,14 @@ end function JobRunner:cleanup() run_job = nil end +-- SIGTERM lets the flutter tool stop the app (or only detach, when attached) +-- before exiting; closing stdin alone leaves it running. +function JobRunner:stop() + if not run_job or not run_job.pid then return end + vim.uv.kill(run_job.pid, vim.uv.constants.SIGTERM) + vim.wait(3000, function() return run_job == nil or run_job.is_shutdown end) +end + function JobRunner:attach(paths, args, cwd, on_run_data, on_run_exit) local command = paths.flutter_bin local command_args = args