emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Rasmus <rasmus@gmx.us>
To: mail@nicolasgoaziou.fr
Cc: eric@ericabrahamsen.net, emacs-orgmode@gnu.org
Subject: Re: [patch] structure snippet completions
Date: Tue, 05 Dec 2017 11:22:42 +0100	[thread overview]
Message-ID: <87vahl8oel.fsf@gmx.us> (raw)
In-Reply-To: <87d13u6ws3.fsf@nicolasgoaziou.fr> (Nicolas Goaziou's message of "Mon, 04 Dec 2017 21:55:39 +0100")

[-- Attachment #1: Type: text/plain, Size: 2877 bytes --]

Hi,

Thanks for the comments.  I have attached a new version that addresses the
issues you raised.

I think Org Tempo should pretty much work as this point, but of course
additional testing would be great.  And more cool key expansions of
course.

>> +@vindex org-tempo
>
> Is it worth mentioning the _variable_ `org-tempo'?

No. 

> Also,
>
> @cindex Tempo
> @cindex Template expansion
> @cindex ... whatever ...

Good idea.

>> +@vindex org-tempo-keywords-alist
>
> Is 
>
> @vindex org-structure-template-alist
>
> missing?

Perhaps.  Added.


>> +@code{org-structure-template-alist} and @code{org-tempo-keywords-alist}.  For
>> +example, @code{org-tempo} makes @kbd{<} @kbd{s} @kbd{@key{TAB}}
>> expand to a
>
> For example, Org Tempo makes @kbd(< s @key{TAB}) expand to a code block.

That was taken from an old revision of the manual, but I am happy to use
the more clear form.

>> +@samp{src} code block.  Enable it by customizing @code{org-modules} or add
>> +@code{(require 'org-tempo)} to your Emacs init file@footnote{For more
>> +information, please refer to the commentary section in
>> @code{org-tempo.el}}.
>
> ... @file{org-tempo.el}.}.

So much texinfo syntax...


>> +	(user-error
>> +	 "Duplicated keys in `org-structure-template-alist' and
>> `org-tempo-keywords-alist'"))
>
> Is is an issue?

I guess if "<l" is defined to both make a export latex block and a latex
keyword it’s at least an issue, but I demoted it to a warning, which is
probably more appropriate.


>> +(defun org-tempo-add-keyword (entry)
>> +  "Add keyword entry from `org-tempo-keywords-alist'."
>> +  (let* ((key (format "<%c" (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
>
> Why `ignore-errors'?

In case the file selection is quit.  But I have re-done the include
keyword in a better way.

>> +	      ;; Simple test if `org-tempo-setup' has been run.
>> +	      ;; May not be the case if `org-tempo' was loaded
>> +	      ;; after Org.
>> +	      (unless (cl-member "<I" tempo-collection :key 'car :test 'equal)
>> +		(org-tempo-setup))
>
> (unless (assoc "<I" tempos-collection) (org-tempo-setup))
>
> But wouldn't calling 
>
>   (org-tempo-setup)
>
> at top level in "org-tempo.el" solve the issue?

Good idea.  I call it if we’re in an Org buffer.  Perhaps people use Tempo
in other modes so it would be potentially disruptive to call it in other
modes.

Rasmus

-- 
You people at the NSA are becoming my new best friends!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-tempo.el-New-file-for-expansion-of-templates.patch --]
[-- Type: text/x-patch, Size: 8500 bytes --]

From d645c92381420203d42c0397269122de06ee76d9 Mon Sep 17 00:00:00 2001
From: Rasmus <rasmus@gmx.us>
Date: Thu, 9 Nov 2017 16:47:13 +0100
Subject: [PATCH 1/2] org-tempo.el: New file for expansion of templates

* lisp/org-tempo.el: New file.
* doc/org.texi (Structure templates):
* lisp/org.el (org-modules): Add org-tempo.
---
 doc/org.texi      |  13 +++++
 etc/ORG-NEWS      |   4 +-
 lisp/org-tempo.el | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lisp/org.el       |   1 +
 4 files changed, 181 insertions(+), 1 deletion(-)
 create mode 100644 lisp/org-tempo.el

diff --git a/doc/org.texi b/doc/org.texi
index 5becb0175..e6e6706cb 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -17396,6 +17396,19 @@ the key is @key{TAB}, the user is prompted to enter a type.
 Available structure types are defined in @code{org-structure-template-alist},
 see the docstring for adding or changing values.
 
+@cindex Tempo
+@cindex Template expansion
+@cindex template insertion
+@cindex insertion, of templates
+@vindex org-tempo-keywords-alist
+@vindex org-structure-template-alist
+Org Tempo expands snippets to structures defined in
+@c @code{org-structure-template-alist} and @code{org-tempo-keywords-alist}.  For
+@c example, @code{org-tempo} expands @kbd{< s @key{TAB}} to a code block.
+Enable it by customizing @code{org-modules} or add @code{(require
+'org-tempo)} to your Emacs init file@footnote{For more information, please
+refer to the commentary section in @file{org-tempo.el}.}.
+
 @multitable @columnfractions 0.2 0.8
 @item @kbd{c} @tab @samp{#+BEGIN_CENTER}
 @item @kbd{C} @tab @samp{#+BEGIN_COMMENT}
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 66865ffe1..9d6c91ef3 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -72,6 +72,8 @@ document, use =shrink= value instead, or in addition to align:
 #+END_EXAMPLE
 
 ** New features
+*** ~org-tempo~ may used for snippet expansion of structure template.
+See manual and commentary in ~org-tempo.el~ for details.
 *** Exclude unnumbered headlines from table of contents
 Set their =UNNUMBERED= property to the special =notoc= value.  See
 manual for details.
@@ -167,7 +169,7 @@ See docstring for details.
 ** Removed functions
 
 *** ~org-try-structure-completion~
-
+=org-tempo= may be used as a replacement.
 ** Removed variables
 
 *** org-babel-use-quick-and-dirty-noweb-expansion
diff --git a/lisp/org-tempo.el b/lisp/org-tempo.el
new file mode 100644
index 000000000..6f9af81fc
--- /dev/null
+++ b/lisp/org-tempo.el
@@ -0,0 +1,164 @@
+;;; org-tempo.el --- Template expansion for Org structures -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+;;
+;; Author: Rasmus Pank Roulund <emacs at pank dot eu>
+;; 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 <https://www.gnu.org/licenses/>.
+;;
+;;; 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 "<e" at the beginning of the line will be
+;; expanded to an example block.
+;;
+;; All blocks defined in `org-structure-template-alist' are added as
+;; Org Tempo shortcuts, in addition to keywords defined in
+;; `org-tempo-keywords-alist'.
+;;
+;; `tempo' can also be used to define more sophisticated keywords
+;; completions.  See the section "Additional keywords" below for
+;; additional details.
+;;
+;;; Code:
+
+(require 'tempo)
+(require 'cl-lib)
+
+\f
+(defgroup org-tempo nil
+  "Options for template expansion of Org structures"
+  :tag "Org structure"
+  :group 'org)
+
+(defvar org-tempo-tags nil
+  "Tempo tags for org-mode")
+
+(defcustom org-tempo-keywords-alist
+  '((?L . "latex")
+    (?H . "html")
+    (?A . "ascii")
+    (?i . "index"))
+  "Keyword completion elements.
+
+Like `org-structure-template-alist' this alist of KEY characters
+and KEYWORD.  The tempo snippet \"<KEY\" is expand to the KEYWORD
+value.  
+
+For example \"<l\" at the beginning of a line is expanded to
+#+latex:"
+  :group 'org-tempo
+  :type '(repeat (cons (character :tag "Key")
+		       (string :tag "Keyword")))
+  :package-version '(Org . "9.2"))
+
+
+\f
+;;; Org Tempo functions and setup.
+
+(defun org-tempo-setup ()
+  (org-tempo-add-templates)
+  (tempo-use-tag-list 'org-tempo-tags)
+  (setq-local tempo-match-finder "^ *\\(<[[:word:]]\\)\\="))
+
+(defun org-tempo-add-templates ()
+  "Update all Org Tempo templates.
+
+Goes through `org-structure-template-alist' and
+`org-tempo-keywords-alist'."
+  (let ((keys (mapcar (lambda (pair) (format "<%c" (car pair)))
+		      (append org-structure-template-alist
+			      org-tempo-keywords-alist))))
+    ;; Check for duplicated snippet keys and warn if any are found.
+    (when (> (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.
+    (mapcar (lambda (key)
+	      (if (assoc-string key org-tempo-tags)
+		  (setq org-tempo-tags
+			(delete (assoc-string key org-tempo-tags)
+				org-tempo-tags))))
+	    keys)
+    (mapcar #'org-tempo-add-block org-structure-template-alist)
+    (mapcar #'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 "<%c" (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 (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 "<%c" (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
+
+(defun org-tempo--include-file ()
+  "Ask for file name and take care of quit"
+  (let* ((inhibit-quit t))
+    (unless (with-local-quit
+	      (prog1 t
+		(insert
+		 (format "#+include: \"%s\" " (file-relative-name
+  				    (read-file-name "Include file: "))))))
+      (insert "<I")
+      (setq quit-flag nil))))
+
+(tempo-define-template "org-include"
+		       '((org-tempo--include-file)
+			 p >)
+		       "<I"
+		       "Include keyword"
+		       'org-tempo-tags)
+
+\f
+;;; Setup of Org Tempo
+;;
+;; Org Tempo is set up with each new Org buffer and potentially in the
+;; current Org buffer.
+;;
+;; Tempo templates can only be added after Org is loaded as
+;; `org-structure-template-alist' must be loaded.
+
+(add-hook 'org-mode-hook 'org-tempo-setup)
+(add-hook 'org-tab-before-tab-emulation-hook
+	  'tempo-complete-tag)
+(when (eq major-mode 'org-mode) (org-tempo-setup))
+
+(eval-after-load 'org
+  '(org-tempo-add-templates))
+
+(provide 'org-tempo)
+
+;;; org-tempo.el ends here
diff --git a/lisp/org.el b/lisp/org.el
index 611817b40..47ca283f2 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -706,6 +706,7 @@ For export specific modules, see also `org-export-backends'."
 	(const :tag "   mouse:             Additional mouse support" org-mouse)
 	(const :tag "   protocol:          Intercept calls from emacsclient" org-protocol)
 	(const :tag "   rmail:             Links to RMAIL folders/messages" org-rmail)
+	(const :tag "   tempo:             Fast completion for structures" org-tempo)
 	(const :tag "   w3m:               Special cut/paste from w3m to Org mode." org-w3m)
 
 	(const :tag "C  annotate-file:     Annotate a file with org syntax" org-annotate-file)
-- 
2.15.1


  reply	other threads:[~2017-12-05 10:23 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-04 16:22 [patch] structure snippet completions Rasmus
2017-12-04 20:55 ` Nicolas Goaziou
2017-12-05 10:22   ` Rasmus [this message]
2017-12-05 20:29     ` Nicolas Goaziou
2017-12-07 23:37       ` Rasmus
2017-12-07 23:49         ` Rasmus
2017-12-08  2:38           ` Kaushal Modi
2017-12-08 20:16             ` Rasmus
2017-12-08 21:07         ` Berry, Charles
2017-12-08 21:20           ` Rasmus
2017-12-09 13:42             ` numbchild
2017-12-09 16:22               ` Rasmus
2017-12-09 17:23             ` Berry, Charles
2017-12-10 11:09               ` Rasmus
2017-12-04 21:37 ` Eric Abrahamsen
2017-12-05 10:24   ` Rasmus
2017-12-05 19:14     ` Eric Abrahamsen
  -- strict thread matches above, loose matches on Subject: below --
2017-12-04 16:20 Rasmus

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87vahl8oel.fsf@gmx.us \
    --to=rasmus@gmx.us \
    --cc=emacs-orgmode@gnu.org \
    --cc=eric@ericabrahamsen.net \
    --cc=mail@nicolasgoaziou.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).