5

I am used to bind my YASnippet trigger keys to sequences that start with < (e.g. when I type <hn in org-mode, it expands to a custom header for my notes).

The problem is that in some modes, the < character is part of electric pairs (I have electric-pair-mode enabled), which automatically writes a closing > when I type it. As a consequence, my snippet expansions are followed by an unwanted >.

The < character is not in electric-pair-pairs nor in electric-pair-text-pairs, so it does not seem easy to just avoid electric pairing for this character (which, besides, I do not want for certain modes).

How should I go about it? Is there a way to make YASnippet delete the > character at expansion, before the actual expansion is written?

Giuseppe
  • 455
  • 2
  • 14
  • maybe this helps [reddit > disable minor mode temporarily while yasnippet](https://www.reddit.com/r/emacs/comments/cg5sf8/disable_a_minor_mode_temporarily_while_yasnippet/) – Hubisan Feb 19 '20 at 06:22

3 Answers3

3

You can disable pairing of <..> as follows:

(add-function :before-until electric-pair-inhibit-predicate
  (lambda (c) (eq c ?<)))
Stefan
  • 26,154
  • 3
  • 46
  • 84
  • 1
    There is a missing parenthesis at the end (I cannot edit since edits have a minimum of 6 characters...). So the working code is `(add-function :before-until electric-pair-inhibit-predicate (lambda (c) (eq c ?<)))`. Thanks! :) – Giuseppe Feb 19 '20 at 20:55
  • @Giuseppe: Indeed, thanks, fixed. – Stefan Feb 19 '20 at 22:16
  • 1
    I'd add that using `(local 'electric-pair-inhibit-predicate)` would make the modification buffer-local, so that this call can be enclosed in a lambda and put in an hook for a specific mode – Alessandro Bertulli Aug 26 '22 at 20:05
1

You can delete chars from the buffer during expansion, but modifying the buffer during expansion is dicouraged.

Deleting chars is pretty easy, because yasnippet allows to eval elisp code during expansion. You have to put this code into back-quotes Read more about it here.

Your snippet would then look like this example (you need to refine this crude example, to match your needs, of course):

# -*- mode: snippet -*-
# name: <hn
# key: <hn
# --
${0:* blubb}`(when (eq major-mode 'org-mode) (delete-char 2))`

Note: This snippet, when expanded in an org-mode buffer, triggers at <hn| > and replaces it with * blubb. (| is cursor position)

jue
  • 4,476
  • 8
  • 20
  • I marked as accepted because it answers exactly my question on how to automatically delete chars. But changing the first trigger key may be a simpler solution. Could you please elaborate on why it is discouraged to delete chars during expansion? – Giuseppe Feb 19 '20 at 20:28
  • @Giuseppe I'm unsure why it is discouraged. The documentation (link in my answer) states so, without giving a reason. Maybe it could mess up indentation or insertion of the snippet. – jue Feb 19 '20 at 21:26
0

I ended up using closing brace for snippets, e.g. } expands to {{ | }} for me. Try >hn instead of <hn.

muffinmad
  • 2,250
  • 7
  • 11
  • Yes, changing the first trigger key is probably the fastest workaround... I will wait for possible other answers before closing this thread. – Giuseppe Feb 17 '20 at 10:59
  • 1
    In case it is helpful to others: when using an alternative first key, and when it turns out this key may cause unwanted snippet expansions (because it is more used in other contexts), a [useful trick](https://emacs.stackexchange.com/questions/45040/expand-yasnippet-only-when-its-at-beginning-of-the-line/45054) consists in limiting the expansion for example to the beginning of line, by adding the following in the snippet file: `# condition: (looking-back "^ – Giuseppe Feb 19 '20 at 21:08