0

I'm writing a screenplay using Fountain mode. My org file is set up so there are multiple screenplays in a given file, for example

* Number one!
#+begin_src fountain
  INT A PARK IN SAN FRANCISCO

  EMPEROR NORTON
  Being desirous of allaying the dissensions of party strife now existing within our realm, I do hereby dissolve and abolish the Democratic and Republican parties.
#+end_src

* Number two!
#+begin_src fountain
  INT LETTERS DISPLAYED OVER A DESK

  PHILIP II OF MACEDON
  You are advised to submit without further delay, for if I bring my army into your land, I will destroy your farms, slay your people, and raze your city.

  letter is replaced

  SPARTA
  If.
#+end_src

I want to run an external command to convert one of these screenplays into a pdf. Fountain mode does not have the export functionality I want. It currently has some, but it is being removed in a future release.

If I had the screenplay in a file by itself, I could run a command in bash using wrap: wrap pdf my-screenplay.fountain. But it's not in a file by itself; it's a single source block.

So I'd like to be able to run a command on this single source block.

No org feature I've looked at seems to do this cleanly, although I might be missing something. I've looked at Org export, Org tangle, and Org publish, but as far as I can tell, they only act on a file as a whole.

How can I pass the contents of a single source block to an external command? Ideally I'd also be able to get the name of the headline before the command, so I can name each exported pdf differently.

4
  • You might have luck with org-narrow-to-block or org-narrow-to-subtree before running org-latex-export-to-pdf. Jun 21, 2020 at 2:06
  • This would work, but one can imagine how this is a frustrating procedure, especially if I want to reference one block while writing another.
    – zck
    Jun 21, 2020 at 5:18
  • If you add the header arg :tangle number-two.fountain to the appripriate source block and then did org-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?
    – NickD
    Jun 21, 2020 at 13:23
  • Does the wrap command work without passing a file name? Specifically can a fountain file be piped to the wrap command? If so, then you might be able to use here-doc syntax to pass the block contents to the command.
    – Melioratus
    Aug 7, 2020 at 20:27

2 Answers 2

1

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-dir2!

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".

4
  • I'm not sure I'll have time to properly evaluate this for a while. This looks interesting, but definitely runs a lot of things I don't want to do. As I said, I'm looking to run an external command on the block. It's not a .tex file, so org-latex-compile will do the wrong thing. I'll try to remember to come back and see if I can modify the code to run arbitrary external commands once I have more time.
    – zck
    Jun 23, 2020 at 4:31
  • It looks like we may be talking past one another. I have provided more detail and explanation which I hope will clarify things. :) Jun 24, 2020 at 15:19
  • I think I see your issue: you want to send the contents of the source block to wrap which interprets the fountain markup specifically. Plain Org export won't work for that, you're right. The string approach I gave might work for you by a pipe or redirect. Otherwise, we can probably come up with a solution that works with a temp file made by with-temp-file. Jun 24, 2020 at 18:15
  • Updated with direct answer. See the edit history for previous brute force attempts. Jun 25, 2020 at 23:56
0

I'm not sure what you want, but if you want to export one of the headings to a PDF, you can export it by selecting the sub-heading in the export selection dialog. For example, if you have this:

* Number One
:PROPERTIES:
:EXPORT_FILE_NAME: one
:END:

Put the cursor somewhere on or under the heading, and then C-c C-e C-s where the C-s selects sub-heading, and then choose your export format. PDF via LaTeX, or to plain text which you can then wrap, whatever that is.

The :PROPERTIES: and :EXPORT_FILE_NAME: is not required.

If you want to operate on the SRC block itself, I don't know anything about Fountain, but this works for me:

* Foo

#+NAME: f
#+BEGIN_QUOTE fountain
text here
#+END_QUOTE

#+BEGIN_SRC bash :var f=f
echo $f
#+END_SRC

#+RESULTS:
: text here

That is, change your BEGIN_SRC fountain to BEGIN_EXAMPLE or BEGIN_QUOTE, add a #+NAME: to it, and you can then ingest your Fountain text into a Bash or Python block where you write only the contents of the Fountain source to another file. For example, instead of echo $f you could do echo $f > source.fountain and then wrap that.

1
  • I'd rather not have to export to a separate file -- in that case, I might as well just be editing the file directly. For the #+BEGIN_QUOTE version, I can't seem to make it work. When I run it, I get the message "Code block produced no output.", and no output file is produced from the wrap call. Do you know of any ways to debug this?
    – zck
    Jan 29, 2020 at 6:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.