djiamnot / ob-sclang

Orgmode Library of Babel implementation of sclang support in code blocks
GNU General Public License v3.0
11 stars 1 forks source link
babel orgmode sclang supercollider

+TITLE: ob-sclang

+STARTUP: showall

+STARTUP: showstars

** Why do I even? [[https://orgmode.org/][Org-mode]] makes [[http://literateprogramming.com/][literate programming]] easy via [[https://orgmode.org/worg/library-of-babel.html][Library of Babel]]. Il simply allows to mix text with executable /code blocks/ which can also be extracted (/tangled/) into separate, executable files. The beauty of the Library of Babel implementation in org-mode lies in the fact that it supports many languages. I craved support for [[https://github.com/supercollider/supercollider][SuperCollider]] and craving became an itch when I needed to document a working pipeline alternating between executing sclang and shell scripts. I scratched an itch with this little module.

** How to install? First of all, you will need emacs (>=26) and SuperCollider (with emacs support) installed. Modern emacsen and Spacemacs come with bundled org-mode.

It can be installed as a package via [[https://melpa.org/#/i-ching][Melpa]] or manually.

+BEGIN_SRC emacs-lisp

(use-package ob-sclang :config (org-babel-do-load-languages 'org-babel-load-languages '((sclang . t))))

+END_SRC

To install manually you can either drop [[file:ob-sclang.el]] somewhere in your Emacs' path or add its containing directory to ~load-path~ in =.init= file:

+BEGIN_SRC elisp

(add-to-list 'load-path "/path/to/ob-sclang/")

+END_SRC

You will also have to add it to =(org-babel-do-load-languages)=

+BEGIN_SRC elisp

(require 'ob-sclang) (org-babel-do-load-languages 'org-babel-load-languages '((sclang . t)))

+END_SRC

** And then?

Well, then you type a block like this one:

+BEGIN_SRC org

,#+BEGIN_SRC sclang "boo".postln; ,#+END_SRC

+END_SRC

And after you hit /C-c C-c/ you should see the string appear in your =SCLang:PostBuffer*=

Note:, make sure you execute =sclang-start= prior to executing any sclang code blocks

*** Use of variables

You can also include variables to be passed to you sclang code:

+BEGIN_SRC org

,#+BEGIN_SRC sclang :var boo="hoo" :var pi=3.14159 :var year=2000 :var buf='foo boo.postln; pi.postln; year.postln; buf.postln; ,#+END_SRC

+END_SRC

Will reformat your sclang body to:

+BEGIN_SRC sclang

"hoo".postln; 3.141590.postln; 2000.postln; "foo".asSymbol.postln;

+END_SRC

Before passing it on to the sclang process.

The use of sclang's own global variables is persistent between code blocks so =~boo=

+BEGIN_SRC org

,#+BEGIN_SRC sclang ~boo = "hoo"; ,#+END_SRC

+END_SRC

is accessible here:

+BEGIN_SRC org

,#+BEGIN_SRC sclang ~boo.postln; ,#+END_SRC

+END_SRC

** Known issues At this point, this plugin has a very crude functionality. It allows unidirectional control of SuperCollider process running inside Emacs. As such, here is a list of issues:

Of course feel free to open questions, suggestions, discussions and even pull requests.

The code blocks beyond this point can be executed from an org buffer:

Post some string to SC's Post Buffer:

+begin_src sclang

"boo".postln;

+end_src

This python code does not need to be evaluated beforehand because it will be evaluated by sclang block below.

+name: frompy

+begin_src python :session sc :results value

[1,2,3,4]

+end_src

+RESULTS: frompy

| 1 | 2 | 3 | 4 |

And we will use this table as input data

+name: tbl

| boo | 5 | 9 | | good | 7 | xa |

And here we execute some sclang that simply reads variables specified in code block's header. They include named python codeblock above and the table.

+begin_src sclang :var x=10 y=11 z=1.1 table=tbl tb=frompy

x.postln; x.class.postln; y.postln; y.class.postln; z.postln; z.class.postln; table.postln; table.class.postln; table[0].postln; tb.postln; tb.class.postln;

+end_src

And this is the output to SC's Post Buffer.

+begin_example

10 Integer 11 Integer 1.1 Float [ [ boo, 5, 9 ], [ good, 7, xa ] ] Array [ boo, 5, 9 ] [ 1, 2, 3, 4 ] Array

+end_example