I'm new to emacs/LISP and would like guidance how to achieve the following output

I'd like to type "color glass hat sport" in a single string ($1) that will be converted to the following:

Color = "C"
Glass = "G"
Hat   = "H"
Sport = "S"

    (Color, 'Colors'), (Glass, 'Glasses'), (Hat, 'Hats'), (Sport, 'Sports'),

How to achieve that with YAS Snippets?

  • Have a look at capitaomorte.github.io/yasnippet/…
    – user2699
    Jan 4 '16 at 14:28
  • Doing something very similar to what you want would be very easy. The difficult (probably impossible) part, would be to have your snippet understand regular and irregular pluralization (i.e., to understand Color -> 'Colors' but Glass -> 'Glasses'. If it were just a matter of adding an 's' to the end of each of the strings, that could easily be achieved, but it would not be accurate for many words (what about "Baby", "Moose", "Money", etc.?)
    – elethan
    Jan 4 '16 at 15:01
  • Thanks @elethan, I understand that and 's' at the end would be just fine. I'm looking for a way to get this done as I'm totally new to LISP / Emacs (but I getting a lot of WOW about it). Any directions how to achieve it? Jan 4 '16 at 16:22
  • Your example string ("color glass hat sport") has four words in it, but probably you want it to work even if it has 2, 5 or 100 words, right? Yasnippet can deal with the case where you know ahead of time how many values you will have (i.e., how many words you will have in your list), but I am not sure how to deal with an arbitrary number of values with yasnippet and elisp alone (others may know how though). Have a look at this discussion stackoverflow.com/questions/18107568/… and this package github.com/abo-abo/auto-yasnippet
    – elethan
    Jan 4 '16 at 16:53
  • It doesn't look these packages help, as I need to add a custom logic, like grab first letter of each type, make it the value of attribute, then make a custom dictionary with those types camelized etc. I'm looking towards custom function in lisp that will produce such output based on words in a string separated by space. Jan 4 '16 at 17:00

With the exception of the pluralization feature I managed to get it to work:

First, add this to your .emacs (or .yas-setup.el in your snippet directory):

(defun dmitry-enum (beg end)
  "Transform the selected region between BEG and END."
  (interactive "r")
  (let* ((strings (split-string (buffer-substring-no-properties beg end)))
         (max (apply 'max (mapcar (lambda (x) (length x)) strings))))
    (delete-region beg end)
    (insert (mapconcat (lambda (x) (format "%s%s = \"%s\""
                                           (capitalize x)
                                           (make-string (- max (length x)) ? )
                                           (upcase (substring x 0 1))))
                       strings "\n"))
    (insert "\n\n_CATEGORIES = (\n")
    (insert "    ")
    (insert (mapconcat (lambda (x) (format "(%s, '%s')"
                                           (capitalize x)
                                           (capitalize (concat x "s"))))
                       strings ", "))
    (insert ",\n)\n")))

Then add the snippet:

# -*- mode: snippet; require-final-newline: nil -*-
# name: special enum
# key: enums
# --
$1${0:$$(let ((beg yas-snippet-beg)
              (end yas-snippet-end))
              (dmitry-enum beg end))}

Now you can either select a region with words such as "color glass hat sport" and call M-x dmitry-enum or write enums followed by yas-expand.

Here it is in action:

yasnippet special enum

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.