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

Smear when jumping to command #9

Closed
sphamba opened this issue Nov 25, 2024 · 11 comments · Fixed by #71
Closed

Smear when jumping to command #9

sphamba opened this issue Nov 25, 2024 · 11 comments · Fixed by #71
Labels
enhancement New feature or enhancement help needed Need help from contributors

Comments

@sphamba
Copy link
Owner

sphamba commented Nov 25, 2024

No description provided.

@sphamba sphamba added the enhancement New feature or enhancement label Nov 25, 2024
@bew
Copy link

bew commented Dec 7, 2024

Is there a limitation for this to overcome? or is it just not implemented yet?

@sphamba
Copy link
Owner Author

sphamba commented Dec 7, 2024

In my understanding, Neovim blocks the execution of some API calls when entering the command prompt, such as updating the window and buffer options (which smear-cursor relies heavily on). So I am not sure that it would be technically possible. The (unsatisfactory) alternative would be to hide the smear instead of letting it frozen, see #15 ☹️

@sphamba sphamba added the help needed Need help from contributors label Dec 7, 2024
@ColinKennedy
Copy link

ColinKennedy commented Dec 8, 2024

It doesn't look like Neovim allows people to draw virtual text (I assume that's what smear-cursor.nvim is using) during command mode.

A quick test

See test
-- List of random virtual text options
local random_texts = {
  "Hello, Neovim!",
  "Lua rocks!",
  "Virtual text demo",
}

-- Function to get a random number within a range
local function random_range(min, max)
  return math.random(min, max)
end

-- Function to display virtual text at a random position with random text
local function show_random_virtual_text()
  -- Get the current buffer
  local buf = vim.api.nvim_get_current_buf()

  -- Get random line and column within the buffer
  local num_lines = vim.api.nvim_buf_line_count(buf)
  local line = random_range(0, num_lines - 1)
  local col = random_range(0, 80)  -- You can adjust the column limit based on your terminal width

  -- Pick a random text from the list
  local text = random_texts[math.random(#random_texts)]

  -- Set the virtual text at the random position
  vim.api.nvim_buf_set_virtual_text(buf, 0, line, {{text, "Search"}}, {})
end

-- Create a timer to run the function every second (1000 ms)
local timer = vim.uv.new_timer()

-- Start the timer to call show_random_virtual_text every 1000ms
timer:start(0, 1000, vim.schedule_wrap(function()
  show_random_virtual_text()
end))

Run the file, then enter command mode. It should draw a virtual text every second but doesn't. Instead, the accumulated time is executed once command mode is exited. e.g. If you wait 5 seconds, you get ~5 messages when you exit.

I found that if you type a bunch of text in the command mode section it will update without leaving command mode. Sometimes. All of the same behavior applies to noice.nvim. noice uses vim.ui_attach(...) so I don't think anything can be done there.

@ColinKennedy
Copy link

ColinKennedy commented Dec 8, 2024

If you go the "just hide it" route, I'd imagine you'd want to use ModeChanged. (Edit: Actually thinking about it if virtual text changes are not allowed then ModeChanged would probably be too late)

Other than rendering the smear what other things would smear-cursor.nvim need specifically to interact with Neovim?

I did a quick test and you can set buffer variables while in command mode.

See here
-- List of random virtual text options
local random_texts = {
  "Hello, Neovim!",
  "Lua rocks!",
  "Virtual text demo",
}

-- Function to get a random number within a range
local function random_range(min, max)
  return math.random(min, max)
end

-- Function to display virtual text at a random position with random text
local function show_random_virtual_text()
  -- Get the current buffer
  local buf = vim.api.nvim_get_current_buf()

  -- Get random line and column within the buffer
  local num_lines = vim.api.nvim_buf_line_count(buf)
  local line = random_range(0, num_lines - 1)
  local col = random_range(0, 80)  -- You can adjust the column limit based on your terminal width

  -- Pick a random text from the list
  local text = random_texts[math.random(#random_texts)]

  -- Set the virtual text at the random position
  vim.api.nvim_buf_set_virtual_text(buf, 0, line, {{text, "Search"}}, {})
end

-- Create a timer to run the function every second (1000 ms)
local timer = vim.uv.new_timer()

local buffer = vim.api.nvim_get_current_buf()

-- Start the timer to call show_random_virtual_text every 1000ms
timer:start(0, 1000, vim.schedule_wrap(function()
  show_random_virtual_text()

  if vim.b.test then
    local file = io.open("/tmp/foo", "a+")
    file:write(vim.b.test .. "\n")
    file:close()
  end

  local text = random_texts[math.random(#random_texts)]

  vim.b.test = text
end))

@sphamba
Copy link
Owner Author

sphamba commented Dec 8, 2024

To render the smear, there are:

  • floating windows
  • scratch buffers
  • one extmark per buffer, with a given highlight group

So to make the smear disappear, I imagine we could:

  • hide/move/destroy windows or buffers
  • delete extmarks
  • change the highlight groups to something invisible

I started doing some testing with timer and without schedule_wrap, that allows to run code even after a CmdLineEnter event. But we are limited to "fast API" calls, whatever that means

@ColinKennedy
Copy link

ColinKennedy commented Dec 8, 2024

Update - You can actually force a redraw in command mode!

Details
-- List of random virtual text options
local random_texts = {
  "Hello, Neovim!",
  "Lua rocks!",
  "Virtual text demo",
}

-- Function to get a random number within a range
local function random_range(min, max)
  return math.random(min, max)
end

-- Function to display virtual text at a random position with random text
local function show_random_virtual_text()
  -- Get the current buffer
  local buf = vim.api.nvim_get_current_buf()

  -- Get random line and column within the buffer
  local num_lines = vim.api.nvim_buf_line_count(buf)
  local line = random_range(0, num_lines - 1)
  local col = random_range(0, 80)  -- You can adjust the column limit based on your terminal width

  -- Pick a random text from the list
  local text = random_texts[math.random(#random_texts)]

  -- Set the virtual text at the random position
  vim.api.nvim_buf_set_virtual_text(buf, 0, line, {{text, "Search"}}, {})
end

-- Create a timer to run the function every second (1000 ms)
local timer = vim.uv.new_timer()

-- Start the timer to call show_random_virtual_text every 1000ms
timer:start(0, 1000, vim.schedule_wrap(function()
  vim.cmd.redraw()
  show_random_virtual_text()
end))

Thank you to @echasnovski who pointed it out.

I'm not sure if that unblocks you but more options can't hurt, right?

@sphamba
Copy link
Owner Author

sphamba commented Dec 26, 2024

@ColinKennedy Thank you for the pointers! Apparently, using timer:start(timeout, 0, ... (equvalent to current implementation) is blocking, while using timer:start(0, interval, ...) is not. I implemented that in #71, and it works 🎉

There is still an issue with keybindings that use the command line (: ... <cr>), which also trigger a smear that I would not expect in this case.

@ColinKennedy
Copy link

ColinKennedy commented Dec 26, 2024

In general the : ... <cr> case shouldn't come up that much. Most people should be using <cmd> ... <cr> anyway because it's more efficient. I only use :Foo in keybindings when the binding does not end in <cr>. Because in that case I'd be intentionally switching to command mode and would expect smear-cursor to activate.

@craftgear
Copy link

Hi, can we disable this feature on configuration?

@sphamba
Copy link
Owner Author

sphamba commented Dec 30, 2024

Hi, can we disable this feature on configuration?

@craftgear Just added the configuration parameter smear_to_cmd (true by default) #77

@craftgear
Copy link

@sphamba Wow, I didn't expect this! Thank you so much😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or enhancement help needed Need help from contributors
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants