emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Michael Brand <michael.ch.brand@gmail.com>
To: Bastien <bzg@gnu.org>
Cc: Org Mode <emacs-orgmode@gnu.org>
Subject: Re: Add the capture feature "%(sexp)" to org-feed
Date: Sat, 11 Aug 2012 17:31:00 +0200	[thread overview]
Message-ID: <CALn3zog7VsfUFQ2LDv5hZLKgyaQ7mPCrN=HznmrypvEaaTp9bQ@mail.gmail.com> (raw)
In-Reply-To: <87a9y3m8ko.fsf@gnu.org>

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

Hi Bastien

On Fri, Aug 10, 2012 at 10:53 AM, Bastien <bzg@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

[-- Attachment #2: 0001-Add-the-capture-feature-sexp-to-org-feed.patch.txt --]
[-- Type: text/plain, Size: 6390 bytes --]

From 142625bad45ca07a185d95caa0d810225e389b95 Mon Sep 17 00:00:00 2001
From: Michael Brand <michael.ch.brand@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	other threads:[~2012-08-11 15:31 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-16 15:53 Add the capture feature "%(sexp)" to org-feed Michael Brand
2012-06-17  2:07 ` Nick Dokos
2012-06-24 17:51   ` Michael Brand
2012-08-07 23:05     ` Bastien
2012-08-09 14:07       ` Michael Brand
2012-08-09 14:53         ` Bastien
2012-08-09 18:00           ` Michael Brand
2012-08-10  8:53             ` Bastien
2012-08-11 15:31               ` Michael Brand [this message]
2012-08-11 16:55                 ` Bastien
2012-08-11 18:11                   ` Michael Brand
2012-08-11 21:59                     ` Bastien
2012-08-12  9:37                       ` Michael Brand
2012-08-12 10:12                         ` Bastien
2012-08-09 21:09           ` Ivan Andrus
2012-08-10  4:48             ` Michael Brand
2012-08-10  7:24               ` Bastien

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='CALn3zog7VsfUFQ2LDv5hZLKgyaQ7mPCrN=HznmrypvEaaTp9bQ@mail.gmail.com' \
    --to=michael.ch.brand@gmail.com \
    --cc=bzg@gnu.org \
    --cc=emacs-orgmode@gnu.org \
    /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).