joaotavora / yasnippet

A template system for Emacs
http://joaotavora.github.io/yasnippet/
2.81k stars 311 forks source link

declarative yasnippet templates #1050

Open ghost opened 4 years ago

ghost commented 4 years ago

More often then not I find myself embedding a lot of elisp code in my templates.

I find it painful to write and edit long one-liner snippets with lots of inner elisp code. Additionally, I dislike having many different files for snippets. To me it's a potential source of errors (what if I accidentally delete one? what if I move one into the wrong path? what if I forget to clone the yasnippet dir in the right place? etc.) and it makes it so I have to go looking for a snippet whenever I want to edit it. I would strongly prefer to define a snippet in emacs lisp and keep it in my init file with the rest of my configuration.

These grievances have inspired me to write an API for writing snippet templates in a declarative syntax as opposed to via a snippet file.

A template would look something along these lines.

;; This is a snippet for defining an org link that when clicked opens a
;; *helpful* buffer for describing the specified function.
(defsnippet "help-function"
  :mode org-mode
  :key "hfn"
  :body "[[helpfn:$1][$1]]$0"
  :1 '(yas-auto-next (yas-choose-value (void-list-symbols #'functionp))))

The underlying code would be essentially be converting all of what the snippet manual refers to as "directives" to their string representation (:key "hfn" ==> "# key: hfn" for example), then it would generate the proper yasnippet template body, and finally it would put them into a yasnippet buffer and evaluate it (using yas-load-snippet-buffer).

The main function would look something like this:

(defun defsnippet (&rest declarations)
  "Define a snippet."
  ;; TODO process declarations

  ;; `name', `key', `mode' and `body' should all be non-nil.
  (cl-assert (and name key mode body))

  ;; generate the buffer which yasnippet can load.
  (with-temp-buffer
    (insert (concat (defsnippet-compute-declarations declarations)
                    "\n"
                    (defsnippet-compute-body body)))
    (yas-load-snippet-buffer mode)))

Of course, these are rough sketches. Before I set out to do this:

(1) do you think this is a worthwhile idea? why or why not?

(2) if you belive it is worthwhile, do you have any suggestions or advice for this package?

joaotavora commented 4 years ago

do you think this is a worthwhile idea? why or why not?

My personal opinion is that it is not worthwile, because it is not ambitious enough. Your lispy declarative language would be just "syntactic sugar" around the existing non-lispy declarative language in the snippet files. It doesn't "change the game".

if you belive it is worthwhile, do you have any suggestions or advice for this package?

My suggestion is that you pick up the snippet.el file in the snippet-engine branch, study its functioning and its purpose and get back to me.

npostavs commented 4 years ago

I would strongly prefer to define a snippet in emacs lisp and keep it in my init file with the rest of my configuration.

By the way, you can use yas-define-snippets if you don't mind the snippets being in elisp strings. But ultimately yes, we would want to migrate to the snippet-engine eventually, though it's not something I've had the energy to take on.