diff --git a/home/emacs/default.nix b/home/emacs/default.nix index ca2594af..df57b8c1 100644 --- a/home/emacs/default.nix +++ b/home/emacs/default.nix @@ -3,7 +3,7 @@ { xdg.configFile = { "emacs/init.el".source = ./init.el; - "emacs/snippets".source = ./snippets; + "emacs/templates".source = ./templates; }; programs.emacs = { enable = true; @@ -25,9 +25,8 @@ vertico # snippets-packages - yasnippet - yasnippet-snippets - consult-yasnippet + tempel + tempel-collection # ide-packages flymake-popon diff --git a/home/emacs/init.el b/home/emacs/init.el index 66632784..b38c92a5 100644 --- a/home/emacs/init.el +++ b/home/emacs/init.el @@ -602,11 +602,6 @@ ("C-r" . consult-history)) :config (setq completion-in-region-function #'consult-completion-in-region)) -(use-package consult-yasnippet - :ensure t - :after consult - :commands (consult-yasnippet)) - (use-package consult-eglot :ensure t :after consult @@ -625,20 +620,43 @@ :after (embark consult) :hook (embark-collect-mode . consult-preview-at-point-mode)) -(use-package yasnippet - :ensure t - :hook ((prog-mode org-mode) . yas-minor-mode)) +;; Configure Tempel +(use-package tempel + ;; Require trigger prefix before template name when completing. + :custom + (tempel-trigger-prefix "<") -(use-package yasnippet-snippets - :ensure t - :after yasnippet - :config (yas-reload-all)) + :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand + ("M-*" . tempel-insert)) -(use-package yasnippet-capf - :ensure t - :after cape - :config - (add-to-list 'completion-at-point-functions #'yasnippet-capf)) + :init + + ;; Setup completion at point + (defun tempel-setup-capf () + ;; Add the Tempel Capf to `completion-at-point-functions'. + ;; `tempel-expand' only triggers on exact matches. Alternatively use + ;; `tempel-complete' if you want to see all matches, but then you + ;; should also configure `tempel-trigger-prefix', such that Tempel + ;; does not trigger too often when you don't expect it. NOTE: We add + ;; `tempel-expand' *before* the main programming mode Capf, such + ;; that it will be tried first. + (setq-local completion-at-point-functions + (cons #'tempel-expand + completion-at-point-functions))) + + (add-hook 'conf-mode-hook 'tempel-setup-capf) + (add-hook 'prog-mode-hook 'tempel-setup-capf) + (add-hook 'text-mode-hook 'tempel-setup-capf) + + ;; Optionally make the Tempel templates available to Abbrev, + ;; either locally or globally. `expand-abbrev' is bound to C-x '. + (add-hook 'prog-mode-hook #'tempel-abbrev-mode) + (global-tempel-abbrev-mode) + ) + +;; Optional: Add tempel-collection. +;; The package is young and doesn't have comprehensive coverage. +(use-package tempel-collection) (use-package aggressive-indent :ensure t diff --git a/home/emacs/init.org b/home/emacs/init.org index e5be7e5a..0d63f3a3 100644 --- a/home/emacs/init.org +++ b/home/emacs/init.org @@ -722,11 +722,6 @@ For reference information, see [[https://orgmode.com][Org-mode website]] ("C-r" . consult-history)) :config (setq completion-in-region-function #'consult-completion-in-region)) - (use-package consult-yasnippet - :ensure t - :after consult - :commands (consult-yasnippet)) - (use-package consult-eglot :ensure t :after consult @@ -750,20 +745,43 @@ For reference information, see [[https://orgmode.com][Org-mode website]] #+end_src ** Snippets #+begin_src emacs-lisp - (use-package yasnippet - :ensure t - :hook ((prog-mode org-mode) . yas-minor-mode)) + ;; Configure Tempel + (use-package tempel + ;; Require trigger prefix before template name when completing. + :custom + (tempel-trigger-prefix "<") - (use-package yasnippet-snippets - :ensure t - :after yasnippet - :config (yas-reload-all)) + :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand + ("M-*" . tempel-insert)) - (use-package yasnippet-capf - :ensure t - :after cape - :config - (add-to-list 'completion-at-point-functions #'yasnippet-capf)) + :init + + ;; Setup completion at point + (defun tempel-setup-capf () + ;; Add the Tempel Capf to `completion-at-point-functions'. + ;; `tempel-expand' only triggers on exact matches. Alternatively use + ;; `tempel-complete' if you want to see all matches, but then you + ;; should also configure `tempel-trigger-prefix', such that Tempel + ;; does not trigger too often when you don't expect it. NOTE: We add + ;; `tempel-expand' *before* the main programming mode Capf, such + ;; that it will be tried first. + (setq-local completion-at-point-functions + (cons #'tempel-expand + completion-at-point-functions))) + + (add-hook 'conf-mode-hook 'tempel-setup-capf) + (add-hook 'prog-mode-hook 'tempel-setup-capf) + (add-hook 'text-mode-hook 'tempel-setup-capf) + + ;; Optionally make the Tempel templates available to Abbrev, + ;; either locally or globally. `expand-abbrev' is bound to C-x '. + (add-hook 'prog-mode-hook #'tempel-abbrev-mode) + (global-tempel-abbrev-mode) + ) + + ;; Optional: Add tempel-collection. + ;; The package is young and doesn't have comprehensive coverage. + (use-package tempel-collection) #+end_src ** Aggressive Indent #+begin_src emacs-lisp diff --git a/home/emacs/templates b/home/emacs/templates new file mode 100644 index 00000000..a841c498 --- /dev/null +++ b/home/emacs/templates @@ -0,0 +1,156 @@ +;; ~/.config/emacs/templates + +fundamental-mode ;; Available everywhere + +(today (format-time-string "%Y-%m-%d")) + +prog-mode + +(fixme (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "FIXME ") +(todo (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "TODO ") +(bug (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "BUG ") +(hack (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "HACK ") + +latex-mode + +(abstract "\\begin{abstract}\n" r> n> "\\end{abstract}") +(align "\\begin{align}\n" r> n> "\\end{align}") +(alignn "\\begin{align*}\n" r> n> "\\end{align*}") +(gather "\\begin{gather}\n" r> n> "\\end{gather}") +(gatherr "\\begin{gather*}\n" r> n> "\\end{gather*}") +(appendix "\\begin{appendix}\n" r> n> "\\end{appendix}") +(begin "\\begin{" (s env) "}" r> n> "\\end{" (s env) "}") +(center "\\begin{center}\n" r> n> "\\end{center}") +(displaymath "\\begin{displaymath}\n" r> n> "\\end{displaymath}") +(document "\\begin{document}\n" r> n> "\\end{document}") +(enumerate "\\begin{enumerate}\n\\item " r> n> "\\end{enumerate}") +(equation "\\begin{equation}" r> n> "\\end{equation}") +(flushleft "\\begin{flushleft}" r> n> "\\end{flushleft}") +(flushright "\\begin{flushright}" r> n> "\\end{flushright}") +(frac "\\frac{" p "}{" q "}") +(fussypar "\\begin{fussypar}" r> n> "\\end{fussypar}") +(itemize "\\begin{itemize}\n\\item " r> n> "\\end{itemize}") +(letter "\\begin{letter}\n" r> n> "\\end{letter}") +(math "\\begin{math}\n" r> n> "\\end{math}") +(minipage "\\begin{minipage}[t]{0.5\linewidth}\n" r> n> "\\end{minipage}") +(quotation "\\begin{quotation}\n" r> n> "\\end{quotation}") +(quote "\\begin{quote}\n" r> n> "\\end{quote}") +(sloppypar "\\begin{sloppypar}\n" r> n> "\\end{sloppypar}") +(theindex "\\begin{theindex}\n" r> n> "\\end{theindex}") +(trivlist "\\begin{trivlist}\n" r> n> "\\end{trivlist}") +(verbatim "\\begin{verbatim}\n" r> n> "\\end{verbatim}") +(verbatimm "\\begin{verbatim*}\n" r> n> "\\end{verbatim*}") + +texinfo-mode + +(defmac "@defmac " p n> r> "@end defmac") +(defun "@defun " p n> r> "@end defun") +(defvar "@defvar " p n> r> "@end defvar") +(example "@example " p n> r> "@end example") +(lisp "@lisp " p n> r> "@end lisp") +(bullet "@itemize @bullet{}" n> r> "@end itemize") +(code "@code{" p "}") +(var "@var{" p "}") + +lisp-mode emacs-lisp-mode ;; Specify multiple modes + +(lambda "(lambda (" p ")" n> r> ")") + +emacs-lisp-mode + +(autoload ";;;###autoload") +(pt "(point)") +(var "(defvar " p "\n \"" p "\")") +(local "(defvar-local " p "\n \"" p "\")") +(const "(defconst " p "\n \"" p "\")") +(custom "(defcustom " p "\n \"" p "\"" n> ":type '" p ")") +(face "(defface " p " '((t :inherit " p "))\n \"" p "\")") +(group "(defgroup " p " nil\n \"" p "\"" n> ":group '" p n> ":prefix \"" p "-\")") +(macro "(defmacro " p " (" p ")\n \"" p "\"" n> r> ")") +(alias "(defalias '" p " '" p ")") +(fun "(defun " p " (" p ")\n \"" p "\"" n> r> ")") +(iflet "(if-let (" p ")" n> r> ")") +(whenlet "(when-let (" p ")" n> r> ")") +(whilelet "(while-let (" p ")" n> r> ")") +(andlet "(and-let* (" p ")" n> r> ")") +(cond "(cond" n "(" q "))" >) +(pcase "(pcase " (p "scrutinee") n "(" q "))" >) +(let "(let (" p ")" n> r> ")") +(lett "(let* (" p ")" n> r> ")") +(pcaselet "(pcase-let (" p ")" n> r> ")") +(pcaselett "(pcase-let* (" p ")" n> r> ")") +(rec "(letrec (" p ")" n> r> ")") +(dotimes "(dotimes (" p ")" n> r> ")") +(dolist "(dolist (" p ")" n> r> ")") +(loop "(cl-loop for " p " in " p " do" n> r> ")") +(command "(defun " p " (" p ")\n \"" p "\"" n> "(interactive" p ")" n> r> ")") +(advice "(defun " (p "adv" name) " (&rest app)" n> p n> "(apply app))" n> + "(advice-add #'" (p "fun") " " (p ":around") " #'" (s name) ")") +(header ";;; " (file-name-nondirectory (or (buffer-file-name) (buffer-name))) + " -- " p " -*- lexical-binding: t -*-" n + ";;; Commentary:" n ";;; Code:" n n) +(provide "(provide '" (file-name-base (or (buffer-file-name) (buffer-name))) ")" n + ";;; " (file-name-nondirectory (or (buffer-file-name) (buffer-name))) + " ends here" n) + +eshell-mode + +(for "for " (p "i") " in " p " { " q " }") +(while "while { " p " } { " q " }") +(until "until { " p " } { " q " }") +(if "if { " p " } { " q " }") +(ife "if { " p " } { " p " } { " q " }") +(unl "unless { " p " } { " q " }") +(unle "unless { " p " } { " p " } { " q " }") + +text-mode + +(box "┌─" (make-string (length str) ?─) "─┐" n + "│ " (s str) " │" n + "└─" (make-string (length str) ?─) "─┘" n) +(abox "+-" (make-string (length str) ?-) "-+" n + "| " (s str) " |" n + "+-" (make-string (length str) ?-) "-+" n) +(cut "--8<---------------cut here---------------start------------->8---" n r n + "--8<---------------cut here---------------end--------------->8---" n) +(rot13 (p "plain text" text) n "----" n (rot13 text)) +(calc (p "taylor(sin(x),x=0,3)" formula) n "----" n (format "%s" (calc-eval formula))) + +rst-mode + +(title (make-string (length title) ?=) n (p "Title: " title) n (make-string (length title) ?=) n) + +java-mode + +(class "public class " (p (file-name-base (or (buffer-file-name) (buffer-name)))) " {" n> r> n "}") + +c-mode :when (re-search-backward "^\\S-*$" (line-beginning-position) 'noerror) + +(inc "#include <" (p (concat (file-name-base (or (buffer-file-name) (buffer-name))) ".h")) ">") +(incc "#include \"" (p (concat (file-name-base (or (buffer-file-name) (buffer-name))) ".h")) "\"") + +org-mode + +(caption "#+caption: ") +(drawer ":" p ":" n r ":end:") +(begin "#+begin_" (s name) n> r> n "#+end_" name) +(quote "#+begin_quote" n> r> n "#+end_quote") +(sidenote "#+begin_sidenote" n> r> n "#+end_sidenote") +(marginnote "#+begin_marginnote" n> r> n "#+end_marginnote") +(example "#+begin_example" n> r> n "#+end_example") +(center "#+begin_center" n> r> n "#+end_center") +(ascii "#+begin_export ascii" n> r> n "#+end_export") +(html "#+begin_export html" n> r> n "#+end_export") +(latex "#+begin_export latex" n> r> n "#+end_export") +(comment "#+begin_comment" n> r> n "#+end_comment") +(verse "#+begin_verse" n> r> n "#+end_verse") +(src "#+begin_src " q n r n "#+end_src") +(gnuplot "#+begin_src gnuplot :var data=" (p "table") " :file " (p "plot.png") n r n "#+end_src" :post (org-edit-src-code)) +(elisp "#+begin_src emacs-lisp" n r n "#+end_src" :post (org-edit-src-code)) +(inlsrc "src_" p "{" q "}") +(title "#+title: " p n "#+author: Daniel Mendler" n "#+language: en") + +;; Local Variables: +;; mode: lisp-data +;; outline-regexp: "[a-z]" +;; End: