dotfiles/emacs-lisp/tempel.org
Magic_RB 5828904ece
Tempel templates
Signed-off-by: Magic_RB <magic_rb@redalder.org>
2022-10-09 16:30:31 +02:00

141 lines
3.9 KiB
Org Mode

:PROPERTIES:
:ID: a0514202-b2ef-41a4-9d77-01efaa7e8d64
:END:
#+title: Tempel
#+filetags: emacs-load
# SPDX-FileCopyrightText: 2022 Richard Brežák <richard@brezak.sk>
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#+begin_quote
Tempel is a tiny template package for Emacs, which uses the syntax of the Emacs Tempo library. Tempo is an ancient temple of the church of Emacs. It is 27 years old, but still in good shape since it successfully resisted change over the decades. However it may look a bit dusty here and there. Therefore we present to you, Tempel, a modernized implementation of Tempo, in the form of three commands.
#+end_quote
#+begin_src emacs-lisp :noweb yes :exports none
(use-package tempel
:straight '(tempel :type git :host github :repo "minad/tempel")
:config
<<tempel-path>>
:init
<<tempel-hooks>>
<<tempel-keymaps>>)
#+END_SRC
Set the template file to the result of tangling [[id:3e8f0e02-dbfe-4f34-9b00-8b7ecd0a238d][Tempel - Templates]].
#+name: tempel-path
#+begin_src emacs-lisp
(setq tempel-path (expand-file-name "~/roam/emacs-lisp/templates.lisp"))
#+end_src
Hook ~tempel-capf~ on both ~prog-mode~ and ~text-mode~.
#+name: tempel-hooks
#+begin_src emacs-lisp
(defun tempel-setup-capf ()
(add-hook 'completion-at-point-functions #'tempel-complete -1 'local))
(add-hook 'prog-mode-hook 'tempel-setup-capf)
(add-hook 'text-mode-hook 'tempel-setup-capf)
#+end_src
Define keymaps, the defaults are unnecessarily hard to trigger.
#+name: tempel-keymaps
#+begin_src emacs-lisp
(general-define-key
:keymaps '(insert normal)
"C-n" 'nil
"C-p" 'nil)
(general-define-key
:keymaps 'tempel-map
"M-{" nil
"M-}" nil
"C-n" 'tempel-next
"C-p" 'tempel-previous)
#+end_src
~lsp-mode~ completely wipes ~completion-at-point-functions~, so we need re-add ~cape~ after it removes everything.
#+begin_src emacs-lisp
(use-package lsp-mode
:defer t
:after tempel
:config
(add-hook 'lsp-mode-hook 'tempel-setup-capf))
#+end_src
Fix LSP not getting notified about changes, can be fixed by notifying it at the of template expansion.
#+begin_src emacs-lisp
(advice-add
'tempel--disable
:before
(lambda (&rest r)
(when lsp-mode
(let* ((region-start (tempel--beginning))
(region-end (tempel--end)))
(lsp-on-change region-start region-end (- region-end region-start))))))
#+end_src
To setup a post template return point, use ~(p (ignore (setq tempel-retpoint (point))))~ in a template.
#+begin_src emacs-lisp
(defvar tempel-retpoint nil)
(defun tempel-retpoint-here ()
(setq tempel-retpoint (point))
"")
(advice-add
'tempel--disable
:before
(lambda (&rest r)
(when tempel-retpoint
(goto-char tempel-retpoint)
(setq tempel-retpoint nil))))
#+end_src
Disabling ~org-fragtog-mode~ makes the expansion a bit less sporadic.
#+begin_src emacs-lisp
(advice-add
'tempel-expand
:before
(lambda (&rest _r)
(when (eq major-mode 'org-mode)
(org-fragtog-mode -1))))
(advice-add
'tempel-complete
:before
(lambda (&rest _r)
(when (eq major-mode 'org-mode)
(org-fragtog-mode -1))))
(advice-add
'tempel--disable
:before
(lambda (&rest _r)
(when (eq major-mode 'org-mode)
(org-fragtog-mode 1))))
#+end_src
To allow for ~=>~ as template keys, ~'symbol~ won't work, but ~'evil-word~ will.
#+begin_src emacs-lisp
(defun tempel--prefix-bounds ()
"Return prefix bounds."
(if tempel-trigger-prefix
(let ((end (point))
(beg (save-excursion
(search-backward tempel-trigger-prefix
(line-beginning-position) 'noerror))))
(when (and beg (save-excursion
(not (re-search-backward "\\s-" beg 'noerror))))
(cons (+ beg (length tempel-trigger-prefix)) end)))
(bounds-of-thing-at-point 'symbol)))
#+end_src