mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(startup): stop TUI properly when quitting at swap dialog (#25337)
This commit is contained in:
		@@ -341,7 +341,7 @@ int main(int argc, char **argv)
 | 
			
		||||
    uint64_t rv = ui_client_start_server(params.argc, params.argv);
 | 
			
		||||
    if (!rv) {
 | 
			
		||||
      os_errmsg("Failed to start Nvim server!\n");
 | 
			
		||||
      getout(1);
 | 
			
		||||
      os_exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    ui_client_channel_id = rv;
 | 
			
		||||
  }
 | 
			
		||||
@@ -1582,6 +1582,7 @@ static void handle_tag(char *tagname)
 | 
			
		||||
 | 
			
		||||
    // If the user doesn't want to edit the file then we quit here.
 | 
			
		||||
    if (swap_exists_did_quit) {
 | 
			
		||||
      ui_call_error_exit(1);
 | 
			
		||||
      getout(1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -1725,6 +1726,7 @@ static void create_windows(mparm_T *parmp)
 | 
			
		||||
          if (got_int || only_one_window()) {
 | 
			
		||||
            // abort selected or quit and only one window
 | 
			
		||||
            did_emsg = false;               // avoid hit-enter prompt
 | 
			
		||||
            ui_call_error_exit(1);
 | 
			
		||||
            getout(1);
 | 
			
		||||
          }
 | 
			
		||||
          // We can't close the window, it would disturb what
 | 
			
		||||
@@ -1828,6 +1830,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd)
 | 
			
		||||
        if (got_int || only_one_window()) {
 | 
			
		||||
          // abort selected and only one window
 | 
			
		||||
          did_emsg = false;             // avoid hit-enter prompt
 | 
			
		||||
          ui_call_error_exit(1);
 | 
			
		||||
          getout(1);
 | 
			
		||||
        }
 | 
			
		||||
        win_close(curwin, true, false);
 | 
			
		||||
@@ -2238,6 +2241,7 @@ static void usage(void)
 | 
			
		||||
static void check_swap_exists_action(void)
 | 
			
		||||
{
 | 
			
		||||
  if (swap_exists_action == SEA_QUIT) {
 | 
			
		||||
    ui_call_error_exit(1);
 | 
			
		||||
    getout(1);
 | 
			
		||||
  }
 | 
			
		||||
  handle_swap_exists(NULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,11 @@ local nvim_async = helpers.nvim_async
 | 
			
		||||
local expect_msg_seq = helpers.expect_msg_seq
 | 
			
		||||
local pcall_err = helpers.pcall_err
 | 
			
		||||
local mkdir = helpers.mkdir
 | 
			
		||||
local poke_eventloop = helpers.poke_eventloop
 | 
			
		||||
local meths = helpers.meths
 | 
			
		||||
local retry = helpers.retry
 | 
			
		||||
local trim = helpers.trim
 | 
			
		||||
local write_file = helpers.write_file
 | 
			
		||||
 | 
			
		||||
describe(':recover', function()
 | 
			
		||||
  before_each(clear)
 | 
			
		||||
@@ -49,10 +54,10 @@ describe("preserve and (R)ecover with custom 'directory'", function()
 | 
			
		||||
    set swapfile fileformat=unix undolevels=-1
 | 
			
		||||
  ]]
 | 
			
		||||
 | 
			
		||||
  local nvim1
 | 
			
		||||
  local nvim0
 | 
			
		||||
  before_each(function()
 | 
			
		||||
    nvim1 = spawn(new_argv())
 | 
			
		||||
    set_session(nvim1)
 | 
			
		||||
    nvim0 = spawn(new_argv())
 | 
			
		||||
    set_session(nvim0)
 | 
			
		||||
    rmdir(swapdir)
 | 
			
		||||
    mkdir(swapdir)
 | 
			
		||||
  end)
 | 
			
		||||
@@ -71,8 +76,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
 | 
			
		||||
 | 
			
		||||
  local function test_recover(swappath1)
 | 
			
		||||
    -- Start another Nvim instance.
 | 
			
		||||
    local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'},
 | 
			
		||||
                                true)
 | 
			
		||||
    local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true)
 | 
			
		||||
    set_session(nvim2)
 | 
			
		||||
 | 
			
		||||
    exec(init)
 | 
			
		||||
@@ -103,7 +107,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
 | 
			
		||||
 | 
			
		||||
  it('closing stdio channel without :preserve #22096', function()
 | 
			
		||||
    local swappath1 = setup_swapname()
 | 
			
		||||
    nvim1:close()
 | 
			
		||||
    nvim0:close()
 | 
			
		||||
    test_recover(swappath1)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
@@ -117,7 +121,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
 | 
			
		||||
    local child_session = helpers.connect(child_server)
 | 
			
		||||
    set_session(child_session)
 | 
			
		||||
    local swappath1 = setup_swapname()
 | 
			
		||||
    set_session(nvim1)
 | 
			
		||||
    set_session(nvim0)
 | 
			
		||||
    command('call chanclose(&channel)')  -- Kill the child process.
 | 
			
		||||
    screen:expect({any = pesc('[Process exited 1]')})  -- Wait for the child process to stop.
 | 
			
		||||
    test_recover(swappath1)
 | 
			
		||||
@@ -373,3 +377,90 @@ describe('swapfile detection', function()
 | 
			
		||||
    feed('e')
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
describe('quitting swapfile dialog on startup stops TUI properly', function()
 | 
			
		||||
  local swapdir = luv.cwd()..'/Xtest_swapquit_dir'
 | 
			
		||||
  local testfile = 'Xtest_swapquit_file1'
 | 
			
		||||
  local otherfile = 'Xtest_swapquit_file2'
 | 
			
		||||
  -- Put swapdir at the start of the 'directory' list. #1836
 | 
			
		||||
  -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
 | 
			
		||||
  -- attempt to create a swapfile in different directory.
 | 
			
		||||
  local init_dir = [[set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//]]
 | 
			
		||||
  local init_set = [[set swapfile fileformat=unix nomodified undolevels=-1 nohidden]]
 | 
			
		||||
 | 
			
		||||
  before_each(function()
 | 
			
		||||
    clear({args = {'--cmd', init_dir, '--cmd', init_set}})
 | 
			
		||||
    rmdir(swapdir)
 | 
			
		||||
    mkdir(swapdir)
 | 
			
		||||
    write_file(testfile, [[
 | 
			
		||||
      first
 | 
			
		||||
      second
 | 
			
		||||
      third
 | 
			
		||||
 | 
			
		||||
    ]])
 | 
			
		||||
    command('edit! '..testfile)
 | 
			
		||||
    feed('Gisometext<esc>')
 | 
			
		||||
    poke_eventloop()
 | 
			
		||||
    clear()  -- Leaves a swap file behind
 | 
			
		||||
    meths.ui_attach(80, 30, {})
 | 
			
		||||
  end)
 | 
			
		||||
  after_each(function()
 | 
			
		||||
    rmdir(swapdir)
 | 
			
		||||
    os.remove(testfile)
 | 
			
		||||
    os.remove(otherfile)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('(Q)uit at first file argument', function()
 | 
			
		||||
    local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
 | 
			
		||||
                                 '--cmd', init_dir, '--cmd', init_set,
 | 
			
		||||
                                 testfile})
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', trim(funcs.getline('$')))
 | 
			
		||||
    end)
 | 
			
		||||
    meths.chan_send(chan, 'q')
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq({'', '[Process exited 1]', ''}, {
 | 
			
		||||
        trim(funcs.getline(1)), trim(funcs.getline(2)), trim(funcs.getline('$')),
 | 
			
		||||
      })
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('(A)bort at second file argument with -p', function()
 | 
			
		||||
    local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
 | 
			
		||||
                                 '--cmd', init_dir, '--cmd', init_set,
 | 
			
		||||
                                 '-p', otherfile, testfile})
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', trim(funcs.getline('$')))
 | 
			
		||||
    end)
 | 
			
		||||
    meths.chan_send(chan, 'a')
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq({'', '[Process exited 1]', ''}, {
 | 
			
		||||
        trim(funcs.getline(1)), trim(funcs.getline(2)), trim(funcs.getline('$')),
 | 
			
		||||
      })
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('(Q)uit at file opened by -t', function()
 | 
			
		||||
    write_file(otherfile, ([[
 | 
			
		||||
      !_TAG_FILE_ENCODING	utf-8	//
 | 
			
		||||
      first	%s	/^  \zsfirst$/
 | 
			
		||||
      second	%s	/^  \zssecond$/
 | 
			
		||||
      third	%s	/^  \zsthird$/]]):format(testfile, testfile, testfile))
 | 
			
		||||
    local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
 | 
			
		||||
                                 '--cmd', init_dir, '--cmd', init_set,
 | 
			
		||||
                                 '--cmd', 'set tags='..otherfile, '-tsecond'})
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:', trim(funcs.getline('$')))
 | 
			
		||||
    end)
 | 
			
		||||
    meths.chan_send(chan, 'q')
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq('Press ENTER or type command to continue', trim(funcs.getline('$')))
 | 
			
		||||
    end)
 | 
			
		||||
    meths.chan_send(chan, '\r')
 | 
			
		||||
    retry(nil, nil, function()
 | 
			
		||||
      eq({'', '[Process exited 1]', ''}, {
 | 
			
		||||
        trim(funcs.getline(1)), trim(funcs.getline(2)), trim(funcs.getline('$')),
 | 
			
		||||
      })
 | 
			
		||||
    end)
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user