minad / tempel

:classical_building: TempEl - Simple templates for Emacs
GNU General Public License v3.0
506 stars 24 forks source link

Provide an outward-facing function for generating tempel abbrev expansions #134

Closed Luis-Henriquez-Perez closed 5 months ago

Luis-Henriquez-Perez commented 5 months ago

tempel-abbrev-mode is too assuming

The solution to #69, namely the introduction of tempel-abbrev-mode and global-tempel-abbrev-mode, is too assuming and overblown and fails to address the issue's core problem. The core problem is that binding an abbreviation to a function that expands a tempel snippet (as I show below) adds an unecessary space after the snippet is expanded. The problem is not a need to automatically generate an abbrev for every template.

(define-abbrev emacs-lisp-mode-abbrev-table "fun" "" (-partial #'tempel-insert 'fun))

recommended solution

What is needed is simply a user-facing function (as shown below) that generates and returns a function that expands into the specified snippet without adding this extra space. This way the user has a convenient way to actually bind an abbrev to a snippet.

(defun tempel-abbrev-def (name)
  "Return a function."
  (let ((template (cdr (assoc name (tempel--templates))))
        (hook (make-symbol (format "tempel--%s-snippet" name))))
    (fset hook (apply-partially #'tempel--abbrev-hook (symbol-name name) template))
    (put hook 'no-self-insert t)
    hook))

real-life example

The provided tempel-abbrev-mode and its counterpart global-tempel-abbrev-mode do not provide a tool for the user to define their own abbrevs. Opinionated in nature, they assume how users want the abbrev snippets defined and do it for them. In contrast, tempel-abbrev-def only facilitates defining abbrev snippets leaving it users to define their own abbrevs the way they want to–choosing the abbrev name, exactly which snippets they want to have an abbrev for, etc.

Below I provide the real-life example where I had a need for this function and tempel-abbrev-mode did not really help at all–other than being a template from which I learned to write tempel-abbrev-def.

(define-abbrev-table 'emacs-lisp-mode-abbrev-table
  (list (list ".fun"   "" (tempel-abbrev-def 'fun))
        (list ".let"   "" (tempel-abbrev-def 'let))
        (list ".p"     "" (tempel-abbrev-def 'pt))
        (list ".var"   "" (tempel-abbrev-def 'var))
        (list ".al"    "" (tempel-abbrev-def 'alias))
        (list ".alias" "" (tempel-abbrev-def 'alias))))
(abbrev-table-put emacs-lisp-mode-abbrev-table :regexp "\\(?:^\\|[   ]+\\)\\(?1:\\..*\\|.*\\)")

note about laziness

Ideally, tempel should only be loaded (assuming it is not already) when an abbrev that expands to a tempel snippet is expanded. In my example tempel is loaded upon the invocation of tempel-abbrev-def.