;;; org-tempo.el --- Tempo-style templates for Org -*- lexical-binding: t; -*- ;; Copyright (C) 2017 Free Software Foundation, Inc. ;; ;; Author: Rasmus Pank Roulund ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org ;; ;; This file is part of GNU Emacs. ;; ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; Block and structure templates, to replace the previous Org-specific ;; system. The old function `org-try-structure-completion' is ;; provided as a thin wrapper around `tempo-complete-tag', for ;; backwards compatibility. ;;; Code: (require 'tempo) (require 'cl-lib) (defvar org-tempo-tags nil "Tempo tags for org-mode") (defcustom org-structure-keyword-alist '(("L" . "latex") ("H" . "html") ("A" . "ascii") ("i" . "index")) "Keyword templates expanded using the tempo package." :group 'org-tempo :type '(repeat (cons (string :tag "Key") (string :tag "Template"))) :package-version '(Org . "9.2")) (defun org-tempo-setup () (tempo-use-tag-list 'org-tempo-tags) (setq tempo-match-finder "^ *\\(<[[:word:]]\\)\\=")) (add-hook 'org-mode-hook 'org-tempo-setup) (defun org-tempo-add-templates () "Update all org-tempo templates. Goes through `org-structure-block-alist' and `org-structure-keyword-alist'." (let ((keys (mapcar (apply-partially #'format "<%s") (mapcar #'car (append org-structure-block-alist org-structure-keyword-alist))))) (if (> (length keys) (length (delete-dups keys))) (user-error "Duplicate keys in `org-structure-template-alist' and `org-structure-template-alist-keywords'")) (dolist (key keys) (if (assoc-string key org-tempo-tags) (setq org-tempo-tags (delete (assoc-string key org-tempo-tags) org-tempo-tags)))) (mapc #'org-tempo-add-block org-structure-block-alist) (mapc #'org-tempo-add-keyword org-structure-keyword-alist)) (setq tempo-dirty-collection t)) (defun org-tempo-add-block (entry) "Add block entry from `org-structure-block-alist'." (let* ((key (format "<%s" (car entry))) (name (cdr entry))) (tempo-define-template (format "org-%s" (replace-regexp-in-string " " "-" name)) `(,(format "#+begin_%s " name) p '> n n ,(format "#+end_%s" (car (org-split-string name " "))) >) key (format "Insert a %s block" name) 'org-tempo-tags))) (defun org-tempo-add-keyword (entry) "Add keyword entry from `org-structure-keyword-alist'." (let* ((key (format "<%s" (car entry))) (name (cdr entry))) (tempo-define-template (format "org-%s" (replace-regexp-in-string " " "-" name)) `(,(format "#+%s: " name) p '>) key (format "Insert a %s keyword" name) 'org-tempo-tags))) ;; Additional keywords (tempo-define-template "org-include" '("#+include: " (ignore-errors (format "\"%s\" " (file-relative-name (read-file-name "Include file: ")))) p >) "