Fork me on GitHub

Nightlight

An embedded editor for Clojure


Also try Paravim, an editor-as-a-library based on Vim!


What is it?

Nightlight is an editor you run inside your Clojure projects. Instead of being a separate application like traditional editors and IDEs, it's just a library that you add to your project. It spins up a web server and provides a completely browser-based interface to edit your code.

By running inside your project, it has complete access to the running state of your program. The ambition is to create something that follows the Lisp and Smalltalk tradition, blurring the line between your tools and your code to provide unprecedented interactivity.

Join the discussion on /r/Nightcode and read the source code.

How do I get started?

With Boot...

Add it to your build.boot:

(set-env!
  :source-paths #{"src"}
  :dependencies '[[org.clojure/clojure "1.9.0"]
                  [nightlight "RELEASE" :scope "test"]])

(require '[nightlight.boot :refer [nightlight]])

(deftask run []
  (comp
    (wait)
    (nightlight :port 4000)))

Then, in your project, do boot run


With Leiningen...

Add it to your ~/.lein/profiles.clj:

{:user {:plugins [[nightlight/lein-nightlight "RELEASE"]]}}
			

Then, in your project, do lein nightlight


With the official clj tool...

Add it to your deps.edn:

{:paths ["src"]
 :deps {nightlight {:mvn/version "RELEASE"}}}
			

Then, in your project, do clj -m nightlight.core

What can it do?

Code Completion

The right sidebar is constantly showing you code completion suggestions as you type. It works with all your third-party libraries as well. Just hit tab to select the first, or click another item in the list.

REPL

Since it's running inside your project, Nightlight provides a REPL for free. No need to fiddle with connections -- just click the REPL tab in the left sidebar.

InstaREPL

In addition to a standard REPL, you can enable an instaREPL for any Clojure file. That will cause the code to be constantly evaluated as you type, with the results shown on the left.

What about ClojureScript?

Nightlight can optionally display a ClojureScript REPL tab that contains an embedded view of your ClojureScript app and a REPL that can access it. Additionally, it will enable the instaREPL in all your ClojureScript files.

Setting it up involves just two steps:

1. Require nightlight.repl-server in your ClojureScript app

Just add it to your main ns form like this:

(ns hello-world.core
  (:require [nightlight.repl-server]))

Note: Leiningen users will also need to add Nightlight to the dependencies vector in project.clj:

[nightlight "RELEASE"]

2. Tell Nightlight what address your ClojureScript app is running on

With Boot, just pass the URL into the boot task:

(deftask run []
  (comp
    (serve :dir "target/public" :port 3000)
    (watch)
    (reload)
    (cljs :source-map true :optimizations :none)
    (target)
    (nightlight :port 4000 :url "http://localhost:3000")))

With Leiningen or the official clj tool, pass the URL into the command:

lein nightlight --url "http://localhost:3000"
clj -m nightlight.core --url "http://localhost:3000"

That's it! This is quite possibly the simplest setup process you'll find for a ClojureScript REPL.

Can I use this to develop on a remote server?

Absolutely. Run Nightlight on your desired port, and make sure the server is exposing that port publicly. Keep in mind that anyone will be able to access it if they know the address! To prevent this, there are two options:

1. Set a username and password

Nightlight allows you to require a username and password.

With Boot, it's recommended that you do this in ~/.boot/profile.boot:

(set-env! :dependencies '[[nightlight "RELEASE" :scope "test"]])
(require '[nightlight.boot :refer [nightlight]])
(task-options! nightlight {:user "admin passw0rd"})

With Leiningen or the official clj tool, do this in the command:

lein nightlight --user "admin passw0rd"
clj -m nightlight.core --user "admin passw0rd"

2. Bind Nightlight to localhost and access it via SSH tunneling

First, pass :host "localhost" to the Boot task (or --host localhost to the lein command). This will prevent Nightlight from accepting connections from outside localhost.

Then, from your local machine, set up an SSH tunnel. For example, if you run Nightlight on port 4000 on your server, the following command will allow you to access it on your local machine at http://localhost:9000 (replace USERNAME and IP_ADDRESS, of course):

ssh -L 9000:localhost:4000 USERNAME@IP_ADDRESS

How does this compare to Nightcode?

Nightcode is a Clojure IDE I've been working on for some time. It works like any traditional IDE, running in its own process. I have always struggled to provide features like code completion because they require a deep understanding of your project, including its dependencies.

More powerful editors like Cider and Cursive manage to do this with some very complex machinery that I could never duplicate. Instead, I decided to rethink the problem. Since Nightlight runs inside the same process as your project, code completion and other advanced features are trivial to implement.