12

I love yasnippet, but it requires time to memorize. What I'd like to do is change the cursor color when I am at a point that can expand a macro (and back again when there is no macro). However, from what I remember about how yasnippet works, that might not exactly be performant.

A friend suggested that what I want here is a yasnippet-can-fire-p, but I'm still not sure as to the best way to go about doing this. What's the cleanest path towards implementing this that won't drive my sistem to a grinding halt?

angelixd
  • 300
  • 1
  • 7
  • 2
    The solution below looks good enough, but I think the best course of action would be to use yasnippet integrated with one of the completion packages, like auto-complete or company-mode. They show completions when Emacs is idle, and in addition to indication that expansion is possible, they will also show what it will expand to. In fact, auto-complete already has a source for yasnippet. I haven't tried it, though. – Dmitry Jan 10 '13 at 19:18
  • It is possible to use Yasnippet and never have to memorize anything. Clear `name: ` attributes are very helpful for yasnippet search autocompletion. – BinaryButterfly Oct 31 '20 at 17:54

1 Answers1

14

Took some time to find the function that did the checking whether or not it can expand, but was 'lucky' enough to find it eventually.

The key is that this function would normally expand, or otherwise, perform the fallback behavior. I cloned this function and set the cursor colors in those places instead.

And, surprisingly, it actually does not slow down at all.

;; It will test whether it can expand, if yes, cursor color -> green.
(defun yasnippet-can-fire-p (&optional field)
  (interactive)
  (setq yas--condition-cache-timestamp (current-time))
  (let (templates-and-pos)
    (unless (and yas-expand-only-for-last-commands
                 (not (member last-command yas-expand-only-for-last-commands)))
      (setq templates-and-pos (if field
                                  (save-restriction
                                    (narrow-to-region (yas--field-start field)
                                                      (yas--field-end field))
                                    (yas--current-key))
                                (yas--current-key))))

  (set-cursor-color (if (and templates-and-pos (first templates-and-pos)) 
                        "green" "red"))))

; As pointed out by Dmitri, this will make sure it will update color when needed.
(add-hook 'post-command-hook 'yasnippet-can-fire-p)

Added this to my lisp collection (I was actually thinking that this would be useful as well).


Update: In latest version of yasnippet [from august 2014, from 0.8.1], yas--current-key function has been renamed into yas--templates-for-key-at-point. cf Issue

AdrieanKhisbe
  • 3,899
  • 8
  • 37
  • 45
PascalVKooten
  • 20,643
  • 17
  • 103
  • 160
  • 1
    Using `post-self-insert-hook` or even `post-command-hook` instead of advice would be nicer here. You can make them local to certain buffers and, if you use the latter, trigger the cursor change after commands other than `self-insert-command`. – Dmitry Jan 10 '13 at 19:09
  • You can simplify the last 4 lines as follows `(set-cursor-color (if (and templates-and-pos (first templates-and-pos)) "green" "red"))))` – Stefan Jan 10 '13 at 19:52
  • @Stefan Thanks, incorporated your advice! – PascalVKooten Jan 10 '13 at 20:07
  • @Dualinity: you can also move the `unless` into the let-binding, dropping the `setq`: `(let ((templates-and-pos (unless (foo) (if field ...)))) (set-cursor-color ...))`. – Stefan Jan 10 '13 at 20:42
  • Wow, thanks for doing all the hard work! With what you have, I refactored it a bit to be more customizable for people who may want to do something slightly different. I can't include the reply here, but here is a gist: https://gist.github.com/4506396 – angelixd Jan 10 '13 at 22:33
  • https://gist.github.com/4506396 Here's my slight refactor. The main thing it to make yasnippet-can-fire-p is its own boolean function, so you can use it to trigger other events if you'd like. – angelixd Jan 10 '13 at 22:53
  • I actually am considering to "if possible expand, then expand". It is quite interesting but it doesn't work when you have shorthand writing like `r` for require (imagine that on any written `r` it will expand). I am considering to rewrite snippets to a bit longer version (so when you write them, they are unique and you're sure it will trigger correctly!) – PascalVKooten Jan 12 '13 at 14:00
  • It seems that `yas--current-key` no longer exist in latest `yasnippet`: `Error in post-command-hook (yasnippet-can-fire-p): (void-function yas--current-key)` – AdrieanKhisbe Aug 14 '14 at 16:24
  • @PascalvKooten you're welcome. :) (It might be a good idea to push this to yasnippets itself, but that wasn't my call) – AdrieanKhisbe Aug 31 '14 at 11:28