diff --git a/doc/pending.txt b/doc/pending.txt index 9a62c3d..752f6f1 100644 --- a/doc/pending.txt +++ b/doc/pending.txt @@ -349,6 +349,7 @@ Default buffer-local keys: ~ `gb` Toggle blocked status (`blocked`) `g/` Toggle cancelled status (`cancelled`) `ge` Open markdown detail buffer for task notes (`edit_notes`) + `gx` Open the forge link under the cursor in a browser (`open_link`) `gf` Prompt for filter predicates (`filter`) `` Switch between category / queue view (`view`) `gz` Undo the last `:w` save (`undo`) @@ -494,6 +495,13 @@ old keys to `false`: >lua Shows a read-only metadata header and editable notes below a `---` separator. Press `q` to return to the task list. Default key: `ge`. + *(pending-open-link)* +(pending-open-link) + Open the forge link under the cursor in a browser via |vim.ui.open()|. + If the cursor is positioned on a forge token (`gh:user/repo#42` or a + full URL), that link is opened. Otherwise, the last forge reference on + the line is used. No-op on lines without forge links. Default key: `gx`. + *(pending-open-line)* (pending-open-line) Insert a correctly-formatted blank task line below the cursor. diff --git a/lua/pending/config.lua b/lua/pending/config.lua index 0015b37..9351b75 100644 --- a/lua/pending/config.lua +++ b/lua/pending/config.lua @@ -83,6 +83,7 @@ ---@field priority_down_visual? string|false ---@field cancelled? string|false ---@field edit_notes? string|false +---@field open_link? string|false ---@class pending.CategoryViewConfig ---@field order? string[] @@ -165,6 +166,7 @@ local defaults = { blocked = 'gb', cancelled = 'g/', edit_notes = 'ge', + open_link = 'gx', priority_up = '', priority_down = '', priority_up_visual = 'g', diff --git a/lua/pending/init.lua b/lua/pending/init.lua index 013533c..829a410 100644 --- a/lua/pending/init.lua +++ b/lua/pending/init.lua @@ -404,6 +404,9 @@ function M._setup_buf_mappings(bufnr) edit_notes = function() M.open_detail() end, + open_link = function() + M.open_link() + end, } for name, fn in pairs(actions) do @@ -931,6 +934,31 @@ function M.open_detail() end, { buffer = detail_bufnr }) end +---@return nil +function M.open_link() + local bufnr = buffer.bufnr() + if not bufnr then + return + end + local row = vim.api.nvim_win_get_cursor(0)[1] + local meta = buffer.meta() + if not meta[row] or meta[row].type ~= 'task' then + return + end + local spans = meta[row].forge_spans + if not spans or #spans == 0 then + return + end + local col = vim.api.nvim_win_get_cursor(0)[2] + for _, span in ipairs(spans) do + if col >= span.col_start and col < span.col_end then + vim.ui.open(span.ref.url) + return + end + end + vim.ui.open(spans[#spans].ref.url) +end + ---@param direction 'up'|'down' ---@return nil function M.move_task(direction) diff --git a/plugin/pending.lua b/plugin/pending.lua index 48ade42..53cc062 100644 --- a/plugin/pending.lua +++ b/plugin/pending.lua @@ -411,6 +411,10 @@ vim.keymap.set('n', '(pending-edit-notes)', function() require('pending').open_detail() end) +vim.keymap.set('n', '(pending-open-link)', function() + require('pending').open_link() +end) + vim.keymap.set('n', '(pending-priority-up)', function() require('pending').increment_priority() end)