From 73ab0f27b39658acacc771de46f6853ed4ca41a6 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Tue, 4 Jun 2024 09:56:20 -0700 Subject: [PATCH] feat: open_output component --- doc/components.md | 17 +++++ doc/overseer.txt | 28 ++++++-- doc/reference.md | 3 + lua/overseer/component/init.lua | 1 + lua/overseer/component/open_output.lua | 97 ++++++++++++++++++++++++++ lua/overseer/task_list/sidebar.lua | 18 +++++ lua/overseer/window.lua | 17 ++++- 7 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 lua/overseer/component/open_output.lua diff --git a/doc/components.md b/doc/components.md index e7357ec3..821025d1 100644 --- a/doc/components.md +++ b/doc/components.md @@ -15,6 +15,7 @@ - [on_result_diagnostics](#on_result_diagnostics) - [on_result_diagnostics_quickfix](#on_result_diagnostics_quickfix) - [on_result_notify](#on_result_notify) +- [open_output](#open_output) - [restart_on_save](#restart_on_save) - [run_after](#run_after) - [timeout](#timeout) @@ -190,6 +191,22 @@ Normally you will want to use on_complete_notify. If you have a long-running wat - **on_change:** This only works when infer_status_from_diagnostics = true +## open_output + +[open_output.lua](../lua/overseer/component/open_output.lua) + +Open task output + +| Param | Type | Default | Desc | +| ----------- | --------- | ---------- | --------------------------------------------------------------------------------------- | +| direction | `enum` | `"dock"` | Where to open the task output (`"dock"\|"float"\|"tab"\|"vertical"\|"horizontal"`) | +| focus | `boolean` | `false` | Focus the output window when it is opened | +| on_complete | `enum` | `"always"` | Open the output when the task completes (`"always"\|"never"\|"success"\|"failure"`) | +| on_result | `enum` | `"never"` | Open the output when the task produces a result (`"always"\|"never"\|"if_diagnostics"`) | +| on_start | `boolean` | `false` | Open the output when the task starts | + +- **direction:** The 'dock' option will open the output docked to the bottom next to the task list. + ## restart_on_save [restart_on_save.lua](../lua/overseer/component/restart_on_save.lua) diff --git a/doc/overseer.txt b/doc/overseer.txt index d9931c5b..a1919c18 100644 --- a/doc/overseer.txt +++ b/doc/overseer.txt @@ -341,10 +341,11 @@ toggle({opts}) *overseer.toggl Parameters: {opts} `nil|overseer.WindowOpts` - {enter} `nil|boolean` - {direction} `nil|"left"|"right"|"bottom"` - {winid} `nil|integer` Use this existing window instead of opening - a new window + {enter} `nil|boolean` + {direction} `nil|"left"|"right"|"bottom"` + {winid} `nil|integer` Use this existing window instead of opening + a new window + {focus_task} `nil|integer` After opening, focus this task open({opts}) *overseer.open* Open the task list @@ -772,6 +773,25 @@ on_result_notify *on_result_notif {system} `enum` When to send a system notification (default `"never"`) (choices: `"always"|"never"|"unfocused"`) +open_output *open_output* + Open task output + + Parameters: + {direction} `enum` Where to open the task output (default `"dock"`) The + 'dock' option will open the output docked to the bottom next + to the task list. (choices: + `"dock"|"float"|"tab"|"vertical"|"horizontal"`) + {focus} `boolean` Focus the output window when it is opened (default + `false`) + {on_complete} `enum` Open the output when the task completes (default + `"always"`) (choices: + `"always"|"never"|"success"|"failure"`) + {on_result} `enum` Open the output when the task produces a result + (default `"never"`) (choices: + `"always"|"never"|"if_diagnostics"`) + {on_start} `boolean` Open the output when the task starts (default + `false`) + restart_on_save *restart_on_save* Restart on any buffer :write diff --git a/doc/reference.md b/doc/reference.md index 9922e279..4cb7ff72 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -41,6 +41,7 @@ - [on_result_diagnostics](components.md#on_result_diagnostics) - [on_result_diagnostics_quickfix](components.md#on_result_diagnostics_quickfix) - [on_result_notify](components.md#on_result_notify) + - [open_output](components.md#open_output) - [restart_on_save](components.md#restart_on_save) - [run_after](components.md#run_after) - [timeout](components.md#timeout) @@ -385,6 +386,7 @@ Open or close the task list | | enter | `nil\|boolean` | | | | direction | `nil\|"left"\|"right"\|"bottom"` | | | | winid | `nil\|integer` | Use this existing window instead of opening a new window | +| | focus_task | `nil\|integer` | After opening, focus this task | ### open(opts) @@ -721,6 +723,7 @@ Open a tab with windows laid out for debugging a parser - [on_result_diagnostics](components.md#on_result_diagnostics) - [on_result_diagnostics_quickfix](components.md#on_result_diagnostics_quickfix) - [on_result_notify](components.md#on_result_notify) +- [open_output](components.md#open_output) - [restart_on_save](components.md#restart_on_save) - [run_after](components.md#run_after) - [timeout](components.md#timeout) diff --git a/lua/overseer/component/init.lua b/lua/overseer/component/init.lua index 733ae409..34cab857 100644 --- a/lua/overseer/component/init.lua +++ b/lua/overseer/component/init.lua @@ -62,6 +62,7 @@ local builtin_components = { "on_result_diagnostics", "on_result_diagnostics_quickfix", "on_result_notify", + "open_output", "restart_on_save", "run_after", "timeout", diff --git a/lua/overseer/component/open_output.lua b/lua/overseer/component/open_output.lua new file mode 100644 index 00000000..6ce0debb --- /dev/null +++ b/lua/overseer/component/open_output.lua @@ -0,0 +1,97 @@ +local constants = require("overseer.constants") +local STATUS = constants.STATUS + +---@param task overseer.Task +---@param direction "dock"|"float"|"tab"|"vertical"|"horizontal" +---@param focus boolean +local function open_output(task, direction, focus) + if direction == "dock" then + local window = require("overseer.window") + window.open({ + direction = "bottom", + enter = focus, + focus_task = task.id, + }) + else + local winid = vim.api.nvim_get_current_win() + ---@cast direction "float"|"tab"|"vertical"|"horizontal" + task:open_output(direction) + if not focus then + vim.api.nvim_set_current_win(winid) + end + end +end + +---@type overseer.ComponentFileDefinition +local comp = { + desc = "Open task output", + params = { + on_start = { + desc = "Open the output when the task starts", + type = "boolean", + default = false, + }, + on_complete = { + desc = "Open the output when the task completes", + type = "enum", + choices = { "always", "never", "success", "failure" }, + default = "always", + }, + on_result = { + desc = "Open the output when the task produces a result", + type = "enum", + choices = { "always", "never", "if_diagnostics" }, + default = "never", + }, + direction = { + desc = "Where to open the task output", + type = "enum", + choices = { "dock", "float", "tab", "vertical", "horizontal" }, + default = "dock", + long_desc = "The 'dock' option will open the output docked to the bottom next to the task list.", + }, + focus = { + desc = "Focus the output window when it is opened", + type = "boolean", + default = false, + }, + }, + constructor = function(params) + local methods = {} + + if params.on_start then + methods.on_start = function(self, task) + open_output(task, params.direction, params.focus) + end + end + + if params.on_result ~= "never" then + methods.on_result = function(self, task, result) + if + params.on_result == "always" + or ( + params.on_result == "if_diagnostics" and not vim.tbl_isempty(result.diagnostics or {}) + ) + then + open_output(task, params.direction, params.focus) + end + end + end + + if params.on_complete ~= "never" then + methods.on_complete = function(self, task, status, result) + if + params.on_complete == "always" + or (params.on_complete == "success" and status == STATUS.SUCCESS) + or (params.on_complete == "failure" and status == STATUS.FAILURE) + then + open_output(task, params.direction, params.focus) + end + end + end + + return methods + end, +} + +return comp diff --git a/lua/overseer/task_list/sidebar.lua b/lua/overseer/task_list/sidebar.lua index 179da521..3863587b 100644 --- a/lua/overseer/task_list/sidebar.lua +++ b/lua/overseer/task_list/sidebar.lua @@ -134,6 +134,24 @@ function Sidebar:_get_task_from_line(lnum) end end +---@param task_id integer +function Sidebar:focus_task(task_id) + local winid = self:_get_winid() + if not winid then + return + end + local lnum = 1 + for _, v in ipairs(self.task_lines) do + local lines, task = v[1], v[2] + if task.id == task_id then + vim.api.nvim_win_set_cursor(winid, { lnum, 0 }) + self:_set_task_focused(task_id) + return + end + lnum = lnum + lines + end +end + ---@param bufnr integer ---@param winlayout nil|any ---@return nil|"left"|"right"|"bottom" diff --git a/lua/overseer/window.lua b/lua/overseer/window.lua index 816e7738..da7b6c52 100644 --- a/lua/overseer/window.lua +++ b/lua/overseer/window.lua @@ -73,10 +73,18 @@ M.is_open = function() return M.get_win_id() ~= nil end +---@param task_id integer +M.focus_task = function(task_id) + local sidebar = require("overseer.task_list.sidebar") + local sb = sidebar.get_or_create() + sb:focus_task(task_id) +end + ---@class overseer.WindowOpts ----@field enter nil|boolean ----@field direction nil|"left"|"right"|"bottom" ----@field winid nil|integer Use this existing window instead of opening a new window +---@field enter? boolean +---@field direction? "left"|"right"|"bottom" +---@field winid? integer Use this existing window instead of opening a new window +---@field focus_task? integer After opening, focus this task ---@param opts? overseer.WindowOpts M.open = function(opts) @@ -100,6 +108,9 @@ M.open = function(opts) if opts.enter then vim.api.nvim_set_current_win(winid) end + if opts.focus_task then + M.focus_task(opts.focus_task) + end end ---@param opts? overseer.WindowOpts