I am trying to setup a snippet to add a src-block header to an emacs org-mode src-block. I want to get a list of possible headers to choose from, which I can get in this snippet (the org-babel-headers function is defined in a .yas-setup.el and just returns a list of the headers).

# -*- mode: snippet -*-
# contributor: John Kitchin <jkitchin@andrew.cmu.edu>
# name: src-block-header
# key: sh
# expand-env: ((headers (org-babel-headers)))
# --
:${1:$$(yas-choose-value headers)} $0

I would also like a second field, right after this, that offers choices that are based on the first choice (i.e. I know the legitimate values each header can take, and I want to offer those as choices).

Is this doable in some way?

  • How about something like a buffer-local or global variable such as (defvar john_kitchin nil "Doc-string.") and then in the snippet instead of (yas-choose-value headers) use (setq john_kitchin (yas-choose-value headers)) and then your second field would be something like (yas-choose-value--john-kitchin john_kitchin)? As you know, setq returns a value -- so in theory, you would be good go ... You can also create a new function yas-choose-value--john_kitchen (based on yas--choose-value) and modify that variable as needed to offer custom choices.
    – lawlist
    May 11 '18 at 1:08
  • Here is an example of something I have been using today: ${3:$$(unless (or yas-moving-away-p yas-modified-p) (let ((result (some #'(lambda (fn) (funcall fn "Are there any transactions >= $1,000.00? " '("n" "y"))) yas-prompt-functions))) (cond ((equal result "n") (setq result "\n+ No individual transactions >= $1,000.00.")) ((equal result "y") (setq result nil))) result))} You can take in/use the result of john-kitchen variable, do whatever needs to be done, and then present a list of choices during that function -- so that when you press enter, the value/string desired is returned.
    – lawlist
    May 11 '18 at 1:20
  • this seems like a good idea, but I have not been able to get it to work. The setq does not seem to be affecting a global variable value. I found another way though. If I can post an answer I will. May 11 '18 at 3:59
  • It seems I can't post an answer yet. The way I found to do it was to use a command type. like described here: groups.google.com/forum/#!topic/smart-snippet/8Og-1U5zJ2E May 11 '18 at 4:00
  • Thank you for posting the link -- I'll hold off with an alternative answer since it sounds like you found a better way of doing it.
    – lawlist
    May 11 '18 at 5:06

Here is how I was able to achieve this goal. It is basically like writing an elisp function that gets the information you want, and then constructs the string to put in the buffer. I adapted the idea from https://groups.google.com/forum/#!topic/smart-snippet/8Og-1U5zJ2E.

# -*- mode: snippet -*-
# contributor: John Kitchin <jkitchin@andrew.cmu.edu>
# name: dependent-choices
# key: exm
# type: command
# --
(let* ((choices '(("a" . ("1" "2" "3"))
          ("b" . ("4" "5" "6"))))
       (choice1 (completing-read "Choice 1: " (mapcar 'car choices)))
       (choice2 (completing-read "Choice 2: " (cdr (assoc choice1 choices)))))
  (yas-expand-snippet (format "${1:%s} ${2:%s} " choice1 choice2)))

Your Answer

