Closed andreyorst closed 5 years ago
I made some changes to allow this, you should now be able to do something like:
try %{
snippets-expand-trigger
} catch %{
exec <tab>
}
Note that the commit also comes with some breaking changes in the option names.
I can't get it to work. I've defined a snippet like this:
set global snippets 'for' %{
snippets-insert %{for (int ${1:i}; $1 < $2; $1++) {
${indent}$0
}}}
After that I've tried to:
hook global InsertKey <ret> %{ try %{ snippets-expand-trigger } }
and every time I type for
I get not a valid trigger
error
Right some of this stuff is still a bit underdocumented. I still rely on the two options for (maybe it's worth merging all this stuff into one at some point) for defining the snippet and its trigger, so currently you would have to do something like that
set global snippets_auto_expand false
set global snippets 'For loop' %{
snippets-insert %{for (int ${1:i}; $1 < $2; $1++) {
${indent}$0
}}}
set global snippets_triggers 'for' 'For loop'
And for using <ret>
, I'd suggest using a mapping instead of a hook, so that we don't have to remove the inserted newline:
def snippet-or-newline %{ try %{ snippets-expand-trigger b } catch %{ exec <ret> } }
map global insert <ret> "<a-;>: snippet-or-newline<ret>"
... I guess there is still a way to go before this can be considered user-friendly
maybe it's worth merging all this stuff into one at some point
Consider implementing this as part of #6. I think it would be much better to have triggers defined within snippet syntax, and not Kakoune configuration.
For example, yasnippet snippet definition:
# -*- mode: C -*-
# name: for
# key: for
# --
for (${1:int} ${2:i} = 0; $2 ${3:< 10}; $2${4:++}) {
$0
}
key
is the thigger here, and snippet body is defined after the header.
Here's how it is done in UltiSnips:
snippet for "for loop (for)"
for (${2:i} = 0; $2 < ${1:count}; ${3:++$2}) {
${VISUAL}$0
}
endsnippet
Yeah, your example works just fine. I think such command should be part of snippet, so user just could map it on some key, without explicitly defining it.
By the way. Do you somehow track that we are currently within active snippet? If yes,
define-command snippets-expand-or-jump %{
try %{
snippets-expand-trigger b
} catch %{
snippets-jump-forward-or-key
}
}
define-command snippets-jump-forward-or-key %{
try %{
snippets-jump-forward
catch %{
execute-keys some_user_set_key
}
}
map global insert some_user_set_key "<a-;>: snippet-expand-or-jump<ret>"
This way we could use the same key for both expanding and jumping.
Do you somehow track that we are currently within active snippet?
Not in the sense of the cursor position, but a cheap workaround to that is to keep track of whether there are placeholders remaining. So:
define-command snippets-expand-or-jump %{
try %{
snippets-expand-trigger b
} catch %{
snippets-jump-forward
} catch %{
exec <key>
}
}
It would be cool to have such function inside plugin core, except it should be ready to use user's keys. Something like so:
declare-option str snippets_user_mapping "<tab>"
map global insert %opt{snippets_user_mapping} "<a-;>:<space>snippets-expand-or-jump<ret>"
define-command snippets-expand-or-jump %{
try %{
snippets-expand-trigger b
} catch %{
snippets-jump-forward
} catch %{
exec %opt{snippets_user_mapping}
}
}
Except I'm not sure if this map
will respect user config at all...
Although I'm completely fine if there will be just functions, and mapping those would be on user's side.
With such config:
map global insert '<tab>' "z<a-;>: snippets-expand-or-jump 'tab'<ret>"
hook global InsertCompletionShow .* %{
try %{
execute-keys -draft 'h<a-K>\h<ret>'
map window insert '<ret>' "z<a-;>: snippets-expand-or-jump 'ret'<ret>"
}
}
hook global InsertCompletionHide .* %{
unmap window insert '<ret>' "z<a-;>: snippets-expand-or-jump 'ret'<ret>"
}
define-command snippets-expand-or-jump -params 1 %{
execute-keys <backspace>
try %{
snippets-expand-trigger
} catch %{
snippets-select-next-placeholders
} catch %sh{
case $1 in
ret|tab)
printf "%s\n" "execute-keys -with-hooks <$1>" ;;
*)
printf "%s\n" "execute-keys -with-hooks $1" ;;
esac
}
}
It works like so:
And that's just amazing.
Basically I've made it work just like it worked in my plugin: if popup completion is opened, use return to jump or expand, and tab to cycle. If no popup is opened use tab for expand and jump.
@occivink I've updated my configuration in the comment above. I think that it can be added to the Wiki and this issue can be closed.
I don't really want to start wiki pages yet, but feel free to create them if you wish, I'll update them in case of breaking changes.
It would be handy to have an option to expand snippets when some user-definde key is pressed. Automatic expansion is good feature, but not always wanted. I like to expand snippets with Tab, and jump betwen placeholders with Tab too. This involves some problems when you actually want to insert tab character. When I've designed SimpleSnippets.vim, I've implemented a function, that checked if typed text is a trigger, and if it is it inserted a snippet, otherwise it acted as tab key was pressed. That allowed me to use tab to completions and snippets.