From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id +qH0IOIgW2EyhgAAgWs5BA (envelope-from ) for ; Mon, 04 Oct 2021 17:42:26 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id EBrsG+IgW2FhQAAAB5/wlQ (envelope-from ) for ; Mon, 04 Oct 2021 15:42:26 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 9B136339A7 for ; Mon, 4 Oct 2021 17:42:25 +0200 (CEST) Received: from localhost ([::1]:45752 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mXQ6i-0004PV-Eo for larch@yhetil.org; Mon, 04 Oct 2021 11:42:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43260) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mXQ5g-0004PL-Qc for emacs-orgmode@gnu.org; Mon, 04 Oct 2021 11:41:20 -0400 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]:43783) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mXQ5c-0004fm-Uu for emacs-orgmode@gnu.org; Mon, 04 Oct 2021 11:41:20 -0400 Received: by mail-lf1-x136.google.com with SMTP id e15so73435293lfr.10 for ; Mon, 04 Oct 2021 08:41:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=pkCyxq6gsyvttBGC2RmGoLIxVbJ8mKZNFmNNHTC1kUg=; b=H9vUz3PaJAS3UDe8siglVDchswsBsUgbRTuHeoKPmPs5dzzbibxnmT7xB00lfiLb2y o6wLgD/7aq8xakHIyoIXjWyg3gtR+d9+qG0YzFfv29C7oCKAiwfAaowlVx9RWKD1T3Fy CHXE9p41KvrR8zsAIfYiR9hshFz6hxNDK9z7dHANXZ/mdsmbwJGb9Iax7MzC6XdzZT0A vfPTzlPFa/qDWTi2oXUXNdX8Fag3IwMAmOZaOVeXhlZQ0U7vHDK5Saf+3ggHzQctWFSX sjGcM2zqC8sNgvO+Iglk7501VbzS8nGeis0owgNtktL3MAj7GiLiAq4MX2W3p3GU0Mse C6pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=pkCyxq6gsyvttBGC2RmGoLIxVbJ8mKZNFmNNHTC1kUg=; b=xRuhxoH40688mNQhY3XkIcC+VIfuWBlZyoq977Ne8/CYTEuhMsfjpXI/jJybdbXMdc cE4Q6aEEJt4RTfenD2wNLDQxJc34AmTyZd2fwoeksf+wPRL5zyOdj0tTGAHK8HwqflN6 5q7x1t8UAqkr5A5ybz8MiLiqaJIPgraZO9GnXS+/HwlZ/lAGzGBCCEzH3qe+iq6explD 7TilbKlqCPbRUwSKZMLEl2bPn8o/Y9i5BBAtkNNGsNNSE6ZP/HViTDmRYQspoV/TYbfQ h9NrYzNFJAu969DLZGi2P0N/c24dyjWaN2QDi/sMEnXzIY6acnklYKoLHy11oinUFzVv nrdQ== X-Gm-Message-State: AOAM532a7Sc4S0xkyDv7MpOjcPrDFZ0ikOOHEEshmfvD7s7c7a1I5H6N jbz4Yj0X8HU2QNO0nds8EdPpBssN50uZk78s27U= X-Google-Smtp-Source: ABdhPJwqEisGZBkv4PoldDuekofgrCAx38jo+6vAsHfQmyg8jQpNfj3wY9zRB8IdAZ+nIYnN4zDUhfYs2FSa/GSY4HM= X-Received: by 2002:a2e:534a:: with SMTP id t10mr17046043ljd.407.1633362074989; Mon, 04 Oct 2021 08:41:14 -0700 (PDT) MIME-Version: 1.0 References: <87wnmtb2sb.fsf@localhost> In-Reply-To: <87wnmtb2sb.fsf@localhost> From: Jason Ross Date: Mon, 4 Oct 2021 08:41:03 -0700 Message-ID: Subject: Re: Best way to include METAPOST in ConTeXt exporter To: Ihor Radchenko Content-Type: text/plain; charset="UTF-8" Received-SPF: pass client-ip=2a00:1450:4864:20::136; envelope-from=jasonross1024@gmail.com; helo=mail-lf1-x136.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: emacs-orgmode@gnu.org Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1633362146; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=pkCyxq6gsyvttBGC2RmGoLIxVbJ8mKZNFmNNHTC1kUg=; b=hhGh2AlHcVKoOtApW2aQTr9kZZehrXj01PCcEY6WJIa4Q+wP2zPePl50NC4o7XHhZt/c/B sSwq4rB69fRbKuT66aYy176mWJPc2Ha0Cl1YziZFgWcpFlZ6MwlL+pNdSkq5t9exkMsZgF e8jm+X1ogrAyX60lXexYeUVWoM/wZQqZp1/HmtOLk6Y3TQXMD0L3OPEyazEPRZvlBR5oh8 18iFcwFu5aOcgLSPF76PTHYV+K2qt7NrKaG6JAhG/ZTziEWlm1EfkrZNxHe25htUWvd86m XC3D/WrQ9XHpsfHiexyrOWay69NLPf+4h01nkDt4uZiIHdMgQVlwgX0Wf4B++A== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1633362146; a=rsa-sha256; cv=none; b=oij/1RfDDWdAP3G2qfXprQh2nvnppHSZn3GzONiN3zIPw9B6Sq2Yoe638csNgiTKDajyIU QaAIcuFeGH29Z/6I4tjvpFt0+gcpgcFOkKuNpdRTGeBDHaX1QxVa4Cd5NyVjyWWLhnWOLw 0aVQ8UXYTCNdL3KAqEL5tMEdwfa1EvHrNb34IW0l5UckZH3oe8iz56esjJ5mfinKm8t4Jc m3QB/dkOiGM301t1Sc6rozEz7pmLxXVzwb6MfodUT7JtTcP/L7jYYkoVKipf7Sr2znvhSv srYURFh9B0g99pJ03Yide0NfUxH8NRn2bEW8dRNbt48iKAhxmPb73BHgU6V/Eg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=H9vUz3Pa; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Spam-Score: -3.11 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=H9vUz3Pa; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Queue-Id: 9B136339A7 X-Spam-Score: -3.11 X-Migadu-Scanner: scn0.migadu.com X-TUID: DVfLQM+Gtm1A 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 wrote: > > Jason Ross 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