I think you might be looking for something like this:
(defvar se-wrap-executable "C:/Program Files/Wraparound/Wrap/wrap.exe"
"Wrap is an open source command line tool that is able to
convert Fountain and Wrap files into a correctly formatted
screen- or stageplay as an HTML or a PDF. See URL
`https://github.com/Wraparound/wrap'")
(defvar se-wrap-out-dir default-directory
"Output directory for converted source.
Must end in slash. Errors may occur if path contains spaces.
See explanation at URL `https://emacs.stackexchange.com/a/59198/15177'.")
(defun se-wrap-src-block ()
"Call wrap on an Org source block at point.
Output to pdf in `se-wrap-out-dir' using the name of
the subtree containing the source block."
(interactive)
;; (save-buffer)
(let* ((element (org-element-at-point))
(type (org-element-type element))
(src (if (string= type "src-block")
(org-element-property :value element)))
(tempfile (concat (temporary-file-directory) "tempfile"))
(headline (org-entry-get nil "ITEM"))
(outfile (concat se-wrap-out-dir "\"" headline "\".pdf"))
(command (concat "\"" se-wrap-executable "\" pdf " tempfile " -o " outfile)))
(cond (src
(with-temp-file tempfile
(insert src))
(message "%s" (shell-command-to-string command))
(delete-file tempfile)
(message "Output: %s" outfile))
(t (message "Not a src-block")))))
Let's break it down.
We need the content of the source block at point. Org has two ways we might get it, the element parser or entry properties. The former parses an Org buffer into an abstract syntax tree composed of elements. We get the element at point with org-element-at-point
, check that it is a source block with org-element-type
, and obtain the contents using org-element-property
. According to the Org Element API, the :value
property contains the source code in a block as a string1.
We also need the headline containing the source block. Entry properties are more useful here since the point is at the source block. It's not entirely clear to me what an "entry" is, but it seems to be a subtree. Executing org-entry-properties
while in a source block shows that "ITEM"
corresponds to the headline. This can be obtained with org-entry-get
(n.b. not org-get-entry
).
So far so good.
Now we need to get this information to the wrap
program. There are several ways this could be done. I chose shell-command-to-string
which allows us to send a string to a shell process and who returns the result as a string.
The major challenge is how to present information to wrap
. Does it accept files or can it work with streams? It turns out both. However, sending a string directly to wrap
is a giant pain because of shell quoting. It's much simpler to dump the source content into a temp file and pass that to wrap
. Even still, some fiddling has to happen with quotes. A headline or file path may contain a space. As written, don't include spaces in the se-wrap-out-dir
2!
Otherwise, there's some mundane grunt work done to set up the right environment, construct the wrap
shell command, and clean up. Hopefully this is all self-explanatory (via C-h f
and C-h v
).
There are various style details to consider. You could refactor to pass arguments rather than use globals. You also might want to save the source before converting it. This would help ensure the source and output are in sync, but it's not strictly necessary. I have included that option as a comment. Of course, you can also bind things to a single key:
(global-set-key (kbd "<f5>") 'se-wrap-src-block)
This was written using Org 9.3.1 and Emacs 26.3.
I had fun writing this and I hope it helps! I wouldn't want you to break anonymity, but maybe we'll see something of yours on the silver screen soon, if not in a community theater nearby! Cheers!
1 The way this works is that :value
is a keyword (constant variable) of the element symbol. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html
2 The code for the outfile
is not safe against spaces. The headline
is quoted but then it's not easy to "quote the quotes" to protect against spaces in se-wrap-out-dir
. You might be able to use something like convert-standard-filename
here. I have little patience for these kinds of details, so I "leave this as an exercise to the reader".
org-narrow-to-block
ororg-narrow-to-subtree
before runningorg-latex-export-to-pdf
.:tangle number-two.fountain
to the appripriate source block and then didorg-tangle
(C-c C-v C-t
), you should get a file ``number-two.fountain` in the current directory with just the contents of that source block. You could then run you shell command on it. Does that help?