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:
parent
fd50740c96
commit
c04e357f3d
99
doc/org.texi
99
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
|
||||
|
|
|
@ -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~
|
||||
|
||||
|
|
130
lisp/org.el
130
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 \"<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)
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue