org-babel-screen
Org-babel support for interactive terminals
Introduction
org-babel-screen is an extension to Org-babel and was inspired by Eduardo Ochs's eev.
org-babel-screen provides the ability to write interactive Makefiles that can be called from inside Emacs. Now before you get your hopes up: The whole point of Makefiles is that they should run automatic. org-babel-screen doesn't do that! I guess the only thing they have in common is that they both do certain things. And that they can be grouped.
I admit, the analogy is not great. But to explain why I still think it's useful I will go and show a few examples in this document.
First install org-babel according to the directions given in the org-babel manual. Then come back here.
Setup
Now that you've installed org-babel, add the following after the other org-babel related statements.
(require 'org-babel-screen) ;; requires screen, terminal
There are two important variables that you might want to review before using org-babel-screen: org-babel-screen-location and org-babel-default-header-args:screen
If GNU Screen is installed and recognized by your PATH you can ignore org-babel-screen-location, otherwise change the value of that variable to the absolute path of the screen binary.
The default headers arguments are a bit more interesting. If you don't have XTerm installed or you don't wish to use it, you need to edit the value of org-babel-default-header-args:screen.
This is the default:
(defvar org-babel-default-header-args:screen '((:results . "silent") (:session . "default") (:cmd . "sh") (:terminal . "xterm")) "Default arguments to use when running screen source blocks.")
The :session, :cmd & :terminal keys are the only thing that matter in this mode.
You can test the default setup by executing M-x org-babel-screen-test RET
.
The minibuffer will echo if the test has succeeded or not. 1
Example 1: Creating a gif out of a video file
Let's get on with the examples though: I'm going to use MPlayer, QIV & ImageMagick for this. But you can follow this example without them.
Set the correct settings
I'm setting the session name of create-gif so I can have other interactive terminals running without interference. Example 2 will go further into this.
The :cmd is zsh, because that's my favorite shell and I know how to do globbing with it.
This example is very verbose, but here it goes:
#+begin_src screen :cmd zsh :session create-gif TMPDIR=/tmp/gif VIDEOFILE=~/TMP/DubistTerrorist_de_divx_HD.avi #+end_src
Create TMPDIR and change directory to it
The :session parameter has to be the same as the one used in the first step, the :cmd parameter can be ignored though.
#+begin_src screen :session create-gif mkdir -p $TMPDIR cd $TMPDIR #+end_src
Copy video to TMPDIR
#+begin_src screen :session create-gif cp -v $VIDEOFILE . VIDEOFILE=$VIDEOFILE:t #+end_src
Skip through the video file to find the spot you want to extract
This is the first interactive step. Find the position in the video of the section you want to extract. This information will be used in the next step.
#+begin_src screen :session create-gif mplayer -ao null -osdlevel 3 $VIDEOFILE #+end_src
Extract those frames from the video
Change the value of START and optionally SECS. For this video I've chosen 1:10 with a 10 seconds window.
#+begin_src screen :session create-gif START=1:00 SECS=10 mplayer -ao null -vo png $VIDEOFILE -ss $START -endpos $SECS #+end_src
Delete the frames you don't want
This is the second interactive part.
You delete the frames by pressing 'd' in qiv.
#+begin_src screen :session create-gif qiv . #+end_src
Resize pictures
256 x the corresponding aspect ratio is a good size.
#+begin_src screen :session create-gif SCALE=25% mkdir Small/ for img (*.png) { convert -scale $SCALE $img Small/$img } file Small/*.png([1]) #+end_src
Inspect down-scaled size
If the size isn't alright, redo the previous step with a different SCALE.
#+begin_src screen :session create-gif qiv Small/*.png #+end_src
Generate gif file
The settings here are for an endless looping gif. If the gif plays to fast or too slow, you can just change the command line options as you normally would.
#+begin_src screen :session create-gif convert -delay 10 -loop 0 Small/* animation.gif #+end_src
Look at the resulting gif
I use opera for this. If the gif is not satisfactory, repeat the above steps as necessary.
#+begin_src screen :session create-gif opera animation.gif #+end_src
Example 2: Semi-parallel communication via netcat
This is a very small example2, but expands on the concept of sessions well. The objective is to send a message via TCP to someone else. (We fake this by doing everything via localhost The principle is the same.)
Listen for message
Set up netcat to listen to port 1234.
Notice the :session parameter. Specifying receiver
here and
sender
below allows us to run this example from a single source
but with two interactive seesions.
#+begin_src screen :session receiver netcat -l -p 1234 #+end_src
Send the message
Use the default shell (:cmd has been omitted.) to generate a message and send it to the port that is listening for it.
#+begin_src screen :session sender { echo hi sleep 1 echo bye sleep 1 } | netcat -c localhost 1234 #+end_src
After you've invoked both examples, you can see how the receiver
session sees the message send by sender
.
How this might be useful: You could take this example further and test an app that communicated via a network interface. You wouldn't have a fully automatic setup yet, but the Reproducible Research concept still applies.
Header Arguments
Here's a general overview of header arguments:
- session
- session name that is used by screen
- default value
- default
- cmd
- argument must be a shell of some sort
- default value
- sh
- examples
- sh, zsh, irb, python, sqlite3
- terminal
- must support -T 'title' and -e 'command'
- default value
- xterm
- examples
- xterm, urxvt, aterm, Eterm
- results
- argument currently ignored
- default value
- silent
Footnotes:
It does this by generating a random string, writing it via org-screen-babel to /tmp/testfile and reading it back via Emacs. If the validation fails, the setup is deemed broken.
The example is taken from Eev as well: channels.anim