Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/helpers/pivi_fake.lua

Raw
--- Fake Pi child process for pivi specs.
--- Never patches globals: pivi takes its spawner as an argument.
local new = function()
  local channel = {
    writes = {},
    killed = false,
    commands = {},
  }

  channel.spawn = function( command, options )
    channel.command = command
    channel.options = options
    channel.stdout = options.stdout
    channel.stderr = options.stderr
    channel.on_exit = options.on_exit
    return {
      write = function( _, data )
        if data == nil then
          channel.stdin_closed = true
          return
        end
        table.insert( channel.writes, data )
        for _, record in ipairs( vim.split( data, '\n', { plain = true, } ) ) do
          if record ~= '' then
            local ok, value = pcall( vim.json.decode, record )
            if ok then table.insert( channel.commands, value ) end
          end
        end
      end,
      kill = function() channel.killed = true end,
    }
  end

  --- Emits raw bytes on the child's stdout.
  channel.emit = function( text ) channel.stdout( nil, text ) end

  --- Emits one frame as a complete JSONL record.
  channel.frame = function( value ) channel.emit( vim.json.encode( value ) .. '\n' ) end

  channel.stderr_emit = function( text ) channel.stderr( nil, text ) end

  channel.close = function( code ) channel.on_exit { code = code or 0, } end

  --- Waits for a predicate without sleeping blindly.
  channel.settle = function( predicate )
    return vim.wait( 2000, predicate, 5 )
  end

  --- Waits until every scheduled callback so far has run.
  channel.flush = function()
    local done = false
    vim.schedule( function() done = true end )
    vim.wait( 2000, function() return done end, 1 )
  end

  return channel
end

--- Runs the event loop briefly so callbacks scheduled by a finished test
--- cannot surface after its stubs and buffers are gone.
local drain = function( milliseconds )
  vim.wait( milliseconds or 60, function() return false end, 5 )
end

--- Closes every window except the first so repeated splits cannot exhaust space.
local close_extra_windows = function()
  local wins = vim.api.nvim_tabpage_list_wins( 0 )
  for index = 2, #wins do
    pcall( vim.api.nvim_win_close, wins[index], true )
  end
  for _, tabpage in ipairs( vim.api.nvim_list_tabpages() ) do
    if tabpage ~= vim.api.nvim_get_current_tabpage() then
      pcall( vim.api.nvim_win_close, vim.api.nvim_tabpage_list_wins( tabpage )[1], true )
    end
  end
end

return { new = new, drain = drain, close_extra_windows = close_extra_windows, }