;;; org-tempo.el --- Template expansion for Org structures -*- lexical-binding: t; -*- ;; Copyright (C) 2017-2024 Free Software Foundation, Inc. ;; ;; Author: Rasmus Pank Roulund ;; Keywords: outlines, hypermedia, calendar, wp ;; URL: https://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: ;; ;; Org Tempo reimplements completions of structure template before ;; point like `org-try-structure-completion' in Org v9.1 and earlier. ;; For example, strings like " (length keys) (length (delete-dups keys))) (warn "Duplicated keys in `org-structure-template-alist' and `org-tempo-keywords-alist'")) ;; Remove any keys already defined in case they have been updated. (setq org-tempo-tags (cl-remove-if (lambda (tag) (member (car tag) keys)) org-tempo-tags)) (mapc #'org-tempo-add-block org-structure-template-alist) (mapc #'org-tempo-add-keyword org-tempo-keywords-alist))) (defun org-tempo-add-block (entry) "Add block entry from `org-structure-template-alist'." (let* ((key (format "<%s" (car entry))) (name (cdr entry)) (special (member name '("src" "export"))) (upcase? (string= (car (split-string name)) (upcase (car (split-string name)))))) (tempo-define-template (format "org-%s" (replace-regexp-in-string " " "-" name)) `(,(format "#+%s_%s%s" (if upcase? "BEGIN" "begin") name (if special " " "")) ,(when special 'p) '> n ,(unless special 'p) n ,(format "#+%s_%s" (if upcase? "END" "end") (car (split-string name " "))) >) key (format "Insert a %s block" name) 'org-tempo-tags))) (defun org-tempo-add-keyword (entry) "Add keyword entry from `org-tempo-keywords-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))) (defun org-tempo-complete-tag (&rest _) "Look for a tag and expand it silently. Unlike to `tempo-complete-tag', do not give a signal if a partial completion or no match at all is found. Return nil if expansion didn't succeed." (org-tempo--update-maybe) ;; `tempo-complete-tag' returns its SILENT argument when there is no ;; completion available at all. (not (eq 'fail (tempo-complete-tag 'fail)))) ;;; Additional keywords (defun org-tempo--include-file () "Add #+include: and a file name." (let ((inhibit-quit t)) (unless (with-local-quit (prog1 t (insert (format "#+include: %S " (file-relative-name (read-file-name "Include file: ")))))) (insert ") "