leap.nvim icon indicating copy to clipboard operation
leap.nvim copied to clipboard

Handling inclusive_op and exclusivity(till) with bi-directional search?

Open ggandor opened this issue 2 years ago • 0 comments

Discussed in https://github.com/ggandor/leap.nvim/discussions/92

Originally posted by austinliuigi January 5, 2023 I've been trying out bi-directional search and I find it really comfortable, but I'm not sure how to better tweak my config it so that it's the most intuitive for me in visual/operator-pending mode:

s -> Inclusive regardless of which direction I jump x -> Exclusive regardless of which direction I jump

However, the only way that I've found to achieve this behavior is quite hacky and I'm wondering if there's a better way. This is my current configuration:

-- [[ `s` mappings ]]
vim.keymap.set({'n', 'x'}, 's', function()
  require("leap").leap({
    target_windows = { vim.fn.win_getid() },
    inclusive_op = true
  })
end, { noremap = true })

vim.keymap.set({'o'}, 's', function()
  local pre_leap_pos = vim.fn.getpos(".")
  require("leap").leap({
    target_windows = { vim.fn.win_getid() },
    inclusive_op = true
  })
  local post_leap_pos = vim.fn.getpos(".")

  -- If jumping behind original position
  if (pre_leap_pos[2] > post_leap_pos[2]) or ((pre_leap_pos[2] == post_leap_pos[2]) and (pre_leap_pos[3] > post_leap_pos[3])) then
    vim.cmd("normal! h")
  end
end, { remap = false })


-- [[ `x` mappings ]]
vim.keymap.set({'x'}, 'x', function()
  local pre_leap_pos = vim.fn.getpos(".")
  require("leap").leap({
    target_windows = { vim.fn.win_getid() },
    inclusive_op = true
  })
  local post_leap_pos = vim.fn.getpos(".")

  -- If jumping behind original position
  if (pre_leap_pos[2] > post_leap_pos[2]) or ((pre_leap_pos[2] == post_leap_pos[2]) and (pre_leap_pos[3] > post_leap_pos[3])) then
    vim.cmd("normal! l")
  else
    vim.cmd("normal! h")
  end
end, { remap = false })

vim.keymap.set({'o'}, 'x', function()
  local pre_leap_pos = vim.fn.getpos(".")
  require("leap").leap({
    target_windows = { vim.fn.win_getid() },
    inclusive_op = true
  })
  local post_leap_pos = vim.fn.getpos(".")

  -- If jumping forward from original position
  if (pre_leap_pos[2] > post_leap_pos[2]) or ((pre_leap_pos[2] == post_leap_pos[2]) and (pre_leap_pos[3] < post_leap_pos[3])) then
    vim.cmd("normal! h")
  end
end, { remap = false })

Insights

1. inclusive_op The reason the separate operator-pending mappings are necessary is because inclusive_op behaves incorrectly(?)

Example ('|' is cursor, '1' is first label, '2' is second label) abcdefg|abcdefg

Expected behavior:

inclusive_op = true

  • dsde1 -> abcabcdefg
  • dsde2 -> abcdefgefg

inclusive_op = false

  • dsde1 -> abcdabcdefg
  • dsde2 -> abcdefgdefg

Actual behavior:

inclusive_op = true

  • dsde1 -> abcdabcdefg ×
  • dsde2 -> abcdefgefg ✓

inclusive_op = false

  • dsde1 -> abcabcdefg ×
  • dsde2 -> abcdefgefg ✓

When jumping backwards, it seems like inclusive_op behaves opposite as expected. In hindsight, this is the main concern for this discussion thread.

2. Determining jump direction For my visual mode x mapping, I do some logic to determine whether I jumped backwards or forwards using vim's getpos(). Is there a better way to do this using leap's api?

ggandor avatar Apr 18 '23 16:04 ggandor