I've proceeded with my little project using the dynamic block, since it seems that this is what it was designed for. I wrote the following bit of code and would appreciate answers to a couple of questions.
#+begin_src emacs-lisp :results silent
(defun flatten-string-with-links (str)
(let* ((newstr str))
; find [[link][desc]] and replace with 'desc.
(setq newstr (replace-regexp-in-string "\\[\\[[^\\[]+\\]\\[[^//[]+\\]\\]"
(lambda (s) (save-match-data
(nth 2 (split-string s "[\]\[]+")))) newstr))
; find [[link]] and replace with 'link.
(setq newstr (replace-regexp-in-string "\\[\\[[^\\[]+\\]\\]"
(lambda(s) (save-match-data
(nth 1 (split-string s "[\]\[]+")))) newstr))
newstr))
(defun org-dblock-write:tagged (params)
(insert (mapconcat 'identity
(org-map-entries
(lambda()
(let* (link desc innerlink)
(setq desc (nth 4 (org-heading-components)))
(setq desc (flatten-string-with-links desc))
(setq link (concat "file:"
(abbreviate-file-name (buffer-file-name (buffer-base-buffer)))
"::"
(org-make-org-heading-search-string)))
(org-make-link-string link desc)))
(plist-get params :tag)
(plist-get params :scope))
"\n")))
#+end_src
* example :links:
** not a link
#+BEGIN: tagged :tag "links"
#+END
Q1: I've tried to leverage as much built-in org functionality as possible, but deeply suspect that I'm overlooking some, since agendas do much of this work. Is there a simpler solution than mine?
Q2: The link generated for the last item ("broken link") does not work. Removing the "%" from the URL fixes it. This seems to be a bug in org-make-org-heading-search-string? Or am I misusing it?
Any help would be greatly appreciated.