Skip to content
ClojureScript for Node for Max
Max Clojure
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
promises
simple
.gitignore
README.org

README.org

-*- mode: org; mode: visual-line; -*-

Clojure for Node for Max

Introduction

This is a simple project for bringing up a ClojureScript network REPL to talk to Max 8 via a Node.js sub-process. This means that Max can be live-coded in ClojureScript, at least to the extent that the node.script instance in Max is connected to interesting things in the patcher (via inlets, outlets, named dictionaries). We describe the support for CIDER inside Emacs, although other IDE toolchains are available and should work.

Background

Max has a library object called node.script which can fire up a Node.js process and attach it to the enclosing patcher document, so that the patcher can run Javascript code, and the Javascript code can manipulate things in the Max world.

Figwheel Main is a set of libraries which equips a Javascript client (a web browser, or Node.js) with a network connection to a Figwheel server; the latter runs in Clojure (on the JVM), hosts the ClojureScript cross-compiler, and supports a REPL (read-eval-print loop). When everything’s running, ClojureScript can be live-coded via the server, which compiles everything to Javascript and sends it through to the client. The server also tracks changes to source files, uploading code to the client as required.

When everything is running, the setup looks like this:

  • Max with an instance of node.script and a Node.js process attached to it
  • A Figwheel Main server, which Max’s Node.js attaches to
  • Emacs (or equivalent), attached to the server for live coding via CIDER

Most of this machinery is invisible (so in particular, the user code in ClojureScript for Max needs to know nothing about live coding support); Figwheel and CIDER augment the code automatically to tie everything together.

Setup

We’re using the Clojure CLI tools - nothing we’re doing is complicated enough to need Leiningen, so just follow the set detailed here: https://clojure.org/guides/deps_and_cli.

Compile and Run: First Shot (simple)

A very simple setup with a network REPL. This is the build configuration file, dev.cljs.edn:

^{:watch-dirs   ["src"]
  :node-command "node"
  :launch-node  false}
{:target :nodejs
 :main   simple.core}

The target is :nodejs. Also, in the meta-data, we’ve disabled :launch-node since that’s done by Max. For testing (without the Max API) make this true, in which case the value of :node-command might need to be altered.

Note the symbolic link from simple.js to the actual built target. This is needed because Max’s node.script object doesn’t support complex file paths.

To build, invoke cider-jack-in-cljs from Emacs while visiting scratch.cljs. For ClojureScript REPL type, enter figwheel-main. For figwheel-main build, enter :dev.

Start the Max node process once the CIDER session has initialised and is waiting for a client connection.

Working with Promises (promises)

A more sophisticated example, interacting with Max dictionaries. Since dictionary operations return Javascript promises, we’re using cljs-promises, which wraps them in ClojureScript’s core.async machinery.

You can’t perform that action at this time.