Dialects and runtimes
Jonquil evaluates through a dialect profile: what a language's files look like, how they're painted, and which evaluator runs them. Six profiles exist today: Jolt, ClojureDart (experimental), JVM Clojure, ClojureScript (experimental), jank (experimental) and nREPL, which attaches to any nREPL server you started.
The status bar's dialect label shows which one a window uses and whether its runtime is up:
| Dialect | Label |
|---|---|
| Jolt | Jolt, or Jolt (nREPL) when it runs out of process |
| ClojureDart | ClojureDart (attached) / ClojureDart (not running) |
| JVM Clojure | Clojure (JVM) (attached) / Clojure (JVM) (not running) |
| ClojureScript, shadow-cljs | ClojureScript (shadow-cljs) (attached) / (not running) |
| ClojureScript, own runtime | ClojureScript (node) (running) / (not running), or ClojureScript (browser) with the same endings |
| jank | jank (running) / jank (not running) (until the first evaluation starts one) |
| nREPL | nREPL (attached) / nREPL (not running) |
Choosing a dialect
Jonquil picks a dialect and a runtime for each window, in this order:
.jonquil.ednin the project, if it names one.- A single profile marker in the project (Jolt's is
deps.edn). - The open file's extension.
- The
:dialectsaved insettings.edn. - Jolt, when none of the above decides.
The project is the nearest directory, at or above the open file, holding .jonquil.edn or a profile marker. A loose file or an unsaved window has no project, so only the extension and the settings default are left.
How each dialect gets picked
- ClojureDart: marker
pubspec.yaml;.cljdis ClojureDart even when adeps.ednis also present, while.clj,.cljcand anything else stay Jolt's. - JVM Clojure: only
{:dialect :clj}picks it inside a project. A settings default of JVM Clojure applies to loose or unsaved files only. - ClojureScript: marker
shadow-cljs.ednattaches to your shadow-cljs server; a.cljsfile elsewhere runs on node.{:runtime :launch}or{:runtime :attach}forces the runtime (see ClojureScript). - jank:
.jankfiles, or{:dialect :jank}. - nREPL: only
{:dialect :nrepl}. Abb.ednor Basilisp project stays Jolt's until you say so (see Any nREPL server).
.jonquil.edn
A .jonquil.edn at the project root pins the dialect and, for Jolt, chooses the runtime:
{:dialect :jolt :runtime :in-process}
Both keys default independently, so either can be left out. A file that isn't valid EDN, or isn't a map, never blocks anything: the console prints a line like ; project: .jonquil.edn isn't valid EDN, so it is ignored and selection falls through to the next rule.
{:dialect :jank}pins jank (see jank).{:dialect :nrepl}attaches to any nREPL server.:nreplsays where:{:port 1667},{:host "box" :port 1667}or{:port-file "path/to/port"}(see Any nREPL server).{:dialect :clj}is the only way to reach JVM Clojure: the project attaches to its own nREPL server instead of running under Jolt (see JVM Clojure).:auto-requirelists namespaces to load as Jonquil connects. It works for JVM Clojure and Jolt; other dialects ignore it and the console says so (see Auto-require).:parinfersets Parinfer for the project's tabs, overriding the global setting either way::smart,:indentor:parenturns it on here, and:offkeeps it off here even when the setting is on.:format-stylepins what Format All and Format Selection produce for the project's tabs, so the repo formats one way for everyone whatever each person's Parinfer mode::paren-stablealways runs the Paren pass over the formatter's output,:plainnever does. Left out, a format follows the tab's mode (see Parinfer).:remember-session?decides whether the project's evaluations are recorded for last session's replay, overriding the setting insettings.edneither way:falsekeeps this project off disk, andtruerecords it even when the setting is off.
Running Jolt out of process
In a project with a deps.edn, Jolt runs out of process. Jonquil starts a separate Jolt nREPL server in the project directory and talks to it over a socket. A program that calls System/exit or shutdown-agents, redefines something in clojure.core, or otherwise takes Jolt down takes down that child, not the window. The project's deps.edn is the child's classpath.
{:runtime :in-process} in .jonquil.edn keeps a project inside Jonquil's process instead:
- Its
deps.ednis resolved as thejoltcommand does, so files can require the project's other files and dependencies, and F12 opens either. - A git or Maven dependency is fetched on first need ("Resolving deps.edn..."; Stop cancels). On failure the Run goes ahead on
:pathsalone and the console says why. - Edits to the project's
deps.ednre-resolve; edits to a:local/rootdependency's own do not (touch the project's file).
{:runtime :nrepl} asks for a child in a folder without a deps.edn. A file outside any project always runs in process. An untitled tab follows the window's folder: out of process in a deps.edn window, in process in a window with no folder.
Start lines, Stop, switching projects, and stdin
- The console reports the child's pid, port and project directory at start.
- Stop interrupts first; if the child doesn't answer in about a second, it kills and restarts the child and says so.
- Opening a file from a different project switches the session; the old evaluator is stopped and the console says so.
- stdin, the inspector and jump to definition work through Jonquil's own middleware, written to
~/.cache/jonquil/nrepl-middleware(or under$XDG_CACHE_HOME). If that can't be written or loaded, Jolt starts without them and the start lines say why;{:runtime :in-process}is the way back. A plain nREPL server gets no stdin (read-linereturns nil). - Output streams as it prints with jolt-lang/nrepl v0.4.0 or later, and from v0.4.2 a Run of a saved file records that file as its vars' source, for jump to definition.
Where the nREPL middleware comes from
Interrupt needs Jonquil to inject jolt-lang/nrepl's middleware. It uses, in order:
- A checkout at
$JONQUIL_JOLT_NREPLor~/dev/jolt-lang/nrepl(keep it at v0.4.2 or later). - jolt-lang/nrepl v0.4.2 as a git dependency. The first start clones it into
~/.gitlibs(about 3 seconds; needsgitand a network). - If the fetch fails, a plain nREPL server, and the console says so. It has no
interrupt, so Stop kills and restarts the child, andread-linehas no stdin. The next start retries the fetch.
.nrepl-port
Jonquil's Jolt child writes no .nrepl-port, and never touches one your project has, so another editor or a JVM Clojure window can't mistake the child for your server. Your own jolt nrepl-server writes the file as usual. The child uses Jonquil's middleware list, so a :nrepl/middleware in your deps.edn isn't loaded there.
This page is docs/guide/dialects/index.md in the Jonquil repository.