-
-
Notifications
You must be signed in to change notification settings - Fork 246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add indent string conversion in fmt for multiline string #1264
Conversation
acc62eb
to
d8ac2b6
Compare
Hi :) Thinking about it a bit more, what do you think about |
Yes, the issue is the difficulty in representing When I tried to create a custom snippet using For example, let -- cpp.lua for cpp
s({ trig = "test_if" }, {
sn(1, fmt([[
SSSSif {} then
SSSSSS{}
SSSSend
]], { i(1), i(2) },{}))
})
-- when expanded, I would expect
---cpp
---if {} then
---T{}
---end
-- after that, neovim would expand `T` to certain number of spaces based on configs `shiftwidth`, and `expandtab` (users may have autocmds to set different value of `shiftwidth` for some language) Currently, LuaSnip does not have spaces-to-tab conversion. I tried to explicitly use
-- S is a REAL space, T is a REAL tab
-- \t is just [[\t]]
-- with { indent_string="SS" }, example1 expands to:
---echo "hello\tworld\n"
---Techo "new tab \t"
-- with { }, example1 does nothing after dedent:
---echo "hello\tworld\n"
---SSecho "new tab \t"
s({ trig = "example1" }, {
sn(1, fmt([[
SSSSecho "hello\tworld\n"
SSSSSSecho "new tab \t"
]], {},{ indent_string = "SS"}))
})
-- users may want to explicitly showing the indent by \t
-- with { indent_string=[[\t]] }, example2 expands to:
---echo "hello\tworld\n"
---Techo "new tab \t"
-- with { }, example2 does nothing after dedent:
---echo "hello\tworld\n"
---\techo "new tab \t"
s({ trig = "example2" }, {
-- S is space
sn(1, fmt([[
TTSSecho "hello\tworld\n"
TTSS\techo "new tab \t"
]], {},{ indent_string = [[\t]]}))
})
I may not explain that clearly. This PR intends to ensure custom snippets can be formatted in a neat style when using spaces as indent when |
034b97f
to
3058947
Compare
6acfb9b
to
3082b73
Compare
Ah, thank you, that helped me understand the issue :) I honestly think the best workflow for handling this problem (restore tab-keypress from spaces when expandtab is set) is set listchars+=tab:→\ ,trail:␣,space:·
noremap <silent><leader>l :set invlist<cr> which makes showing whitespace-characters one keybind away. I'd also prefer real tabs because they can be differentiated from real spaces, in case they should be mixed in the snippet: int main(int argc,
·········char*[] argv) {
→ printf("Hello World!")
} where the spaces are dots and the arrow+spaces are a tab Can you see big downsides with this approach? I don't think it's that tedious to press |
I get your point and the method you provided work as expected, but the example is possible with -- real tab inserted by <C-v> as you suggested
fmt([[
int main(int argc,
·········char*[] argv) {
→ printf("Hello World!")
}
]], {}, {})
-- or explicitly mark tab with indent_string
fmt([[
int main(int argc,
·········char*[] argv) {
\tprintf("Hello World!")
}
]], {}, { indent_string = [[\t]] }) It only offers an opt-in conversion if the user intends to convert something (spaces or fmt([[
int main(int argc,
·········char*[] argv) {
····printf("Hello World!")
}
]], {}, { indent_string = "····"})
-- will become:
[[
int main(int argc,
→ → ·char*[] argv) {
→ printf("Hello World!")
}
]]
-- but below is not possible with `indent_string = "····"`, as every 4 spaces become a tab
[[
int main(int argc,
→ ·····char*[] argv) {
→ printf("Hello World!")
}
]]
-- to achieve the above goal, the user can explicitly mark tabs with symbols other than space:
fmt([[
int main(int argc,
\t·····char*[] argv) {
\tprintf("Hello World!")
}
]], {}, { indent_string = [[\t]]})
-- or some visual indicator as mark, for example `→`
fmt([[
int main(int argc,
→·····char*[] argv) {
→printf("Hello World!")
}
]], {}, { indent_string = "→"}) -- "→" here is not a tab, it is an unicode character Limitation
-- <C-v>tab is needed anyway
fmt([[
int main(int argc,
·····→ char*[] argv) {
····printf("Hello World!")
}
]], {}, {})
-- not possible with `indent_string` and explicit marks (though doable if we provide an option to let user specify `unit_indent` and pass it to `convert_indent` function) |
Ahh good point :) Okay, I'm convinced this is a worthwhile addition, thank you! |
Okay, I've looked over the code, this looks very solid, I like the tight loops instead of cobbling something together out of Thank you for implementing this feature! |
Thank you for merging this PR. The path I learned how to create custom LuaSnip snippets was from: s("trigger", {
t("text node "), i(1, "insert node"), t({ "", "this is next line" }), ...
}) to: s("trigger", {
sn(1, fmt([[
text node {}
this is next line
]], { i(1, "insert node") }, {}))
}) For multiline snippets, a |
The following code outputs spaces instead of tabs
'\t'
:The following does not output tabs:
This PR adds option
indent_string
tofmt
, default to empty string (disabled for backward compatibility).Users can specify
indent_string
to letfmt
convert them to tabs'\t'
: