Repository navigation
Integration request #11
Description
Activity
@FrancescoDerme Take a look at the implementations of the other integrations in lua/demicolon/integrations/. Basically you want to call
require('demicolon.jump').repeatably_do()with a function that takes in a{ forward: boolean }, and based on the value offorwardyou want to make a call to flash.Based on their examples section I'm guessing that you should be able to do something like this (I haven't actually tried this code out, so I don't know if it actually works though):
---@param options { forward?: boolean } function flash_jump(options) return function() require("demicolon.jump").repeatably_do(function(opts) require("flash").jump({ search = { forward = opts.forward } }) end, options) end end vim.keymap.set({ "n", "x", "o" }, "s", flash_jump({ forward = true }), { desc = "Flash" })
@mawkler thanks for the help! I'm working my way through lengthy trial and error sessions, and again I kindly ask for some guidance. This is what I have thus far. I am trying to imitate what Flash does upon pressing the 'f' key, to do so I copy the relevant internal Flash settings and pass them to the jump function, this for once doesn't seem to work, but that's not even the worst part.
When I press 'f' I get the "prompt" for a flash jump as expected (although not with the right settings as I mentioned) asking for the character to look for in the buffer, but when I press ";" I get the prompt again instead of "repeating the last motion" i.e. "going to the next match for the previous search" which is how Flash usually behaves if there are no conflicts with the keys for treesiteer-textobjects. I fear this is a little more nasty of an integration than the already present ones.
return { "mawkler/demicolon.nvim", -- keys = { ';', ',', 't', 'f', 'T', 'F', ']', '[', ']d', '[d' }, -- Uncomment this to lazy load -- ft = 'tex', -- ...and this if you use LaTeX dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter-textobjects", }, opts = {}, config = function() require("demicolon").setup({ keymaps = { horizontal_motions = false, }, }) ---@param options { forward?: boolean } function flash_jump(options) return function() require("demicolon.jump").repeatably_do(function(opts) local config = require("flash.config") local settings = vim.deepcopy(config.get().modes.char) require("flash").jump(settings) end, options) end end vim.keymap.set({ "n", "x", "o" }, "f", flash_jump({ forward = true }), { desc = "Flash jump" }) end, }
Notice that I also disabled Flash's char search (the one corresponding to 'f') in order to be able to manage everything from demicolon without conflicts.
return { "folke/flash.nvim", event = "VeryLazy", ---@type Flash.Config opts = { modes = { search = { enabled = false, }, char = { enabled = false, jump_labels = false, }, }, }, keys = { { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash jump", }, { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash textobject jump", }, }, }
Hmm yes this does indeed seem more complex to implement.
Looking at their docs it says this:
You can also go to the next match with
;or previous match with,Isn't the feature that you want already implemented in flash.nvim then?
It is except that when I also add treesitter-textobjects and I try to make motions like “]f” repeatable with “;”, either with the following snippet of code or by using demicolon, this flash functionality breaks. Essentially the behavior I’m looking for is one where “;” can repeat motions from both treesitter-textobjects and flash based on what was the last thing I did.
local ts_repeat_move = require "nvim-treesitter.textobjects.repeatable_move" -- Repeat movement with ; and , -- ensure ; goes forward and , goes backward regardless of the last direction vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move_next) vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_previous)
I want to emphasize that this snippet of code is not present in my current setup, it works to make treesitter-textobjects motions repeatable but I discarded it and started to use demicolon instead hoping it would be easier to do what I want to with it.
I think I finally manage to create the behaviour you want:
---@param options { key: string, fowrard: boolean } local function flash_jump(options) return function() require("demicolon.jump").repeatably_do(function(o) local flash_char = require("flash.plugins.char") local key = o.forward and o.key:lower() or o.key:upper() -- Copied from here -- https://github.com/folke/flash.nvim/blob/3c942666f115e2811e959eabbdd361a025db8b63/lua/flash/plugins/char.lua#L118-L136 flash_char.jumping = true local autohide = require("flash.config").get("char").autohide if require("flash.repeat").is_repeat then flash_char.jump_labels = false flash_char.state:jump({ count = vim.v.count1 }) flash_char.state:show() else flash_char.jump(key) end vim.schedule(function() flash_char.jumping = false if flash_char.state and autohide then flash_char.state:hide() end end) end, options) end end vim.keymap.set({ "n", "x", "o" }, "f", flash_jump({ key = "f", forward = true }), { desc = "Flash forward" }) vim.keymap.set({ "n", "x", "o" }, "F", flash_jump({ key = "F", forward = false }), { desc = "Flash backward" })
@mawkler I've tried playing with your code a bit and we're almost there, thanks for the support. The slight problem with it is that after having entered Flash's jump mode I can no longer exit from it in the way I usually do (esc doesn't work, entering insert mode doesn't work) and I am forced to quit neovim. To solve this I've added the following snippet of code and it works fine.
The only thing that's missing now is to have the different behavior of the flash jump depending on whether it was called by "f" or by ";" (right now ";" doesn't jump to the next match for the previous search as it should but only enters flash's char search mode), isn't there a way inside
require('demicolon.jump').repeatably_do()to understand wether it was called by "f" or by ";"?local flash_char = require("flash.plugins.char") vim.api.nvim_create_autocmd({ "BufLeave", "CursorMoved", "InsertEnter" }, { group = vim.api.nvim_create_augroup("flash_char", { clear = true }), callback = function(event) local hide = event.event == "InsertEnter" or not flash_char.jumping if hide and flash_char.state then flash_char.state:hide() end end, }) vim.on_key(function(key) if flash_char.state and key == require("flash.util").ESC and (vim.fn.mode() == "n" or vim.fn.mode() == "v") then flash_char.state:hide() end end)
- added a commit that references this issue
on Apr 22, 2025 @FrancescoDerme I pushed a feature to the branch
repeatedwhich should let you determine whether it was repeated with;/,or not. In my code above that would be the valueo.repeated.Let me know if that's of any help!
@mawkler we did it! Well, you did it, thanks! The following code seems to be working perfectly well. Will you consider merging this feature into the main branch or is it too niche?
return { "mawkler/demicolon.nvim", branch = "repeated", -- keys = { ';', ',', 't', 'f', 'T', 'F', ']', '[', ']d', '[d' }, -- Uncomment this to lazy load -- ft = 'tex', -- ...and this if you use LaTeX dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter-textobjects", }, opts = {}, config = function() require("demicolon").setup({ keymaps = { horizontal_motions = false, }, }) local flash_char = require("flash.plugins.char") ---@param options { key: string, fowrard: boolean } local function flash_jump(options) return function() require("demicolon.jump").repeatably_do(function(o) local key = o.forward and o.key:lower() or o.key:upper() flash_char.jumping = true local autohide = require("flash.config").get("char").autohide -- Originally was -- if require("flash.repeat").is_repeat then if o.repeated then flash_char.jump_labels = false -- Originally was -- flash_char.state:jump({ count = vim.v.count1 }) if o.forward then flash_char.right() else flash_char.left() end flash_char.state:show() else flash_char.jump(key) end vim.schedule(function() flash_char.jumping = false if flash_char.state and autohide then flash_char.state:hide() end end) end, options) end end vim.api.nvim_create_autocmd({ "BufLeave", "CursorMoved", "InsertEnter" }, { group = vim.api.nvim_create_augroup("flash_char", { clear = true }), callback = function(event) local hide = event.event == "InsertEnter" or not flash_char.jumping if hide and flash_char.state then flash_char.state:hide() end end, }) vim.on_key(function(key) if flash_char.state and key == require("flash.util").ESC and (vim.fn.mode() == "n" or vim.fn.mode() == "v") then flash_char.state:hide() end end) vim.keymap.set({ "n", "x", "o" }, "f", flash_jump({ key = "f", forward = true }), { desc = "Flash f" }) vim.keymap.set({ "n", "x", "o" }, "F", flash_jump({ key = "F", forward = false }), { desc = "Flash F" }) vim.keymap.set({ "n", "x", "o" }, "t", flash_jump({ key = "t", forward = true }), { desc = "Flash t" }) vim.keymap.set({ "n", "x", "o" }, "T", flash_jump({ key = "T", forward = false }), { desc = "Flash T" }) end, }
@FrancescoDerme I'm refactoring the implementation to simplify the configuration for the user, but I'll consider merging this when I've completed the refactoring 🙂
I'm trying to create an integration with Flash but have found little success due to my inexperience in programming with lua, could you offer some guidance or implement the integration?