Hi Bastien

On Fri, Aug 10, 2012 at 10:53 AM, Bastien <b...@gnu.org> wrote:
> Please try the attached patch and let me know if it works.

Thank you for making `org-capture-inside-embedded-elisp-p' much
clearer. I was not sure if you really wanted to omit switching to
Emacs Lisp Mode although it is useful for example for “%(length ")")”.
So I attach a new patch where I restored this part, now cleaner too.
Also a small change against your latest patch to not stop at “%”
without following “(” and possibly miss a “%(” before.

I temporarily emptied “:FEEDSTATUS:” in all my feeds and updated them
and also tried some odd artificial examples. All works the same as
with my first patch. Can you please review this new patch compared
against your latest and apply when appropriate?

Michael
From 142625bad45ca07a185d95caa0d810225e389b95 Mon Sep 17 00:00:00 2001
From: Michael Brand <michael.ch.br...@gmail.com>
Date: Sat, 11 Aug 2012 17:26:57 +0200
Subject: [PATCH] Add the capture feature sexp to org feed

* org-feed.el (org-feed-format-entry): Require `org-capture'.
Expand Elisp %(...) templates.
(org-feed-default-template): Update docstring.

* org-capture.el (org-capture-expand-embedded-elisp): New
function.
(org-capture-fill-template): Use it.
(org-capture-inside-embedded-elisp-p): New function to tell if
we are within an Elisp %(...) template.
---
 lisp/org-capture.el |   40 ++++++++++++++++++++++++++++--------
 lisp/org-feed.el    |   56 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 68 insertions(+), 28 deletions(-)

diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 84e5ff6..4a11462 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -1388,15 +1388,7 @@ The template may still contain \"%?\" for cursor 
positioning."
              (error (insert (format "%%![Couldn't insert %s: %s]"
                                     filename error)))))))
       ;; %() embedded elisp
-      (goto-char (point-min))
-      (while (re-search-forward "%\\((.+)\\)" nil t)
-       (unless (org-capture-escaped-%)
-         (goto-char (match-beginning 0))
-         (let ((template-start (point)))
-           (forward-char 1)
-           (let ((result (org-eval (read (current-buffer)))))
-             (delete-region template-start (point))
-             (insert result)))))
+      (org-capture-expand-embedded-elisp)
 
       ;; The current time
       (goto-char (point-min))
@@ -1530,6 +1522,36 @@ The template may still contain \"%?\" for cursor 
positioning."
        t)
     nil))
 
+(defun org-capture-expand-embedded-elisp ()
+  "Evaluate embedded elisp %(sexp) and replace with the result."
+  (goto-char (point-min))
+  (while (re-search-forward "%(" nil t)
+    (unless (org-capture-escaped-%)
+      (goto-char (match-beginning 0))
+      (let ((template-start (point)))
+       (forward-char 1)
+       (let ((result (org-eval (read (current-buffer)))))
+         (delete-region template-start (point))
+         (insert result))))))
+
+(defun org-capture-inside-embedded-elisp-p ()
+  "Return non-nil if point is inside of embedded elisp %(sexp)."
+  (let ((buf (buffer-string)) (p (point)) beg end)
+    (with-temp-buffer   ; to keep major mode and font-lock in original buffer
+      (emacs-lisp-mode) ; to deal with for example %(length ")")
+      (insert buf)
+      (goto-char p)
+      ;; `looking-at' and `search-backward' below do not match the "%(" if
+      ;; point is in its middle
+      (when (equal (char-before) ?%)
+        (backward-char))
+      (save-match-data
+       (when (or (looking-at "%(") (search-backward "%(" nil t))
+         (setq beg (point))
+         (setq end (progn (forward-char) (forward-sexp) (1- (point)))))))
+    (when (and beg end)
+      (and (<= p end) (>= p beg)))))
+
 ;;;###autoload
 (defun org-capture-import-remember-templates ()
   "Set org-capture-templates to be similar to `org-remember-templates'."
diff --git a/lisp/org-feed.el b/lisp/org-feed.el
index 6901ffa..8b3414b 100644
--- a/lisp/org-feed.el
+++ b/lisp/org-feed.el
@@ -225,12 +225,14 @@ Any fields from the feed item can be interpolated into 
the template with
 %name, for example %title, %description, %pubDate etc.  In addition, the
 following special escapes are valid as well:
 
-%h      the title, or the first line of the description
-%t      the date as a stamp, either from <pubDate> (if present), or
-        the current date.
-%T      date and time
-%u,%U   like %t,%T, but inactive time stamps
-%a      A link, from <guid> if that is a permalink, else from <link>"
+%h      The title, or the first line of the description
+%t      The date as a stamp, either from <pubDate> (if present), or
+        the current date
+%T      Date and time
+%u,%U   Like %t,%T, but inactive time stamps
+%a      A link, from <guid> if that is a permalink, else from <link>
+%(sexp) Evaluate elisp `(sexp)' and replace with the result, the simple
+        %-escapes above can be used as arguments, e.g. %(capitalize 
\\\"%h\\\")"
   :group 'org-feed
   :type '(string :tag "Template"))
 
@@ -506,9 +508,10 @@ This will find DRAWER and extract the alist."
 ENTRY is a property list.  This function adds a `:formatted-for-org' property
 and returns the full property list.
 If that property is already present, nothing changes."
+  (require 'org-capture)
   (if formatter
       (funcall formatter entry)
-    (let (dlines fmt tmp indent time name
+    (let (dlines time escape name tmp
                 v-h v-t v-T v-u v-U v-a)
       (setq dlines (org-split-string (or (plist-get entry :description) "???")
                                     "\n")
@@ -527,20 +530,35 @@ If that property is already present, nothing changes."
                  ""))
       (with-temp-buffer
        (insert template)
+
+       ;; Simple %-escapes
+       ;; before embedded elisp to support simple %-escapes as
+       ;; arguments for embedded elisp
        (goto-char (point-min))
        (while (re-search-forward "%\\([a-zA-Z]+\\)" nil t)
-         (setq name (match-string 1))
-         (cond
-          ((member name '("h" "t" "T" "u" "U" "a"))
-           (replace-match (symbol-value (intern (concat "v-" name))) t t))
-          ((setq tmp (plist-get entry (intern (concat ":" name))))
-           (save-excursion
-             (save-match-data
-               (beginning-of-line 1)
-               (when (looking-at (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
-                 (setq tmp (org-feed-make-indented-block
-                            tmp (org-get-indentation))))))
-           (replace-match tmp t t))))
+         (unless (org-capture-escaped-%)
+           (setq name (match-string 1)
+                 escape (org-capture-inside-embedded-elisp-p))
+           (cond
+            ((member name '("h" "t" "T" "u" "U" "a"))
+             (setq tmp (symbol-value (intern (concat "v-" name)))))
+            ((setq tmp (plist-get entry (intern (concat ":" name))))
+             (save-excursion
+               (save-match-data
+                 (beginning-of-line 1)
+                 (when (looking-at
+                        (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
+                   (setq tmp (org-feed-make-indented-block
+                              tmp (org-get-indentation))))))))
+           (when tmp
+             ;; escape string delimiters `"' when inside %() embedded lisp
+             (when escape
+               (setq tmp (replace-regexp-in-string "\"" "\\\\\"" tmp)))
+             (replace-match tmp t t))))
+
+       ;; %() embedded elisp
+       (org-capture-expand-embedded-elisp)
+
        (decode-coding-string
         (buffer-string) (detect-coding-region (point-min) (point-max) t))))))
 
-- 
1.7.4.2

Reply via email to