Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/lua/bugabinga/pivi_keys.lua

Raw
--- Keys for pivi.
--- pivi publishes intents and chooses no keys, so every choice below is this
--- configuration's. A key that already exists keeps its meaning: it is only
--- reused where the local behaviour is the same idea as the global one.
local auto = require 'std.auto'
local map = require 'std.map'

--- Inside a transcript.
--- `<CR>` activates the thing under the cursor, as it does in a quickfix list,
--- a help buffer or a file explorer.
--- `K` shows what is known about the thing under the cursor.
--- `]]` and `[[` move by section, and an entry is exactly a section.
--- Folding needs no key at all, because entries are real folds.
local TRANSCRIPT = {
  { keys = '<cr>', intent = 'goto-location', description = 'Go to what this entry names', },
  { keys = 'K', intent = 'inspect-entry', description = 'Inspect this entry', },
  { keys = ']]', intent = 'next-entry', description = 'Next entry', },
  { keys = '[[', intent = 'previous-entry', description = 'Previous entry', },
  { keys = '<leader>pd', intent = 'compare-change', description = 'Compare this change', },
  { keys = '<leader>p?', intent = 'guide', description = 'Show the pivi guide', },
  { keys = '<leader>pn', intent = 'next-tool', description = 'Next tool call', },
  { keys = '<leader>pN', intent = 'previous-tool', description = 'Previous tool call', },
}

--- Inside the prompt.
--- `\u003cc-y\u003e` accepts: the completion when one is offered, the prompt otherwise.
--- `\u003ccr\u003e` in normal mode activates what has been composed, and stays a newline
--- while typing.
local PROMPT = {
  { keys = '<c-y>', intent = 'accept', modes = { 'i', }, description = 'Accept the completion, else send', },
  { keys = '<cr>', intent = 'submit', modes = { 'n', }, description = 'Send the prompt', },
  { keys = '<leader>p?', intent = 'guide', modes = { 'n', }, description = 'Show the pivi guide', },
}

local bind = function( bufnr, choices )
  for _, choice in ipairs( choices ) do
    for _, mode in ipairs( choice.modes or { 'n', } ) do
      vim.keymap.set( mode, choice.keys, '<Plug>(pivi-' .. choice.intent .. ')', {
        buffer = bufnr,
        remap = true,
        desc = 'pi: ' .. choice.description,
      } )
    end
  end
end

-- One call: re-calling with the same group name clears everything registered
-- under it, so both surfaces are declared together.
auto 'pivi_keys' {
  {
    events = 'FileType',
    pattern = 'pivi',
    description = 'Choose the keys of a pivi transcript.',
    command = function( event ) bind( event.buf, TRANSCRIPT ) end,
  },
  {
    events = 'FileType',
    pattern = 'pivi-input',
    description = 'Choose the keys of a pivi prompt.',
    command = function( event ) bind( event.buf, PROMPT ) end,
  },
}

-- What the prompt window says about sending, so the hint follows the choice.
vim.g.pivi_submit_hint = '<c-y> or <cr> send'

map.normal {
  description = 'Open the pi prompt',
  category = 'pi',
  keys = '<leader>pp',
  command = '<Plug>(pivi-prompt)',
  remap = true,
}

map.normal {
  description = 'Show the pi transcript',
  category = 'pi',
  keys = '<leader>ps',
  command = '<Plug>(pivi-show)',
  remap = true,
}

map.normal {
  description = 'Abort the current pi run',
  category = 'pi',
  keys = '<leader>pa',
  command = '<Plug>(pivi-abort)',
  remap = true,
}

map.normal {
  description = 'Toggle following the agent',
  category = 'pi',
  keys = '<leader>pf',
  command = '<Plug>(pivi-follow)',
  remap = true,
}

map.normal {
  description = 'Ask pi about neovim, pivi or pi',
  category = 'pi',
  keys = '<leader>ph',
  command = ':Pi help ',
}

map.normal {
  description = 'Ask pi about the project',
  category = 'pi',
  keys = '<leader>pk',
  command = ':Pi ask ',
}

map.visual {
  description = 'Ask pi about the selection',
  category = 'pi',
  keys = '<leader>pk',
  command = ':Pi ask ',
}

return {
  transcript = TRANSCRIPT,
  prompt = PROMPT,
  bind = bind,
}