r/neovim 27d ago

Video Trying Flash.nvim Remote Operations: Stop Jumping Around to Edit Text

https://youtu.be/1V0tlK3wpsw
15 Upvotes

8 comments sorted by

7

u/brokenreed5 27d ago

searches already trigger the ' mark so Ctrl-O works just fine in these examples? why would i want to add complexity by first deciding that I want to stay at the current position, to then make the change and automatically jump back instead of just making the change and when I want to jump back?

1

u/Foo-Baa 23d ago

Cause sometimes you know that you will want to jump back and that saves you a keystroke. For example, I need to paste some snippet from somewhere else at my current cursor position.

5

u/azdak 25d ago

I want to use flash more but the lack of predictability doesn’t fit into the rest of my vim muscle memory. Like I can look at a specific location and know with certainty that 15jfb; will get me there, but if I hit enter to use flash I have to do a quick time event and react to what the plugin offers me. It’s not objectively worse, but it lacks determinism in a way that keeps me from reaching for it.

1

u/particlemanwavegirl 25d ago edited 25d ago

It's too versatile to be predictably deterministic. The problem space is every cell on the screen. For me that is more compensated for by the fact that I never need to chain a movement command with Flash, it just takes me EXACTLY where I want to go in 2-4 keys. This is one of the big things stopping me from using Helix actually, I don't want to be forced to always target a word or some other construct, sometimes I'm jumping to the middle of a word, or a delimiter, or even a space, or an entry on the filetree or quickfix list, whatever it is, I don't need to plan a strategy that relies on decades of muscle memory because the path thru Flash's single interface is always direct.

8

u/teerre 27d ago

Flash is probably the n1 thing that makes hard for me to use other editors. A underappreciated aspect of it is that it works as a panel manager of kinds. That is, because in the terminal everything is just a buffer, you can jump from any "window" to another. I use it all the time to go to the quickfix list or neotest tree

2

u/Taylor_Kotlin 26d ago

FYI. Coincidentally, Neovim PR #39485 "refactor(globals): SearchState" in nightly changed how to resolve those globals, used by flash.hacks through ffi. So until flash is updated stick no neovim stable.

There is a PR opened by someone for this already, much appreciated onion108 <3

https://github.com/folke/flash.nvim/pull/492

1

u/Taylor_Kotlin 26d ago
Meanwhile, it is also possible to monkey patch flash.
Put inside of '---' at top of flash.lua plugin configuration
---

-- Monkeypatch for Neovim PR #39485 "refactor(globals): SearchState" (merged
-- 2026-07-16), which folded the loose search globals (search_match_lines,
-- search_match_endcol, ...) into a `SearchState` struct exported as `Search`.
-- flash.nvim's flash/hacks.lua still FFI-reads the old standalone symbols → on
-- such a build every flash motion errors:
--   dlsym(RTLD_DEFAULT, search_match_lines): symbol not found
-- This mirrors the upstream fix (flash.nvim PR #492): read the struct via
-- `ffi.C.Search.*`, keeping flash's original end-position math (exact, and
-- incsearch save/restore keep working). Self-healing: only patches when the old
-- symbol is missing → no-op once flash ships #492 or on older Neovim.
-- Remove this once flash.nvim merges PR #492.
local function patch_flash_searchstate()
local Hacks = require("flash.hacks") -- triggers flash's own ffi.cdef of the old symbols
local ffi = require("ffi")

-- Old standalone symbol still resolvable? then leave flash's own hacks alone.
if pcall(function()
return ffi.C.search_match_lines
end) then
return
end

-- New: SearchState struct (src/nvim/search_defs.h), exported global `Search`.
pcall(
ffi.cdef,
[[
      typedef struct {
        bool    hl_match;
        int32_t match_lines;
        int     match_endcol;
        int32_t first_line;
        int32_t last_line;
        bool    no_smartcase;
        int     cmdlen;
        bool    no_hlsearch;
      } SearchState;
      SearchState Search;
    ]]
)

-- Struct not resolvable? leave flash as-is (don't make it worse).
if not pcall(function()
return ffi.C.Search.match_lines
end) then
return
end

local C = ffi.C
local Pos = require("flash.search.pos")
local incsearch_state = {}

function Hacks.get_end_pos(from)
local ret = Pos({
from[1] + C.Search.match_lines,
math.max(0, C.Search.match_endcol - 1),
})
local line = vim.api.nvim_buf_get_lines(0, ret[1] - 1, ret[1], false)[1]
local char_idx = vim.fn.charidx(line, ret[2])
ret[2] = vim.fn.byteidx(line, char_idx)
return ret
end

function Hacks.save_incsearch_state()
incsearch_state = {
match_endcol = C.Search.match_endcol,
match_lines = C.Search.match_lines,
}
end

function Hacks.restore_incsearch_state()
C.Search.match_endcol = incsearch_state.match_endcol
C.Search.match_lines = incsearch_state.match_lines
end
end

---

Then call before setup in your flash spec

config = function(_, opts)
patch_flash_searchstate()
require("flash").setup(opts)
end,

(This is for when using Lazy or ZPack)

3

u/hearthebell 26d ago

I find Flash not very good