Closed andrewferrier closed 2 years ago
This would be great, not only local mappings per language but also entire configurations. For example, in some languages you may want to add a space between the delimiters and the object [ object ]
as the default behavior while in other languages you don’t want that space when wrapping the object [object]
.
This is a silly example since in surround plugins is common to add spaces depending on whether you use an opening delimiter ‘[‘ or a closing one ‘]’. But it’s an example of how you could increase the flexibility of the plugin with this change without needing to code those specific features.
Hmm I think this could be done via modifying the opts
table in the config.lua
file. I'll need to think about how I would make the changes persist for only the buffer though, as opposed to acting on all files.
@kylechui surround does this using b:
variables which are local to a buffer, you can do this in Lua with vim.b[bufnr].value = 1
or vim.api.nvim_buf_set_var(bufnr, "value", 1)
. There might be a bug with the first mechanism. It didn't use to work but might have since been fixed
Thanks for the tip @akinsho, I just committed a simple version of buffer-local mappings to add-buffer-local-mappings
. The setup interface is nearly identical, just use require("nvim-surround").buffer_setup({opts})
wherever you please. For example, one can overwrite the default f
mapping by calling buffer_setup
inside ftplugin
files as follows:
-- ftplugin/python.lua
require("nvim-surround").buffer_setup({
delimiters = {
pairs = {
["f"] = function()
return {
"def " .. require("nvim-surround.utils").get_input(
"Enter the function name: "
) .. "(",
"):"
}
end,
}
}
})
-- ftplugin/lua.lua
require("nvim-surround").buffer_setup({
delimiters = {
pairs = {
["f"] = function()
return {
"function " .. require("nvim-surround.utils").get_input(
"Enter the function name: "
) .. "(",
")"
}
end,
}
}
})
@andrewferrier and @pmrt also please test it out and let me know what you think! I still have some ugly code I need to clean up in the meantime though
Tried this out, and it works pretty nicely @kylechui, nicely done. One thing which is frankly a separate issue, but I'm posting here since I noticed whilst refactoring from vim-surround, is that it allows using \r
to enter new lines. For example, some vim
buffer surrounds I have in my config that I was looking to replace are
let b:surround_{char2nr('i')} = "if \1if: \1 \r endif"
let b:surround_{char2nr('w')} = "while \1while: \1 \r endwhile"
let b:surround_{char2nr('f')} = "for \1for: \1 {\r endfor"
let b:surround_{char2nr('e')} = "foreach \1foreach: \1 \r enforeach"
let b:surround_{char2nr('F')} = "function! \1function: \1() \r endfunction"
let b:surround_{char2nr('T')} = "try \r endtry"
i.e. these will expand to be multiple lines. Again this isn't a blocker and not immediately related to this specific issue, I just noticed as I went to delete them then realized they wouldn't be on par (realistically I don't write much vimscript any more, so these are more likely to be deleted completely anyway).
Hey @akinsho, I've just refactored it so that delimiters can now be tables instead of just strings, where each element of the table represents a different line to be inserted in the file. For example, to map i
to wrap a condition
inside
if condition then
return nil
end
One could use the following config:
-- Not particularly useful but serves as a proof-of-concept
require("nvim-surround").buffer_setup({
delimiters = {
pairs = {
["i"] = function()
return {
"if ",
{
" then",
" return nil",
"end",
}
}
end
}
}
})
Also as a side-note @NoahTheDuke I might've accidentally resolved #20 in this commit, sorry
Works really well ❤️, have officially fully moved over now since that was the final thing I really needed.
Yes, this seems to work well - thanks! I have the simpler (not using a callback function) buffer-local mappings working well now.
@andrewferrier Do you mean to say that there are still some issues/bugs with the branch? Or just that you have not yet tested it?
Sorry for the lack of clarity. I mean that as far as I know it's working well. I've just used simpler pairs unlike @akinsho which don't use callback functions:
require("nvim-surround").buffer_setup({
delimiters = {
pairs = {
["l"] = { "[", "]()" },
["L"] = { "[](", ")" },
},
},
})
These work well though. From my perspective, you'd be good to merge and close this issue.
Thanks everybody for all the feedback/testing, I really appreciate it!
One thing that would be really nice is if nvim-surround supported filetype-specific or buffer-specific mappings. For example, vim-sandwich allows one to add local "recipes": https://github.com/machakann/vim-sandwich/blob/e114a5e0c90aefed3d2a48ca326eff9d39bc90a9/doc/sandwich.txt#L550.
I use this, for example, to add mappings for Markdown files that I don't use elsewhere. For me, it wouldn't be a huge problem to make them global for now, but this doesn't scale if folks want to have different mappings for the same key in different filetypes.
Perhaps something like
Presumably you'd store these in a buffer-local variable for the duration that the buffer exists.
... then folks can invoke that from
after/ftplugin/markdown.lua
or from inside an autocmd, or wherever they want...