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 ms11 with LMTPS id vmBaC+h1kl5ZHwAA0tVLHw (envelope-from ) for ; Sun, 12 Apr 2020 01:59:04 +0000 Received: from aspmx2.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id uF9XBOp1kl6zHwAAB5/wlQ (envelope-from ) for ; Sun, 12 Apr 2020 01:59:06 +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 aspmx2.migadu.com (Postfix) with ESMTPS id 3DC4F682D59 for ; Sun, 12 Apr 2020 01:59:03 +0000 (UTC) Received: from localhost ([::1]:58006 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jNRtl-0000JU-M9 for larch@yhetil.org; Sat, 11 Apr 2020 21:59:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45829) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jNRtF-0000JA-Gx for emacs-orgmode@gnu.org; Sat, 11 Apr 2020 21:58:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jNRtD-0005TV-KN for emacs-orgmode@gnu.org; Sat, 11 Apr 2020 21:58:29 -0400 Received: from mail-qk1-x732.google.com ([2607:f8b0:4864:20::732]:38755) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1jNRtD-0005TN-CU for emacs-orgmode@gnu.org; Sat, 11 Apr 2020 21:58:27 -0400 Received: by mail-qk1-x732.google.com with SMTP id h14so6233398qke.5 for ; Sat, 11 Apr 2020 18:58:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=5X2H5GxxH7kGJZJR2KkM0RaUk/LR+fS0fdwc58aDXOE=; b=jR0mMId4/YTj8FXHOKNfETmFvC4EQ03CCmx+KDfTknzLJiMcOLZLQoTk6DHB/ptMfK am0QLswT/68MnHvR49CcFDUF43ihXUtXD+ktJYdAwUfOP17Ne/UJRDKVO7Voj4Qe/Gca 76uhQr83g8R+uKsGcCJeFyQm9UI+HukPFtQNEbteo2zH7eM8OgvHMI1pe+pUoWrTaCgx 1LogelKJxDUUgZyKa42VdHyyZGSfhUAW/Z7lKEvSXZmgf/8E3mITLtBmZ8gLvvYOeU2n hJ5iomVr+sBYeDzN80bNwBhVgIm0VXRQqmbSVu0fX/3qTnx1DY9O1770jpALxA2Brs7s iVFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=5X2H5GxxH7kGJZJR2KkM0RaUk/LR+fS0fdwc58aDXOE=; b=gdAzLeJJ4GDEPFpS2WWaCptWet5NpOQ1xiU7vpng66RkQ2e1LqPW2gD4G/rcdmbD/z IFhDWYsHbW919/2YBfH/6KqV4v5LNGznOE5vrxx63p2AVh1DQb8vFSGTs9Xlw7Mn8Cr8 i1LEoUSMBLa53DYeKzcr3+C4ZBXqQ0r0cQZ45X6dMgIn14k4HloJmsZfUH4F1mTwRysl PmO+N6cBHeZutGWQfDDlLBFtHiB+LWJUe4LcSjMLULz9vZCLwhO2xK6B8TSZKyH0JAIo jX9lu62uHQLIPV/FMIZxMtrxZ4FkRhISP1sy6WIYqs1heDASNv/+6PDHYoI3TySQLV0e EE7Q== X-Gm-Message-State: AGi0PuZKJwxGqFVIl3i+aib720XI3kE5d2J4n2K4qE6XSYt0vPlDkJJR IJIwASVITB3sXqnZMTXpjH2LaeJm7aacU+ZkTmhlkbU6oxc= X-Google-Smtp-Source: APiQypJx6/CE73jbeGRV4gLp/yCOL6r3mOhBrDiWCzVNNxqg7NoD+PHKMFLwGxakWUGiGFLq1FxrajKrzuKV+oMkkBs= X-Received: by 2002:a37:d0c:: with SMTP id 12mr10315529qkn.361.1586656706484; Sat, 11 Apr 2020 18:58:26 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Salomon Turgman Date: Sat, 11 Apr 2020 21:58:00 -0400 Message-ID: Subject: Re: How to add new type of block to a derived back-end? To: "Berry, Charles" Content-Type: multipart/alternative; boundary="0000000000005eddd905a30e4df6" X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::732 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: org mode Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Scanner: scn0 X-Spam-Score: -0.71 Authentication-Results: aspmx2.migadu.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=jR0mMId4; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx2.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-Scan-Result: default: False [-0.71 / 13.00]; GENERIC_REPUTATION(0.00)[-0.57957952151778]; R_SPF_ALLOW(-0.20)[+ip4:209.51.188.0/24:c]; FREEMAIL_FROM(0.00)[gmail.com]; IP_REPUTATION_HAM(0.00)[asn: 22989(0.29), country: US(-0.01), ip: 209.51.188.17(-0.58)]; TO_DN_ALL(0.00)[]; DKIM_TRACE(0.00)[gmail.com:+]; RCPT_COUNT_TWO(0.00)[2]; DMARC_POLICY_ALLOW(-0.50)[gmail.com,none]; MX_GOOD(-0.50)[cached: eggs.gnu.org]; MAILLIST(-0.20)[mailman]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:~]; ASN(0.00)[asn:22989, ipnet:209.51.188.0/24, country:US]; SUBJECT_ENDS_QUESTION(1.00)[]; TAGGED_FROM(0.00)[larch=yhetil.org]; ARC_NA(0.00)[]; R_DKIM_ALLOW(-0.20)[gmail.com:s=20161025]; RCVD_COUNT_FIVE(0.00)[6]; FROM_HAS_DN(0.00)[]; FROM_NEQ_ENVFROM(0.00)[sturgman@gmail.com,emacs-orgmode-bounces@gnu.org]; MIME_GOOD(-0.10)[multipart/alternative,text/plain]; PREVIOUSLY_DELIVERED(0.00)[emacs-orgmode@gnu.org]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[] X-TUID: yUZ3DpXAFoYp --0000000000005eddd905a30e4df6 Content-Type: text/plain; charset="UTF-8" Ok... just reporting back my progress in case it helps someone else. Bur first, all the stuff that you can do with src blocks is stuff I never imagined. Seems like the possibilities are endless. Here is what I did so far: #+NAME: simulation #+HEADER: :var cap="DEFAULTCAPTION" :cache yes :eval no-export :var altimage="1_image.svg#img1" #+BEGIN_SRC emacs-lisp :var divid="defid" :var num=1 :results html :exports results (format "
Simulation %s: %s
" num cap divid altimage (capitalize divid) divid) #+END_SRC That is my "definition"... I call it like this: #+CALL: simulation(cap="Manual control of tank level", num=1, divid="main1", altimage="1_manual_noscript.svg") And it seems to work beautifully. Still need to figure out the counting of the number of simulations per page... but that should be trivial at this point. Thank you so much for all the pointers. -s- On Fri, Apr 10, 2020 at 1:14 PM Salomon Turgman wrote: > Thank you very much. I will explore what you suggest. I'm glad I emailed, > seems like I was going down the wrong path. > > Salomon > > On Fri, Apr 10, 2020, 1:10 PM Berry, Charles > wrote: > >> Salomon, see inline comments below. >> >> HTH, >> >> Chuck >> >> > On Apr 10, 2020, at 7:56 AM, Salomon Turgman >> wrote: >> > >> > Hello all, >> > >> > Thanks in advance for any hints you can provide for this. I am trying >> to create a derived back-end that handles a new type of block in org-mode. >> I am trying to derive using the html export backend as a parent. >> > >> > Currently I am solving my problem like this: >> > #+CAPTION[Manual control]: Simulation 1: Manual control of the tank >> level. >> > #+BEGIN_EXPORT html >> >
Simulation 1: Manual control of the tank >> level.
>> >
>> >
>> > >> >
>> >
>> > >> > #+END_EXPORT >> > >> > This has a few downsides: >> > 1. I have to specify the caption twice since export translator does not >> handle captions. >> > 2. I have to include substantial amounts of html. >> > 3. I have keep track of references to simulations manually (simulation >> 1, simulation 2, etc) >> > 4. I have to include the identifier `main1` or `Main1` in several >> locations in the snippet. >> > >> > I could solve some of this with an automated snippet insertion tool but >> I thought that maybe I can get the export back-end to do most of the work >> for me. >> > >> > So I am trying to derive as follows (in pseudo-elisp-code): >> > (require 'ox) >> > (require 'ox-html) >> > >> > (org-export-define-derived-backend 'textbook 'html >> > :menu-entry >> > '(?I "Export textbook section" >> > ((?b "To buffer" org-html-export-as-html) >> > (?I "To file" org-html-export-to-html) >> > (?o "As HTML file and open" >> > (lambda (a s v b) >> > (if a (org-html-export-to-html t s v b) >> > (org-open-file (org-html-export-to-html nil s v >> b))))))) >> > :translate-alist '((simulation . org-textbook-simulation))) >> >> From the `org-export-define-backend' docstring: >> >> "TRANSCODERS is an alist between object or element types and >> functions handling them." >> >> But `simulation' is not such a type. So, this will not work. >> >> > >> > (defun org-textbook-simulation (element contents info) >> > (let* ((simnum (extract simnum value)) >> > (caption (org-export-get-caption element)) >> > (divid (extrac divid value)) >> > (modid (convert divid into modid)) >> > ) >> > (format "
Simulation %simnum%: >> %Caption%.
>> >
>> >
>> >
>> >
>> > " >> > simnum caption divid modid divid))) >> > >> > With the hope that I can do something like this in my .org file: >> > >> > #+CAPTION[Manual control]: Simulation 1: Manual control of the tank >> level. >> > #+BEGIN_SIMULATION main1 >> > Some other cool stuff here >> > #+END_SIMULATION >> >> >> I think an easier approach is to write a babel src-block that formats the >> inputs you need and creates a value that is your desired output. >> >> Use `:var' header arguments to define the inputs. >> >> Use `:wrap html' to prevent the exporter from changing the output. >> >> Subsequent calls can use the `#+CALL' idiom. >> >> You can use any scripting language that suits you - elisp, python, shell, >> R, ... --- for this purpose. >> >> If you are skilled in emacs-lisp you might write an `eval' macro instead >> of a src block. >> >> > >> > Am I on the right track here? Can someone point me to an example on how >> to: >> > 1. Keep track of the number of simulations for referencing? >> >> Using the babel approach, you would need a `:session' with a persistent >> variable that would hold the count. You would need to initialize it in your >> document so that subsequent exports will start counting at zero. >> >> > 2. Extract the caption properly? The above is just my guess. >> >> >> IIRC, the info channel is not populated when babel runs, so you will need >> to parse the src-block and extract the `:caption' element. I think you can >> use a `:var cap=(find-caption)' idiom, where `find-caption' is a function >> you write using `org-element-context' as a starting point. >> >> Or if the only need you have for the caption is within that src block >> just use `:var cap="". >> >> > 3. Extract the divid value (main1) >> >> :var divid="main1" >> >> >> > 4. And finally, how to get org to recognize the new SIMULATION block so >> that it can apply `org-textbook-simulation`? Do I need to register this >> type of block somewhere? Or is the name of the first member of the >> :translate-alist translation pair have some special meaning? >> >> Don't go in that direction. Use babel or write an eval macro. >> >> [snip] >> > --0000000000005eddd905a30e4df6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Ok... just reporting back my progres= s in case it helps someone else. Bur first, all the stuff that you can do w= ith src blocks is stuff I never imagined. Seems like the possibilities are = endless. Here is what I did so far:

#+NAME: simulation
#+= HEADER: :var cap=3D"DEFAULTCAPTION" :cache yes :eval no-export :v= ar altimage=3D"1_image.svg#img1"
#+BEGIN_SRC emacs-lisp :var d= ivid=3D"defid" :var num=3D1 :results html :exports results
(fo= rmat
"<div class=3D\"caption\">Simulation %s: %s&l= t;/div>
=C2=A0 <div class=3D\"simulation\">
=C2=A0= =C2=A0 <div id=3D\"%s\">
=C2=A0 =C2=A0 =C2=A0 <noscr= ipt>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 <svg>
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 <use xlink:href=3D\"assets/%s\" </use>
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 </svg>
=C2=A0 =C2=A0 =C2=A0 </noscr= ipt>
=C2=A0 =C2=A0 </div>
=C2=A0 </div>
=C2=A0 <= script>var app =3D Elm.%s.init({node: document.getElementById(\"%s\= ")});</script>"
num cap divid altimage (capitalize divid= ) divid)
#+END_SRC

That is my "definition&q= uot;... I call it like this:

#+CALL: = simulation(cap=3D"Manual control of tank level", num=3D1, divid= =3D"main1", altimage=3D"1_manual_noscript.svg")<= /div>
=
And it seems to work beautifully. Still need to figure out the = counting of the number of simulations per page... but that should be trivia= l at this point. Thank you so much for all the pointers.

-s-

On Fri, Apr 1= 0, 2020 at 1:14 PM Salomon Turgman <sturgman@gmail.com> wrote:
Thank you very much. I will explore w= hat you suggest. I'm glad I emailed, seems like I was going down the wr= ong path.

Salomon
<= br>
On Fri,= Apr 10, 2020, 1:10 PM Berry, Charles <ccberry@health.ucsd.edu> wrote:
Salomon, see inline comm= ents below.

HTH,

Chuck

> On Apr 10, 2020, at 7:56 AM, Salomon Turgman <sturgman@gmail.com> wrote:
>
> Hello all,
>
> Thanks in advance for any hints you can provide for this. I am trying = to create a derived back-end that handles a new type of block in org-mode. = I am trying to derive using the html export backend as a parent.
>
> Currently I am solving my problem like this:
> #+CAPTION[Manual control]: Simulation 1: Manual control of the tank le= vel.
> #+BEGIN_EXPORT html
> <div class=3D"caption">Simulation 1: Manual control of= the tank level.</div>
> <div class=3D"simulation">
> <div id=3D"main1">
> <noscript>
> Some other cool stuff here.
> </noscript>
> </div>
> </div>
> <script>var app =3D Main1.init({node: document.getElementById(&q= uot;main1")});</script>
> #+END_EXPORT
>
> This has a few downsides:
> 1. I have to specify the caption twice since export translator does no= t handle captions.
> 2. I have to include substantial amounts of html.
> 3. I have keep track of references to simulations manually (simulation= 1, simulation 2, etc)
> 4. I have to include the identifier `main1` or `Main1` in several loca= tions in the snippet.
>
> I could solve some of this with an automated snippet insertion tool bu= t I thought that maybe I can get the export back-end to do most of the work= for me.
>
> So I am trying to derive as follows (in pseudo-elisp-code):
> (require 'ox)
> (require 'ox-html)
>
> (org-export-define-derived-backend 'textbook 'html
>=C2=A0 =C2=A0:menu-entry
>=C2=A0 =C2=A0'(?I "Export textbook section"
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((?b "To buffer" org-html-export-= as-html)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(?I "To fil= e" org-html-export-to-html)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(?o "As HTM= L file and open"
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lambda (a s v b)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if a (org-html-= export-to-html t s v b)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0(org-open-file (org-html-export-to-html nil s v b)))))))
>=C2=A0 =C2=A0:translate-alist '((simulation . org-textbook-simulati= on)))

>From the `org-export-define-backend' docstring:

"TRANSCODERS is an alist between object or element types and
functions handling them."

But `simulation' is not such a type. So, this will not work.

>
> (defun org-textbook-simulation (element contents info)
>=C2=A0 =C2=A0(let* ((simnum (extract simnum value))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(caption (org-ex= port-get-caption element))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (divid (extrac divid value))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(modid (convert = divid into modid))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )
>=C2=A0 =C2=A0 =C2=A0(format "<div class=3D\"caption\"= >Simulation %simnum%: %Caption%.</div>
>=C2=A0 =C2=A0<div class=3D\"simulation\">
>=C2=A0 =C2=A0 =C2=A0<div id=3D\"%divid%\">
>=C2=A0 =C2=A0 =C2=A0</div>
>=C2=A0 =C2=A0</div>
> <script>var app =3D %modid%.init({node: document.getElementById(= \"%divid%\")});</script>"
>=C2=A0 =C2=A0 simnum caption divid modid divid)))
>
> With the hope that I can do something like this in my .org file:
>
> #+CAPTION[Manual control]: Simulation 1: Manual control of the tank le= vel.
> #+BEGIN_SIMULATION main1
> Some other cool stuff here
> #+END_SIMULATION


I think an easier approach is to write a babel src-block that formats the i= nputs you need and creates a value that is your desired output.

Use `:var' header arguments to define the inputs.

Use `:wrap html' to prevent the exporter from changing the output.

Subsequent calls can use the `#+CALL' idiom.

You can use any scripting language that suits you - elisp, python, shell, R= , ... --- for this purpose.

If you are skilled in emacs-lisp you might write an `eval' macro instea= d of a src block.

>
> Am I on the right track here? Can someone point me to an example on ho= w to:
> 1. Keep track of the number of simulations for referencing?

Using the babel approach, you would need a `:session' with a persistent= variable that would hold the count. You would need to initialize it in you= r document so that subsequent exports will start counting at zero.

> 2. Extract the caption properly? The above is just my guess.


IIRC, the info channel is not populated when babel runs, so you will need t= o parse the src-block and extract the `:caption' element. I think you c= an use a `:var cap=3D(find-caption)' idiom, where `find-caption' is= a function you write using `org-element-context' as a starting point.<= br>
Or if the only need you have for the caption is within that src block just = use `:var cap=3D"<your caption here>".

> 3. Extract the divid value (main1)

:var divid=3D"main1"


> 4. And finally, how to get org to recognize the new SIMULATION block s= o that it can apply `org-textbook-simulation`? Do I need to register this t= ype of block somewhere? Or is the name of the first member of the :translat= e-alist translation pair have some special meaning?

Don't go in that direction. Use babel or write an eval macro.

[snip]
--0000000000005eddd905a30e4df6--