From: Jason Ross <jasonross1024@gmail.com>
To: Ihor Radchenko <yantar92@gmail.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: Best way to include METAPOST in ConTeXt exporter
Date: Mon, 4 Oct 2021 08:41:03 -0700 [thread overview]
Message-ID: <CABcgBK+RdcGreiPSgcBQ6xEnDmsMACSp3HWj+Zj--07sg4asxg@mail.gmail.com> (raw)
In-Reply-To: <87wnmtb2sb.fsf@localhost>
I had considered using special blocks; they match my mental model the best.
However, they don't provide any support for syntax highlighting or opening
the block in a new major mode buffer. I'm not sure if it's worth giving up
language features in order to use the block that's most intuitive to users.
I'm also considering writing an Org Babel module for METAPOST. This could
allow METAPOST figures to be included with any export backend. However,
if I go this route, there are still some challenges:
1. Getting captions and tags attached to the resulting figures is clumsy.
As far as I know, this could be done with the :post header argument
and a wrapper source block, but this would require boilerplate code
in documents that use this feature
2. I don't know if there's a reasonable way to leverage ConTeXt's native support
for METAPOST this way; if I ask Org Babel to generate an SVG, ConTeXt then
has to parse the SVG and (internally) convert it back into METAPOST to
render in the document. ConTeXt's SVG support (particularly with mathematical
symbols) is missing some features, so this will be a lossy process.
Essentially I'd want the module to return a file most of the time, but
return raw METAPOST (wrapped in some tags) if the ConTeXt backend is used.
Here's a minimal implementation of the source block concept:
# Define a macro to add header arguments UNLESS ConTeXt backend is used
#+MACRO: conditional-header (eval (when (not (eq
org-export-current-backend 'context)) (concat "#+HEADER: :results
file :file " $1)))
# Define a wrapper block to annotate source block outputs with
# caption and name
#+NAME: wrap_metapost
#+BEGIN_SRC emacs-lisp :var data="" :var caption="" :var name=""
(concat
(when (org-string-nw-p name) (format "#+NAME: %s\n" name))
(when (org-string-nw-p caption) (format "#+CAPTION: %s\n" caption))
(if (eq org-export-current-backend 'context)
(format "#+BEGIN_METAPOST \n%s\n#+END_METAPOST" data)
data))
#+END_SRC
# Minimal Org Babel implementation for METAPOST
#+BEGIN_SRC emacs-lisp
(defvar org-babel-default-header-args:metapost
'((:exports . "results"))
"Default arguments to use when evaluating a dot source block.")
(defun org-babel-execute:metapost (body params)
"Execute a block of METAPOST code with org-babel.
This function is called by `org-babel-execute-src-block'."
(if (cdr (assq :file params))
(let* ((out-file (cdr (assq :file params)))
(cmdline (or (cdr (assq :cmdline params))
(format "-T%s" (file-name-extension out-file))))
(cmd (or (cdr (assq :cmd params)) "mpost"))
(coding-system-for-read 'utf-8) ;use utf-8 with sub-processes
(coding-system-for-write 'utf-8)
(in-file (org-babel-temp-file "metapost-")))
(with-temp-file in-file
(insert (org-babel-expand-body:generic body params)))
(org-babel-eval
(concat cmd
" -s 'outputformat=\"svg\"'"
(format " -s 'outputtemplate=\"%s\"'"
(org-babel-process-file-name out-file))
" " (org-babel-process-file-name in-file)) "")
nil)
body))
#+END_SRC
# Example Usage
{{{conditional-header(foo.svg)}}}
#+BEGIN_SRC metapost :results drawer :post
wrap_metapost(name="my-name", caption="my-caption", data=*this*)
beginfig(1);
draw origin--(100,100)--(200,0)--cycle;
endfig;
end;
#+END_SRC
This kind of works: It exports to HTML with a nice SVG figure and sends raw
METAPOST code to the backend, with #+CAPTION and #+NAME information
attached. Also, links to the figures work in the buffer as well as the pdf.
However, there's a lot I don't like about this.
1. No SVG preview in the buffer since the `conditional-header` macro doesn't
get expanded until export time
2. Boilerplate; both the `conditional-header` and `wrap_metapost` definitions
need to be included in the org file
3. Inconvenient to use since I have to add a macro call and a :post argument
with weird syntax to every METAPOST figure, and the way captions and tags
are specified is different.
On Mon, Oct 4, 2021 at 1:39 AM Ihor Radchenko <yantar92@gmail.com> wrote:
>
> Jason Ross <jasonross1024@gmail.com> writes:
>
> > Hello,
> >
> > I'd like to include METAPOST figures in the ConTeXt exporter backend I'm
> > developing. However, I don't know of an idiomatic way to add captions and
> > references for the figures.
>
> You can use affiliated keywords:
>
> (defconst org-element-affiliated-keywords
> '("CAPTION" "DATA" "HEADER" "HEADERS" "LABEL" "NAME" "PLOT" "RESNAME" "RESULT"
> "RESULTS" "SOURCE" "SRCNAME" "TBLNAME")
> "List of affiliated keywords as strings.
> By default, all keywords setting attributes (e.g., \"ATTR_LATEX\")
> are affiliated keywords and need not to be in this list.")
>
> > Currently, I export METAPOST with `#+BEGIN_EXPORT metapost` / `#+END_EXPORT`
> > tags. However, this feature seems to be intended for completely "raw"
> > outputs
> > with no markup or tagging in the resulting export. I'm interested in
> > supporting
> > at least `#+NAME` and `#+CAPTION` keywords for METAPOST figures so that they
> > can be referred to in the Org file and also in the exported pdf.
>
>
>
> > What are some better ways of doing something like this? Source blocks? How
> > would
> > a user expect to use a feature like this?
>
>
> You can use a special block:
> #+caption: Sample caption
> #+attr_context: :field value
> #+begin_metapost
> ...
> #+end_metapost
>
> The parsed representation of this element in exporter will be something like:
>
> (special-block (:type "metapost" :begin 292 :end 382 :contents-begin 364 :contents-end 368 :post-blank 0 :post-affiliated 347 :caption (((#("Sample caption" 0 14 (:parent #4))))) :attr_context (":field value")))
>
>
> Best,
> Ihor
next prev parent reply other threads:[~2021-10-04 15:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-03 17:53 Best way to include METAPOST in ConTeXt exporter Jason Ross
2021-10-04 8:41 ` Ihor Radchenko
2021-10-04 15:41 ` Jason Ross [this message]
2021-10-04 16:46 ` Ihor Radchenko
2021-10-05 14:40 ` Jason Ross
2021-10-05 19:50 ` Jason Ross
2021-10-13 6:51 ` Ihor Radchenko
2021-10-13 6:54 ` Ihor Radchenko
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=CABcgBK+RdcGreiPSgcBQ6xEnDmsMACSp3HWj+Zj--07sg4asxg@mail.gmail.com \
--to=jasonross1024@gmail.com \
--cc=emacs-orgmode@gnu.org \
--cc=yantar92@gmail.com \
/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).