Closed Vanillma closed 1 week ago
Hi :)
This sounds pretty reasonable, and is a really small change :D
I've pushed a first version of this in #1209, could you check if it works as you expect?
Just add copy_selection_keys
in your config
Hi :) This sounds pretty reasonable, and is a really small change :D I've pushed a first version of this in #1209, could you check if it works as you expect? Just add
copy_selection_keys
in your config
Wow, that's fast! Thank you so much, you're amazing!
I tried it out, and it's working great now. But I ran some tests and I'd like to share them with you.
I apologize for the delayed response, as I'm still learning Lua. I tried to explore the luasnip code a bit today with the help of Gemini (Google AI) to understand how the selection part works.
Okay, first of all, I noticed that these two values are defined in the default_config file:
copy_selection_keys = nil,
cut_selection_keys = nil,
When the user sets them, they are used as {lhs} in the key mapping in config file:
if session.config.cut_selection_keys then
vim.cmd(
string.format(
[[xnoremap <silent> %s %s]], session.config.cut_selection_keys, require("luasnip.util.select").select_keys
)
)
end
Then I found {rhs} in the select file and tried to play around with it a bit :))
M.select_keys =
[[:lua require("luasnip.util.select").pre_cut()<Cr>gv"zs<cmd>lua require('luasnip.util.select').post_cut("z")<Cr>]]
M.copy_keys =
[[:lua require("luasnip.util.select").pre_cut()<Cr>gv"zy<cmd>lua require('luasnip.util.select').post_cut("z")<Cr>]]
For example, I noticed that when I use copy, it doesn't enter insert mode by default (I know this is because of the "zy command, which only copies the value to the z register).
I initially changed it to this:
M.copy_keys =
[[:lua require("luasnip.util.select").pre_cut()<Cr>gv"zyi<cmd>lua require('luasnip.util.select').post_cut("z")<Cr>]]
I added an "i" to it to enter insert mode after copying. Then I realized that this method always brings the cursor to the beginning of the line. To solve this, I played around with it again and came up with this :))
M.copy_keys =
[[:lua require("luasnip.util.select").pre_cut()<Cr>gv"zygv<esc>i<cmd>lua require('luasnip.util.select').post_cut("z")<Cr>]]
With this method, the cursor stays where it is.
I know this behavior is probably only my preference and can't be forced on everyone who uses this popular plugin.
So I thought maybe a variable could be added for the user to customize!
local afterCopy = "<cmd>lua print('Copied')<cr>";
M.copy_keys =
[[:lua require("luasnip.util.select").pre_cut()<Cr>gv"zy]] .. afterCopy .. [[<cmd>lua require('luasnip.util.select').post_cut("z")<Cr>]]
Now it copies and even prints a message for me :)
Finally, I want to thank you again. It's working great even now.
I understood how it works and I can customize it for myself.
I just wanted to share a few ideas with you that might help improve it!
Wow, that's fast! Thank you so much, you're amazing!
TY, power of procrastination :P I'm happy it works for you :)
Then I found {rhs} in the select file and tried to play around with it a bit :))
Nice investigating :ok_hand:
That's some rather deep customization (or, just some I didn't anticipate :D), I'll have to consider how to best make an API for doing this (so your customization is not destroyed when I change something about the way select
works :sweat_smile:)
I think it's fine if luasnip exposes the pre_yank and post_yank functions (so, rename them too, to be more accurate), and require that inbetween them, something is put into the register that post_yank gets as an argument. That has the flexibility you want to move the cursor around
Thanks for sharing that new usecase :)
Ah if we do add the new api, we wouldn't even need the new setting, users could just set up their own keymapping :)
Ah if we do add the new api, we wouldn't even need the new setting, users could just set up their own keymapping :)
Yes please, I much prefer defining keymaps myself 🙏
Hi, finally got to wrapping this up :)
I'll just paste the new doc-entry here, it has all the info on using the new pre-yank
and post-yank
callbacks:
Many snippets use the $TM_SELECTED_TEXT
or (for LuaSnip, preferably
LS_SELECT_RAW
or LS_SELECT_DEDENT
) variable, which has to be populated by
selecting and then yanking (and usually also cutting) text from the buffer
before expanding.
By default, this is disabled (as to not pollute keybindings which may be used for something else), so one has to
cut_selection_keys
in setup
(see
Config-Options).ls.cut_keys
as the rhs of a mapping<Esc>
es to NORMAL (to populate the <
and >
-markers)luasnip.pre_yank(<namedreg>)
<namedreg>
luasnip.post_yank(<namedreg>)
Take care that the yanking actually takes place between the two calls. One way
to ensure this is to call the two functions via <cmd>lua ...<Cr>
:
vim.keymap.set("v", "<Tab>", [[<Esc><cmd>lua require("luasnip.util.select").pre_yank("z")<Cr>gv"zs<cmd>lua require('luasnip.util.select').post_yank("z")<Cr>]])
The reason for this specific order is to allow us to take a snapshot of registers (in the pre-callback), and then restore them (in the post-callback) (so that we may get the visual selection directly from the register, which seems to be the most foolproof way of doing this).
Awesome! Will use that next time I update ✨
Nitpick on naming of rhs function as cut_keys
feels a bit weird, have you considered cut_selection
or cut_selection_action
?
Oh, that's because it's not a function, but a sequence of keys :D
Maybe cut_rhs
would've been better, but I think not so much that I'd change it now
I see, oh well ¯\_(ツ)_/¯
Hi, I recently migrated from the vsnip snippet engine to the luasnip snippet engine.
First of all, thank you for creating this excellent snippet engine.
In vsnip, I had two options for using the $TM_SELECTED_TEXT variable:
One option would only select the text but not delete it. I had configured it to enter insert mode after selecting the text.
I searched and only found one option in luasnip, which performs the cut operation.
Is there a way to simulate the select operation as well?
In HTML, there are times when I need to create a copy of an element but within a new container.
Currently, in luasnip, I have to cut the element first, then switch to normal mode, then undo, and then enter insert mode again to continue. This is a workaround to achieve this functionality.
The luasnip documentation states that it is inspired by vsnip.
The idea of selecting and cutting in vsnip was ingenious, and I think it would be beneficial to include it in luasnip as well.
Thanks