Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/pivi/editor/edit_spec.lua

Raw
---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch
local edit = require 'bugabinga.pivi.edit'
local activity = require 'bugabinga.pivi.activity'

local temp_file = function( lines )
  local path = vim.fs.normalize( vim.fn.tempname() .. '.txt' )
  vim.fn.writefile( lines, path )
  return path
end

local open = function( path )
  vim.cmd( 'edit! ' .. vim.fn.fnameescape( path ) )
  return vim.api.nvim_get_current_buf()
end

local lines_of = function( bufnr )
  return vim.api.nvim_buf_get_lines( bufnr, 0, -1, false )
end

describe( 'pivi edit', function()
  after_each( function()
    vim.cmd 'silent! %bwipeout!'
    activity.clear_trail()
  end )

  it( 'finds the loaded buffer for a path', function()
    local path = temp_file { 'one', }
    local bufnr = open( path )
    assert.equal( bufnr, edit.buffer_for( path ) )
    assert.is_nil( edit.buffer_for( path .. '.absent' ) )
  end )

  it( 'prefers unsaved buffer content over disk content', function()
    local path = temp_file { 'on disk', }
    local bufnr = open( path )
    vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'in buffer', } )

    local content, source = edit.read( path )
    assert.equal( 'in buffer', content )
    assert.equal( 'buffer', source )
    assert.same( { 'on disk', }, vim.fn.readfile( path ) )
  end )

  it( 'falls back to disk when no buffer is loaded', function()
    local path = temp_file { 'only on disk', }
    local content, source = edit.read( path )
    assert.equal( 'only on disk', content )
    assert.equal( 'disk', source )
  end )

  it( 'lands an edit in the loaded buffer without a reload', function()
    local path = temp_file { 'alpha', 'beta', 'gamma', }
    local bufnr = open( path )

    local applied = edit.apply( bufnr, { { first = 1, last = 2, lines = { 'BETA', }, }, } )

    assert.is_true( applied )
    assert.same( { 'alpha', 'BETA', 'gamma', }, lines_of( bufnr ) )
    assert.is_true( vim.bo[bufnr].modified )
  end )

  it( 'keeps a multi part edit inside one undo block', function()
    local path = temp_file { 'one', 'two', 'three', 'four', }
    local bufnr = open( path )
    local before = lines_of( bufnr )

    local applied, joined = edit.apply( bufnr, {
      { first = 0, last = 1, lines = { 'ONE', }, },
      { first = 3, last = 4, lines = { 'FOUR', }, },
    } )

    assert.is_true( applied )
    assert.is_true( joined )
    assert.same( { 'ONE', 'two', 'three', 'FOUR', }, lines_of( bufnr ) )

    vim.api.nvim_buf_call( bufnr, function() vim.cmd 'silent undo' end )
    assert.same( before, lines_of( bufnr ) )
  end )

  it( 'still applies the edit when neovim refuses to join undo blocks', function()
    local path = temp_file { 'one', 'two', 'three', }
    local bufnr = open( path )

    vim.api.nvim_buf_set_lines( bufnr, 0, 1, false, { 'scratch', } )
    vim.api.nvim_buf_call( bufnr, function() vim.cmd 'silent undo' end )

    local applied = edit.apply( bufnr, {
      { first = 0, last = 1, lines = { 'ONE', }, },
      { first = 2, last = 3, lines = { 'THREE', }, },
    } )

    assert.is_true( applied )
    assert.same( { 'ONE', 'two', 'THREE', }, lines_of( bufnr ) )
  end )

  it( 'marks every changed line with a navigable trail', function()
    local path = temp_file { 'one', 'two', 'three', }
    local bufnr = open( path )

    edit.apply( bufnr, { { first = 1, last = 2, lines = { 'TWO', }, }, } )

    assert.is_true( #activity.marks( bufnr ) > 0 )
    assert.is_true( #activity.trail() > 0 )
  end )

  it( 'replaces one unique occurrence', function()
    local path = temp_file { 'local value = 1', 'return value', }
    local bufnr = open( path )

    local applied = edit.replace( bufnr, 'local value = 1', 'local value = 2' )

    assert.is_true( applied )
    assert.same( { 'local value = 2', 'return value', }, lines_of( bufnr ) )
  end )

  it( 'marks only the lines a replacement actually touched', function()
    local path = temp_file { 'one', 'two', 'three', 'four', 'five', }
    local bufnr = open( path )

    edit.replace( bufnr, 'three', 'THREE' )

    assert.same( { { buffer = bufnr, first = 3, last = 3, }, }, activity.trail() )
    assert.equal( 1, #activity.marks( bufnr ) )
  end )

  it( 'keeps a replacement undoable as one change', function()
    local path = temp_file { 'one', 'two', 'three', }
    local bufnr = open( path )
    local before = lines_of( bufnr )

    edit.replace( bufnr, 'two', 'TWO' )
    vim.api.nvim_buf_call( bufnr, function() vim.cmd 'silent undo' end )

    assert.same( before, lines_of( bufnr ) )
  end )

  it( 'rewrites only what differs when setting whole content', function()
    local path = temp_file { 'one', 'two', 'three', 'four', 'five', }
    local bufnr = open( path )

    local applied = edit.set_content( bufnr, 'one\ntwo\nTHREE\nfour\nfive' )

    assert.is_true( applied )
    assert.same( { 'one', 'two', 'THREE', 'four', 'five', }, lines_of( bufnr ) )
    assert.is_true( #activity.marks( bufnr ) < 5 )
  end )

  it( 'reports identical content as already applied without marking it', function()
    local path = temp_file { 'one', 'two', }
    local bufnr = open( path )

    assert.is_true( edit.set_content( bufnr, 'one\ntwo' ) )
    assert.equal( 0, #activity.marks( bufnr ) )
    assert.is_false( vim.bo[bufnr].modified )
  end )

  it( 'sets content that grows and shrinks the buffer', function()
    local path = temp_file { 'one', 'two', }
    local bufnr = open( path )

    assert.is_true( edit.set_content( bufnr, 'one\ninserted\ntwo\ntail' ) )
    assert.same( { 'one', 'inserted', 'two', 'tail', }, lines_of( bufnr ) )

    assert.is_true( edit.set_content( bufnr, 'only' ) )
    assert.same( { 'only', }, lines_of( bufnr ) )
  end )

  it( 'refuses an ambiguous replacement', function()
    local path = temp_file { 'same', 'same', }
    local bufnr = open( path )

    local applied, failure = edit.replace( bufnr, 'same', 'other' )

    assert.is_false( applied )
    assert.equal( 'text is not unique', failure )
    assert.same( { 'same', 'same', }, lines_of( bufnr ) )
  end )

  it( 'refuses a replacement whose text is absent', function()
    local path = temp_file { 'one', }
    local bufnr = open( path )
    local applied, failure = edit.replace( bufnr, 'missing', 'other' )
    assert.is_false( applied )
    assert.equal( 'text not found', failure )
  end )

  it( 'makes an agent edit visible to later filesystem readers', function()
    local path = temp_file { 'before', }
    local bufnr = open( path )

    edit.apply( bufnr, { { first = 0, last = 1, lines = { 'after', }, }, } )
    assert.same( { 'before', }, vim.fn.readfile( path ) )

    assert.is_true( edit.persist( bufnr ) )
    assert.same( { 'after', }, vim.fn.readfile( path ) )
    assert.is_false( vim.bo[bufnr].modified )
  end )

  it( 'never persists a scratch buffer', function()
    local bufnr = vim.api.nvim_create_buf( false, true )
    assert.is_false( edit.persist( bufnr ) )
  end )
end )