March 12, 2018

UXBOX source code browsing with Emacs+Cider

The Clojure and ClojureScript application, which is impressive in its functionality and beautifully structured source code – UXBOX (by uxbox.io).

Using Emacs+Cider for UXBOX source code browsing under Linux. To set up Emacs for Clojure and ClojureScript with Cider, see e.g.: My Emacs configuration.

Clone the UXBOX source code

In a subdirectory of your own choosing execute the following:

git clone https://github.com/uxbox/uxbox.git

Which clones the UXBOX source code into a newly created uxbox subdirectory.

Edit some UXBOX container files

We want to run emacs from inside the UXBOX Docker container (beware of possible security implications –check your firewall) and have its GUI displayed on the host's screen. To accomplish this some files need to be changed, as follows:

manage.sh

Change the Docker run statement in manage.sh to the following:

docker run --net=host -ti \
         -v `pwd`:/home/uxbox/uxbox  \
         -v $HOME/.m2:/home/uxbox/.m2 \
         -v $HOME/.gitconfig:/home/uxbox/.gitconfig \
         -v $HOME/.lein:/home/uxbox/.lein \
         -p 3449:3449 -p 6060:6060 -p 9090:9090 $IMGNAME:$REV

Which uses –net=host to use the host's network stack inside the container. Also maps (additionally) the ~/.lein subdirectory. (The -p 3449:3449 -p 6060:6060 -p 9090:9090 are now superfluous but I've left them in.)

docker/Dockerfile

Change docker/Dockerfile to include Emacs stuff (unzip to view inside jars and the silver searcher):

RUN apt-get update -yq &&  \
    apt-get install -yq bash git tmux vim openjdk-8-jdk rlwrap build-essential \
                        postgresql-9.6 postgresql-contrib-9.6 imagemagick webp \
                        sudo python unzip silversearcher-ag emacs

(The python package is included to prevent a gulp related error –it needs python somewhere.)

docker/files/start.sh

Change docker/files/start.sh to comment out the figwheel line (we'll start it from Emacs):

tmux new-window -t uxbox:1 -n 'figwheel'
tmux select-window -t uxbox:1
tmux send-keys -t uxbox 'cd uxbox/frontend' enter C-l
#tmux send-keys -t uxbox 'npm run figwheel' enter

frontend/scripts/figwheel.clj

Change options so that the local backend is used.

(def options
  {;"uxbox.config.url" "https://demo.uxbox.io/api"
   "uxbox.config.url" "http://127.0.0.1:6060/api"
   })

Note the single semicolon ; (a double semicolon ;; results in an error during figwheel execution).

frontend/project.clj

Change under Build to add piggieback.

  ;; Build
  [com.cemerick/piggieback "0.2.2"]
  [figwheel-sidecar "0.5.9" :scope "provided"]
  [environ "1.1.0"]

And add nrepl options at the end, right above :clean-targets:

    :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
    :clean-targets ^{:protect false} ["resources/public/js" "target"]

Build and run the Docker container

./manage.sh build

If all went well with the build.

./manage.sh run

This will take some time to initialize.

UXBOX container tcmux window

In the backend tmux tab (Ctrl-b 2)

Start a headless REPL for the backend source code.

lein trampoline repl :headless

UXBOX container backend tab

Jot down the port on which the nREPL server started.

Create a new tmux tab (Ctrl-b c) to configure and run Emacs

Use Ctrl-b c to create a new tmux tab.

Set up your Emacs configuration with Cider.

I'm using my own config, as follows:

git clone https://github.com/maridonkers/emacs-config.git /home/uxbox/.emacs.d

UXBOX container emacs-config

Setting up Emacs for source code browsing

Set the DISPLAY variable, start the Emacs daemon and edit the backend/project.clj and frontend/project.clj files in the uxbox subdirectory.

export DISPLAY=:0
emacs --daemon
cd uxbox
emacsclient -nc backend/project.clj frontend/project.clj

UXBOX container emacs-started

(If emacs –daemon or emacsclient fails then re-run emacs –daemon and try again.)

Connect to backend REPL and start the backend

In your Emacs GUI switch to the backend/project.clj buffer and use M-x cider-connect to connect to the backend REPL. Normally you can use the default (localhost) and also press ENTER for the port number (which automatically finds the port number). If it doesn't work then use the jotted down backend REPL port number.

The backend REPL should now show up in a separate Emacs buffer. Now start the backend by typing (start) in the backend REPL buffer:

(start)

UXBOX container emacs backend

In the frontend tmux tab (Ctrl-b 1)

Start a headless REPL for the frontend source code.

lein trampoline repl :headless

UXBOX container frontend tab

Jot down the port on which the nREPL server started.

Connect to frontend REPL and start the frontend

In Emacs switch to the frontend/project.clj buffer and use M-x cider-connect to connect to the frontend REPL. Normally you can use the default (localhost) and also press ENTER for the port number (which automatically finds the port number). If it doesn't work then use the jotted down frontend REPL port number.

The frontend REPL should now show up in a separate Emacs buffer. Now start the frontend by starting figwheel in the frontend REPL buffer:

(load-file "scripts/figwheel.clj")

UXBOX container emacs frontend

Load or reload the page

The frontend REPL reports Prompt will show when Figwheel connects to your application, which occurs when the page with the ClojureScript code is loaded or reloaded. So (re)load the http://localhost:3449 page.

UXBOX container browser window

Now the Figwheel prompt is shown.

UXBOX container emacs frontend activated

Browse the UXBOX source code

Now you're ready to browse through the UXBOX source code, using Emacs+Cider features (such as cider-doc to get documentation and cider-find-var to jump to a symbol).

UXBOX container emacs source code browsing

(If Emacs+Cider features don't work right away then just throw in an Ctrl+c+k cider-load-buffer to kick it.)

Manage repl connections

Sometimes you require a specific repl to be the active connection for a source file. E.g. for .cljc files. There is a section in the CIDER documentation on this: Managing Connections.

Tags: Software IDE Computer JavaScript Clojure ClojureScript Server Web Internet Database Client GUI Emacs Functional