From c04e357f3d5d93484277a7e439847b1233b872bd Mon Sep 17 00:00:00 2001 From: Eric Abrahamsen Date: Sun, 5 Nov 2017 09:25:15 +0100 Subject: [PATCH] Replace easy templates with org-insert-structure-template * lisp/org.el (org-insert-structure-template): New function for wrapping region (or element at point) in a begin/end block. (org-structure-predefined-blocks): New option holding predefined blocks, for completion. (org-try-structure-completion, org-complete-expand-structure-template): Remove functions. * doc/org.texi (Inserting structure templates): Document. * testing/lisp/test-org.el (test-org/insert-template): New test. --- doc/org.texi | 99 ++++++++++++++--------------- etc/ORG-NEWS | 4 ++ lisp/org.el | 130 +++++++++++++++++++-------------------- testing/lisp/test-org.el | 45 ++++++++++++++ 4 files changed, 156 insertions(+), 122 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 77da6d335..e116a9b1e 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -749,7 +749,7 @@ Specific header arguments Miscellaneous * Completion:: M-TAB guesses completions -* Easy templates:: Quick insertion of structural elements +* Structure templates:: Quick insertion of structural elements * Speed keys:: Electric commands at the beginning of a headline * Code evaluation security:: Org mode files evaluate inline code * Customization:: Adapting Org to changing tastes @@ -10108,18 +10108,16 @@ look like the fontified Emacs buffer@footnote{This works automatically for the HTML back-end (it requires version 1.34 of the @file{htmlize.el} package, which you need to install). Fontified code chunks in @LaTeX{} can be achieved using either the -@url{https://www.ctan.org/tex-archive/macros/latex/contrib/listings/?lang=en, listings,} -or the -@url{https://github.com/gpoore/minted, minted,} package. +@url{https://www.ctan.org/tex-archive/macros/latex/contrib/listings/?lang=en, +listings,} or the @url{https://github.com/gpoore/minted, minted,} package. If you use minted or listing, you must load the packages manually, for -example by adding the desired package to -@code{org-latex-packages-alist}. Refer to @code{org-latex-listings} -for details.}. This is done with the @samp{src} block, where you also need -to specify the name of the major mode that should be used to fontify the -example@footnote{Code in @samp{src} blocks may also be evaluated either -interactively or on export. @xref{Working with source code}, for more -information on evaluating code blocks.}, see @ref{Easy templates} for -shortcuts to easily insert code blocks. +example by adding the desired package to @code{org-latex-packages-alist}. +Refer to @code{org-latex-listings} for details.}. This is done with the +@samp{src} block, where you also need to specify the name of the major mode +that should be used to fontify the example@footnote{Code in @samp{src} blocks +may also be evaluated either interactively or on export. @xref{Working with +source code}, for more information on evaluating code blocks.}, see +@ref{Structure templates} for shortcuts to easily insert code blocks. @cindex #+BEGIN_SRC @example @@ -10185,9 +10183,8 @@ If the syntax for the label format conflicts with the language syntax, use a HTML export also allows examples to be published as text areas (@pxref{Text areas in HTML export}). -Because the @code{#+BEGIN_...} and @code{#+END_...} patterns need to be added -so often, shortcuts are provided using the Easy templates facility -(@pxref{Easy templates}). +Because the @code{#+BEGIN_...} @dots{} @code{#+END_...} patterns need to be +added so often, a shortcut is provided (@pxref{Structure templates}). @table @kbd @kindex C-c ' @@ -15243,12 +15240,12 @@ A @samp{src} block conforms to this structure: #+END_SRC @end example -Org mode's templates system (@pxref{Easy templates}) speeds up creating -@samp{src} code blocks with just three keystrokes. Do not be put-off by -having to remember the source block syntax. Org also works with other -completion systems in Emacs, some of which predate Org and have custom -domain-specific languages for defining templates. Regular use of templates -reduces errors, increases accuracy, and maintains consistency. +Do not be put-off by having to remember the source block syntax. Org mode +offers a command for wrapping existing text in a block (@pxref{Structure +templates}). Org also works with other completion systems in Emacs, some of +which predate Org and have custom domain-specific languages for defining +templates. Regular use of templates reduces errors, increases accuracy, and +maintains consistency. @cindex source code, inline An inline code block conforms to this structure: @@ -17299,7 +17296,7 @@ emacs -Q --batch --eval " @menu * Completion:: M-TAB guesses completions -* Easy templates:: Quick insertion of structural elements +* Structure templates:: Quick insertion of structural elements * Speed keys:: Electric commands at the beginning of a headline * Code evaluation security:: Org mode files evaluate inline code * Customization:: Adapting Org to changing tastes @@ -17374,46 +17371,40 @@ If your desktop intercepts the combo @kbd{M-@key{TAB}} to switch windows, use environment. @end table -@node Easy templates -@section Easy templates +@node Structure templates +@section Structure templates @cindex template insertion @cindex insertion, of templates -With just a few keystrokes, Org's easy templates inserts empty pairs of -structural elements, such as @code{#+BEGIN_SRC} and @code{#+END_SRC}. Easy -templates use an expansion mechanism, which is native to Org, in a process -similar to @file{yasnippet} and other Emacs template expansion packages. +With just a few keystrokes, it is possible to insert empty structural blocks, +such as @samp{#+BEGIN_SRC} @dots{} @samp{#+END_SRC}, or to wrap existing text +in such a block. -@kbd{<} @kbd{s} @kbd{@key{TAB}} expands to a @samp{src} code block. +@table @kbd +@orgcmd{C-c C-x w,org-insert-structure-template} +Prompt for a type of block structure, and insert the block at point. If the +region is active, it is wrapped in the block. First prompts the user for +a key, which is used to look up a structure type from the values below. If +the key is @key{TAB}, the user is prompted to enter a type. +@end table -@kbd{<} @kbd{l} @kbd{@key{TAB}} expands to: +@vindex org-structure-template-alist +Available structure types are defined in @code{org-structure-template-alist}, +see the docstring for adding or changing values. -#+BEGIN_EXPORT latex - -#+END_EXPORT - -Org comes with these pre-defined easy templates: - -@multitable @columnfractions 0.1 0.9 -@item @kbd{s} @tab @code{#+BEGIN_SRC ... #+END_SRC} -@item @kbd{e} @tab @code{#+BEGIN_EXAMPLE ... #+END_EXAMPLE} -@item @kbd{q} @tab @code{#+BEGIN_QUOTE ... #+END_QUOTE} -@item @kbd{v} @tab @code{#+BEGIN_VERSE ... #+END_VERSE} -@item @kbd{c} @tab @code{#+BEGIN_CENTER ... #+END_CENTER} -@item @kbd{C} @tab @code{#+BEGIN_COMMENT ... #+END_COMMENT} -@item @kbd{l} @tab @code{#+BEGIN_EXPORT latex ... #+END_EXPORT} -@item @kbd{L} @tab @code{#+LATEX:} -@item @kbd{h} @tab @code{#+BEGIN_EXPORT html ... #+END_EXPORT} -@item @kbd{H} @tab @code{#+HTML:} -@item @kbd{a} @tab @code{#+BEGIN_EXPORT ascii ... #+END_EXPORT} -@item @kbd{A} @tab @code{#+ASCII:} -@item @kbd{i} @tab @code{#+INDEX:} line -@item @kbd{I} @tab @code{#+INCLUDE:} line +@multitable @columnfractions 0.2 0.8 +@item @kbd{c} @tab @samp{#+BEGIN_CENTER} +@item @kbd{C} @tab @samp{#+BEGIN_COMMENT} +@item @kbd{e} @tab @samp{#+BEGIN_EXAMPLE} +@item @kbd{E} @tab @samp{#+BEGIN_EXPORT} +@item @kbd{a} @tab @samp{#+BEGIN_EXPORT ascii} +@item @kbd{h} @tab @samp{#+BEGIN_EXPORT html} +@item @kbd{l} @tab @samp{#+BEGIN_EXPORT latex} +@item @kbd{s} @tab @samp{#+BEGIN_SRC} +@item @kbd{q} @tab @samp{#+BEGIN_QUOTE} +@item @kbd{v} @tab @samp{#+BEGIN_VERSE} @end multitable -More templates can added by customizing the variable -@code{org-structure-template-alist}, whose docstring has additional details. - @node Speed keys @section Speed keys @cindex speed keys diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 391ef94ac..97ccf884b 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -149,6 +149,10 @@ you should expect to see something like: #+END_EXAMPLE ** New functions +*** ~org-insert-structure-template~ + +This function can be used to wrap existing text of Org elements in +a #+BEGIN_FOO/#+END_FOO block. Bound to C-c C-x w by default. *** ~org-export-excluded-from-toc-p~ diff --git a/lisp/org.el b/lisp/org.el index 78a0b47c0..f873f1021 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -6740,8 +6740,6 @@ Use `\\[org-edit-special]' to edit table.el tables")) ((run-hook-with-args-until-success 'org-tab-after-check-for-cycling-hook)) - ((org-try-structure-completion)) - ((run-hook-with-args-until-success 'org-tab-before-tab-emulation-hook)) @@ -11859,76 +11857,71 @@ keywords relative to each registered export back-end." "TITLE:" "TODO:" "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:")) (defcustom org-structure-template-alist - '(("s" "#+BEGIN_SRC ?\n\n#+END_SRC") - ("e" "#+BEGIN_EXAMPLE\n?\n#+END_EXAMPLE") - ("q" "#+BEGIN_QUOTE\n?\n#+END_QUOTE") - ("v" "#+BEGIN_VERSE\n?\n#+END_VERSE") - ("V" "#+BEGIN_VERBATIM\n?\n#+END_VERBATIM") - ("c" "#+BEGIN_CENTER\n?\n#+END_CENTER") - ("C" "#+BEGIN_COMMENT\n?\n#+END_COMMENT") - ("l" "#+BEGIN_EXPORT latex\n?\n#+END_EXPORT") - ("L" "#+LaTeX: ") - ("h" "#+BEGIN_EXPORT html\n?\n#+END_EXPORT") - ("H" "#+HTML: ") - ("a" "#+BEGIN_EXPORT ascii\n?\n#+END_EXPORT") - ("A" "#+ASCII: ") - ("i" "#+INDEX: ?") - ("I" "#+INCLUDE: %file ?")) + '((?a . "export ascii") + (?c . "center") + (?C . "comment") + (?e . "example") + (?E . "export") + (?h . "export html") + (?l . "export latex") + (?q . "quote") + (?s . "src") + (?v . "verse")) "Structure completion elements. -This is a list of abbreviation keys and values. The value gets inserted -if you type `<' followed by the key and then press the completion key, -usually `TAB'. %file will be replaced by a file name after prompting -for the file using completion. The cursor will be placed at the position -of the `?' in the template. -There are two templates for each key, the first uses the original Org syntax, -the second uses Emacs Muse-like syntax tags. These Muse-like tags become -the default when the /org-mtags.el/ module has been loaded. See also the -variable `org-mtags-prefer-muse-templates'." +This is an alist of characters and values. When +`org-insert-structure-template' is called, an additional key is +read. The key is first looked up in this alist, and the +corresponding structure is inserted, with \"#+BEGIN_\" and +\"#+END_\" added automatically." :group 'org-completion :type '(repeat - (list - (string :tag "Key") - (string :tag "Template"))) - :version "26.1" - :package-version '(Org . "8.3")) + (cons (character :tag "Key") + (string :tag "Template"))) + :package-version '(Org . "9.2")) -(defun org-try-structure-completion () - "Try to complete a structure template before point. -This looks for strings like \", prompt the +user for a string to use. With an active region, wrap the region +in the block. Otherwise, insert an empty block." + (interactive + (list + (let* ((key (read-key "Key: ")) + (struct-string + (or (cdr (assq key org-structure-template-alist)) + (and (= key ?\t) + (read-string "Structure type: ")) + (user-error "`%c' has no structure definition" key)))) + struct-string))) + (let* ((region? (use-region-p)) + (s (if region? (region-beginning) (point))) + (e (copy-marker (if region? (region-end) (point)) t)) + column) + (when (string-match-p + (concat "\\`" (regexp-opt '("example" "export" "src"))) + type) + (org-escape-code-in-region s e)) + (goto-char s) + (setq column (current-indentation)) + (beginning-of-line) + (indent-to column) + (insert (format "#+begin_%s\n" type)) + (goto-char e) + (if (bolp) + (progn + (skip-chars-backward " \n\t") + (forward-line)) + (end-of-line) + (insert "\n")) + (indent-to column) + (insert (format "#+end_%s\n" + (car (split-string type)))) + (when (or (not region?) + (string-match-p "src\\|\\`export\\'" type)) + (goto-char s) + (end-of-line)) + (set-marker e nil))) ;;;; TODO, DEADLINE, Comments @@ -19393,6 +19386,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command names." (org-defkey org-mode-map "\C-c\C-xE" 'org-inc-effort) (org-defkey org-mode-map "\C-c\C-xo" 'org-toggle-ordered-property) (org-defkey org-mode-map "\C-c\C-xi" 'org-columns-insert-dblock) +(org-defkey org-mode-map "\C-c\C-xw" 'org-insert-structure-template) (org-defkey org-mode-map [(control ?c) (control ?x) ?\;] 'org-timer-set-timer) (org-defkey org-mode-map "\C-c\C-x." 'org-timer) diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 379ded672..4a307ef14 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -4000,6 +4000,51 @@ Text. (org-next-block 1 nil "^[ \t]*#\\+BEGIN_QUOTE") (looking-at "#\\+begin_quote"))))) +(ert-deftest test-org/insert-template () + "Test `org-insert-structure-template'." + ;; Test in empty buffer. + (should + (string= "#+begin_foo\n#+end_foo\n" + (org-test-with-temp-text "" + (org-insert-structure-template "foo") + (buffer-string)))) + ;; Test with multiple lines in buffer. + (should + (string= "#+begin_foo\nI'm a paragraph\n#+end_foo\n\nI'm a second paragraph" + (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragraph" + (org-mark-element) + (org-insert-structure-template "foo") + (buffer-string)))) + ;; Test with text in buffer, no region, no final newline. + (should + (string= "#+begin_foo\nI'm a paragraph.\n#+end_foo\n" + (org-test-with-temp-text "I'm a paragraph." + (org-mark-element) + (org-insert-structure-template "foo") + (buffer-string)))) + ;; Test with text in buffer and region set. + (should + (string= "#+begin_foo\nI'm a paragraph\n\nI'm a second paragrah\n#+end_foo\n" + (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragrah" + (set-mark (point)) + (goto-char (point-max)) + (org-insert-structure-template "foo") + (buffer-string)))) + ;; Test with example escaping. + (should + (string= "#+begin_example\n,* Heading\n#+end_example\n" + (org-test-with-temp-text "* Heading" + (org-mark-element) + (org-insert-structure-template "example") + (buffer-string)))) + ;; Test with indentation. + (should + (string= " #+begin_foo\n This is a paragraph\n #+end_foo\n" + (org-test-with-temp-text " This is a paragraph" + (org-mark-element) + (org-insert-structure-template "foo") + (buffer-string))))) + (ert-deftest test-org/previous-block () "Test `org-previous-block' specifications." ;; Regular test.