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.
This commit is contained in:
Eric Abrahamsen 2017-11-05 09:25:15 +01:00 committed by Nicolas Goaziou
parent fd50740c96
commit c04e357f3d
4 changed files with 156 additions and 122 deletions

View File

@ -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

View File

@ -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~

View File

@ -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 \"<e\" on an otherwise empty line and
expands them."
(let ((l (buffer-substring (point-at-bol) (point)))
a)
(when (and (looking-at "[ \t]*$")
(string-match "^[ \t]*<\\([a-zA-Z]+\\)$" l)
(setq a (assoc (match-string 1 l) org-structure-template-alist)))
(org-complete-expand-structure-template (+ -1 (point-at-bol)
(match-beginning 1)) a)
t)))
(defun org-complete-expand-structure-template (start cell)
"Expand a structure template."
(let ((rpl (nth 1 cell))
(ind ""))
(delete-region start (point))
(when (string-match "\\`[ \t]*#\\+" rpl)
(cond
((bolp))
((not (string-match "\\S-" (buffer-substring (point-at-bol) (point))))
(setq ind (buffer-substring (point-at-bol) (point))))
(t (newline))))
(setq start (point))
(when (string-match "%file" rpl)
(setq rpl (replace-match
(concat
"\""
(save-match-data
(abbreviate-file-name (read-file-name "Include file: ")))
"\"")
t t rpl)))
(setq rpl (mapconcat 'identity (split-string rpl "\n")
(concat "\n" ind)))
(insert rpl)
(when (re-search-backward "\\?" start t) (delete-char 1))))
(defun org-insert-structure-template (type)
"Insert a block structure of the type #+begin_foo/#+end_foo.
First read a character, which can be one of the keys in
`org-structure-template-alist'. When it is <TAB>, 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)

View File

@ -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.