Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/pivi/keys_spec.lua

Raw
---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch, redundant-parameter
require 'bugabinga.pivi.fold'
require 'bugabinga.pivi.navigate'
require 'bugabinga.pivi.detail'
require 'bugabinga.pivi.diff'
require 'bugabinga.pivi.guide'
local command = require 'bugabinga.pivi.command'
local session = require 'bugabinga.pivi.session'
local transcript = require 'bugabinga.pivi.transcript'
local fake = dofile 'tests/helpers/pivi_fake.lua'

local MODES = { 'n', 'i', 'x', }

--- Keys pivi binds itself, rather than publishing for the configuration.
--- These are the exceptions where the behaviour *is* the key, mirroring pi:
--- `/` only takes over at the first character, and `@` only when it starts a
--- word, so both remain typable everywhere else.
local ALLOWED = { ['/'] = true, ['@'] = true, }

local claimed = function( bufnr )
  local found = {}
  for _, mode in ipairs( MODES ) do
    for _, mapping in ipairs( vim.api.nvim_buf_get_keymap( bufnr, mode ) ) do
      if not mapping.lhs:find( '<Plug>', 1, true ) and not ALLOWED[mapping.lhs] then
        table.insert( found, mode .. ' ' .. mapping.lhs )
      end
    end
  end
  return found
end

describe( 'pivi keys', function()
  after_each( function()
    session.stop_all()
    transcript.forget_all()
    fake.close_extra_windows()
    vim.cmd 'silent! %bwipeout!'
  end )

  it( 'claims no key of its own in a transcript', function()
    local bufnr = transcript.ensure 'unclaimed'

    assert.same( {}, claimed( bufnr ) )
  end )

  it( 'claims no key of its own in a prompt, beyond naming a command or a file', function()
    local channel = fake.new()
    local current = session.create {
      spawn = channel.spawn,
      name = 'spec',
      extension = false,
      skill = false,
      executable = 'pi',
      env = {},
    }
    local bufnr = command.open_prompt( current )
    vim.cmd.stopinsert()

    assert.same( {}, claimed( bufnr ) )
  end )

  it( 'still types a literal @ inside a word', function()
    -- Naming a file opens a picker, which this test is not exercising.
    local original = vim.ui.select
    vim.ui.select = function( _, _, on_choice ) on_choice( nil ) end

    local channel = fake.new()
    local current = session.create {
      spawn = channel.spawn,
      name = 'typing',
      extension = false,
      skill = false,
      executable = 'pi',
      env = {},
    }
    local bufnr = command.open_prompt( current )
    vim.cmd.stopinsert()

    local at
    for _, mapping in ipairs( vim.api.nvim_buf_get_keymap( bufnr, 'i' ) ) do
      if mapping.lhs == '@' then at = mapping end
    end
    assert.is_table( at )

    local win = vim.fn.bufwinid( bufnr )
    assert.is_true( win > 0 )
    vim.api.nvim_set_current_win( win )

    -- Normal mode cannot place the cursor past the last character, so both
    -- positions below sit inside the line.
    -- Inside a word it is just a character.
    vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'mail me', } )
    vim.api.nvim_win_set_cursor( win, { 1, 4, } )
    assert.equal( '@', at.callback() )

    -- Starting a word it names a file.
    vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'look at x', } )
    vim.api.nvim_win_set_cursor( win, { 1, 8, } )
    assert.equal( '', at.callback() )

    vim.wait( 50, function() return false end )
    vim.ui.select = original
  end )

  it( 'publishes every behavior a key could want', function()
    local bufnr = transcript.ensure 'published'
    local published = {}
    for _, mode in ipairs( MODES ) do
      for _, mapping in ipairs( vim.api.nvim_buf_get_keymap( bufnr, mode ) ) do
        published[mapping.lhs] = true
      end
    end

    for _, intent in ipairs {
      '<Plug>(pivi-toggle-entry)',
      '<Plug>(pivi-next-entry)',
      '<Plug>(pivi-previous-entry)',
      '<Plug>(pivi-next-tool)',
      '<Plug>(pivi-previous-tool)',
      '<Plug>(pivi-goto-location)',
      '<Plug>(pivi-inspect-entry)',
      '<Plug>(pivi-compare-change)',
      '<Plug>(pivi-guide)',
    } do
      assert.is_true( published[intent], intent .. ' is not published' )
    end
  end )

  it( 'never claims a global key', function()
    -- pivi describes its own mappings as `pivi ...`; the configuration
    -- describes its choices as `pi: ...`, and those are allowed to be global.
    for _, mode in ipairs( MODES ) do
      for _, mapping in ipairs( vim.api.nvim_get_keymap( mode ) ) do
        if not mapping.lhs:find( '<Plug>', 1, true ) then
          assert.is_nil( ( mapping.desc or '' ):match '^pivi ',
            mapping.lhs .. ' was claimed globally by pivi' )
        end
      end
    end
  end )

  it( 'yields to a completion popup before accepting a prompt', function()
    local channel = fake.new()
    local current = session.create {
      spawn = channel.spawn,
      name = 'accepting',
      extension = false,
      skill = false,
      executable = 'pi',
      env = {},
    }
    local bufnr = command.open_prompt( current )
    vim.cmd.stopinsert()

    local accept
    for _, mapping in ipairs( vim.api.nvim_buf_get_keymap( bufnr, 'i' ) ) do
      if mapping.lhs == '<Plug>(pivi-accept)' then accept = mapping end
    end

    assert.is_table( accept )
    assert.equal( 1, accept.expr )

    -- With no popup open the prompt is what gets accepted.
    vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'a question', } )
    assert.equal( '', accept.callback() )
  end )
end )