Yasnippet snippets that has a percent sign, %
, ending a line with the last point of the snippet, $0
, before the percent sign acts strange in that the cursor gets placed after the percent sign and not before it. I wonder how I can avoid this strange behavior.
Consider the following snippet:
# -*- mode: snippet -*-
# name: test snippet
# key: ts
# --
{
$0%
}
I take it that as it's activated it should insert three lines where the first contains {
, the last line }
and the second line %
and place the cursor before %
on the second line as in the following example:
{
[cursor]%
}
But what happens is the following:
{
% [cursor]
}
How can I make it so that the snippet behaves as I think it should?
My guess is that this is due to something in AUCTeX because it happens with AUCTeX activated but not in the major mode Lisp Interaction.
It works right with my configuration, but I suspect it has to do with auto indenting (mine is heavily customized so that may be the difference). Do you still see the problem if you add
# expand-env: ((yas/indent-line 'fixed))
or
# expand-env: ((yas/indent-line t))
to the snippet's header? You can also try adding $>
to the line(s) that you want indented to see if that makes a difference (if it does that would narrow things down a lot). There is a note in the yasnippet code about some problems with markers changing places, but that looks like it was fixed a few years ago.
You should also check that indent-line-function
has the proper value namely LaTeX-indent-line
.
You could add some sit-for
's to the definition of yas/indent-according-to-mode
to see where point is at different stages. For example put the following in a scratch buffer, position your cursor after the end of it and type C-x C-e
. Then insert your snippet as usual and it will pause for 1 second every where in the code you see a (sit-for 1)
. So if the cursor starts out in the wrong place, then you know the problem is before indentation, etc. You will have to watch it for every line that is indented, so you may wish to turn off indentation except for the problematic line via $>
. Adding or removing sit-for
's will allow you to narrow it down.
(defun yas/indent-according-to-mode (snippet-markers)
"Indent current line according to mode, preserving
SNIPPET-MARKERS."
(sit-for 1)
(goto-char (yas/real-line-beginning))
(sit-for 1)
(let ((trouble-markers (remove-if-not #'(lambda (marker)
(= marker (point)))
snippet-markers)))
(save-restriction
(widen)
(sit-for 1)
(condition-case err
(indent-according-to-mode)
(error (message "[yas] warning: yas/indent-according-to-mode habing problems running %s" indent-line-function)
nil)))
(sit-for 1)
(mapc #'(lambda (marker)
(set-marker marker (point)))
trouble-markers)))