2

I'm using this yasnippet:

# -*- mode: snippet -*-
# name : case : {...}
# key: case
# --
`(indent-region (- (point) 20) (+ (point) 20) nil)`case ${2:constexpr}: ${3:\{}
    $0
    break;
${3:$(if (string-match "\{" yas-text) "\}" "")}

I think it's some default, but I'm not sure. Until recently, this snippet worked fine, but now I get a t inserted into my buffer, and I think it comes from (indent-region):

        break;
t      case constexpr: {

          break;
        }
      case

How do I get rid of this t?

Andrew Swann
  • 3,436
  • 2
  • 15
  • 43
Markus
  • 471
  • 2
  • 12
  • What was in the buffer before you expanded the snippet, and how did you expand the snippet? There's nothing in indent-region that would insert a t, unless it's been changed from the normal definition. – Tyler Feb 23 '17 at 13:52
  • 4
    Change it to `(progn (indent-region ...) nil)`. – politza Feb 23 '17 at 13:59
  • 1
    Thank you politza, that helped. Apparently, there /is/ something in indent-region that would insert a t. Post your comment as an answer and I will happily accept it :) – Markus Feb 23 '17 at 14:18
  • 3
    My mistake, the last form of `indent-region` is `(setq deactivate-mark t)`, and `setq` does return its value. This is a (relatively) recent change to the function. – Tyler Feb 23 '17 at 15:07
  • 3
    By the way, you should add `# expand-env: ((yas-also-auto-indent-first-line t))` to your snippet instead of trying to indent by side-effect like that. – npostavs Feb 23 '17 at 15:55
  • If this is a recent change that's changed the behavior of `indent-region`, perhaps it's worth `report-emacs-bug`. – Tianxiang Xiong Feb 23 '17 at 18:33
  • @TianxiangXiong It's not a bug in Emacs, the bug is in the snippet depending on the return value of `indent-region`. – npostavs Feb 23 '17 at 21:05
  • If `indent-region`'s return value changed from `nil` to something else, that's a change in the function's interface, which by definition is a breaking change. If it's not intended, it's a bug. – Tianxiang Xiong Feb 23 '17 at 23:37
  • Thanks, npostavs, for the hint with # expand-env. I'm using this now. – Markus Feb 27 '17 at 06:06

1 Answers1

1

The meaning of backquotes in a snippet is to insert the value of the form within the backquotes into the snippet expansion. However, indent-region works by side-effect, and in recent Emacs versions happens to return t. As politza suggested in the comments, you can use (progn (indent-region ...) nil) to drop the return value.

However, this still performs a side effect inside backquotes which will stop being supported in some future version (it triggers a warning in versions 0.11 and higher). In this case, the indentation effect can be written much clearer by binding yas-also-auto-indent-first-line:

# -*- mode: snippet -*-
# name : case : {...}
# key: case
# expand-env: ((yas-also-auto-indent-first-line t))
# --
case ${2:constexpr}:${3: \{}
    $0
    break;
${3:$(if (string-match "\{" yas-text) "\}" "")}

This modification has just been accepted at https://github.com/AndreaCrotti/yasnippet-snippets/pull/176, and will come with the next yasnippet version (0.12), at least for MELPA packages which integrate snippets from that repo. For other examples of avoiding side effects within backquotes, see yasnippet truncates clipboard contents.

npostavs
  • 9,033
  • 1
  • 21
  • 53