Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

screenstring() doesn't recognize floating windows in child Neovim process #22018

Open
echasnovski opened this issue Jan 27, 2023 · 1 comment
Labels
bug-regression wrong behavior that was introduced in a previous commit (please bisect) float floating windows ui
Milestone

Comments

@echasnovski
Copy link
Member

Describe the bug

The screenstring() executed inside child Neovim process through RPC doesn't recognize floating windows.

This seems to have the same root cause as #21886. When applying the workaround from that issue (spawn another process to attach a UI), it works locally, but probably has the same problems as in that issue.

This might also be related to #19020, which actually made screenstring() recognize floating windows.

Steps to reproduce

  • Create 'init-child-screenstring_floating.lua' with the following content:

    init-child-screenstring_floating.lua
    _G.new_child = function(nvim_executable)
      -- Create new child process
      local stdin = vim.loop.new_pipe(true)
      local stdout = vim.loop.new_pipe(true)
      local stderr = vim.loop.new_pipe(true)
    
      local address = vim.fn.tempname()
    
      vim.loop.spawn(nvim_executable or 'nvim', {
        stdio = { stdin, stdout, stderr },
        args = { '--clean', '--listen', address },
      }, function() end)
    
      -- Wait for Neovim to open
      vim.loop.sleep(200)
    
      -- Connect
      local channel = vim.fn.sockconnect('pipe', address, { rpc = true })
    
      -- Follow advice from https://github.com/neovim/neovim/issues/21630
      stdin:close()
      stdout:close()
      stderr:close()
    
      -- Create helper methods for easier demonstration
      local child = { channel = channel }
    
      -- Call `screenstring()` inside child process
      child.screenstring = function(row, col)
        return vim.rpcrequest(channel, 'nvim_exec_lua', 'return vim.fn.screenstring(...)', { row, col })
      end
    
      -- Main setup: some normal text and floating window partially covering it
      child.setup_text_with_float = function()
        vim.rpcrequest(channel, 'nvim_buf_set_lines', 0, 0, -1, true, { 'aaaa' })
    
        local buf_id = vim.rpcrequest(channel, 'nvim_create_buf', true, true)
        vim.rpcrequest(channel, 'nvim_buf_set_lines', buf_id, 0, -1, true, { 'bb ' })
    
        vim.rpcrequest(
          channel,
          'nvim_open_win',
          buf_id,
          false,
          { relative = 'editor', width = 3, height = 1, row = 0, col = 0 }
        )
      end
    
      return child
    end

    It is basically a creation-connection to full child process (following advice from Can't receive an answer from RPC request to Neovim created as child process #21630) and then a couple helper wrappers to get and set information in child process through RPC requests.

  • Assuming nvim_nightly_g825 is the executable for latest nightly, run nvim_nightly_g825 -u init-child-screenstring_floating.lua.

  • :lua child = new_child('nvim_nightly_g825'). This should create and connect to child process running latest nightly.

  • :lua child.setup_text_with_float(). This should add normal text aaaa covered by bb text in floating window. In total, bb a should be a visible text.

  • Execute :lua print(child.screenstring(1, 1)). It prints a, but should print b.

Expected behavior

Always prints actually visible screen string.

There are three notes here:

  • It works in Neovim 0.8.2 (with new_child('nvim'), assuming nvim is Neovim 0.8.2).

  • It works if applied the workaround from screenstring() doesn't work for Command line in child Neovim process #21886. So adding these lines before local channel = ... makes it work locally:

    vim.loop.spawn(nvim_executable or 'nvim', {
      args = { '--remote-ui', '--server', address },
    }, function() end)
  • It works if executed not in child process, but in "normal" one:

    • Create 'init-screenstring_floating.lua' with the following content:
    vim.api.nvim_buf_set_lines(0, 0, -1, true, { 'aaaa' })
    
    local buf_id = vim.api.nvim_create_buf(true, true)
    vim.api.nvim_buf_set_lines(buf_id, 0, -1, true, { 'bb ' })
    
    vim.api.nvim_open_win(buf_id, false, { relative = 'editor', width = 3, height = 1, row = 0, col = 0 })
    • Run nvim_nightly_g825 -u init-screenstring_floating.lua.
    • :echo screenstring(1, 1). It indeed prints b.

Neovim version (nvim -v)

NVIM v0.9.0-dev-825+g843c9025a

Vim (not Nvim) behaves the same?

No (doesn't have this functionality)

Operating system/version

EndeavourOS Linux x86_64 (6.1.7-arch1-1)

Terminal name/version

st-0.9

$TERM environment variable

st-256color

Installation

appimage

@echasnovski echasnovski added the bug issues reporting wrong behavior label Jan 27, 2023
@zeertzjq zeertzjq added bug-regression wrong behavior that was introduced in a previous commit (please bisect) and removed bug issues reporting wrong behavior labels Jan 27, 2023
@zeertzjq zeertzjq added this to the 0.9 milestone Jan 27, 2023
@zeertzjq zeertzjq added ui float floating windows labels Jan 27, 2023
@echasnovski
Copy link
Member Author

As suggested in #21886, using vim.fn.jobstart(..., { pty = true }) instead of vim.loop.spawn() fixes the issue. With the following 'init-child-screenstring_floating.lua' screenstring() returns expected result from floating windows:

init-child-screenstring_floating.lua
_G.new_child = function(nvim_executable)
  local address = vim.fn.tempname()

  vim.fn.jobstart({ nvim_executable or 'nvim', '--clean', '--listen', address }, { pty = true })

  -- Wait for Neovim to open
  vim.loop.sleep(200)

  -- Connect
  local channel = vim.fn.sockconnect('pipe', address, { rpc = true })

  -- Create helper methods for easier demonstration
  local child = { channel = channel }

  -- Call `screenstring()` inside child process
  child.screenstring = function(row, col)
    return vim.rpcrequest(channel, 'nvim_exec_lua', 'return vim.fn.screenstring(...)', { row, col })
  end

  -- Main setup: some normal text and floating window partially covering it
  child.setup_text_with_float = function()
    vim.rpcrequest(channel, 'nvim_buf_set_lines', 0, 0, -1, true, { 'aaaa' })

    local buf_id = vim.rpcrequest(channel, 'nvim_create_buf', true, true)
    vim.rpcrequest(channel, 'nvim_buf_set_lines', buf_id, 0, -1, true, { 'bb ' })

    vim.rpcrequest(
      channel,
      'nvim_open_win',
      buf_id,
      false,
      { relative = 'editor', width = 3, height = 1, row = 0, col = 0 }
    )
  end

  return child
end

I don't have problem with this being close, but it still seems to not be a good behavior to have in an otherwise valid child process.

@bfredl bfredl modified the milestones: 0.9, 0.10 Apr 7, 2023
@bfredl bfredl modified the milestones: 0.10, 0.11 Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug-regression wrong behavior that was introduced in a previous commit (please bisect) float floating windows ui
Projects
None yet
Development

No branches or pull requests

3 participants