This project implements a build target for shadow-cljs so that Clojurescript can be compiled to Javascript in a form suitable for Gnome Javascript Bindings - Gjs.
- This is a modification of the
:node-scripttarget from original shadow-cljs source code. - Only development mode compilation works.
- Gjs does not have a
consoleobject. As such, a rudimentaryconsoleanalog is implemented which proxies appropriate functions in Gjs. This makes Clojurescriptprintlnand related functions working as is. - Gjs builtin modules(i.e.
gi.Gtk,system) are importable as Clojurescript namespaces using a special syntax.
Gjs builtin modules can be accessed using a string based namespace syntax -
"gjs.<builtin-module-name>". For example, if you want to import the gi.Gtk
module, the mapped namespace name should be "gjs.gi.Gtk".
| Javascript | Clojurescript |
|---|---|
const Gtk = imports.gi.Gtk; |
(require '["gjs.gi.Gtk" :as Gtk]) |
const ByteArray = imports.ByteArray; |
(require '["gjs.byteArray" :as ByteArray]) |
const { Gtk, GLib } = imports.gi; |
(require '["gjs.gi" :refer [Gtk GLib]]) |
Here's a short tutorial on how to get a simple Gtk app and running with
Clojurescript. Note that I am detailing the lowest friction way of installing
and using shadow-cljs. Feel free to use lein, boot or deps.edn, if you
want so. Look at shadow-cljs documentation to know how to do that.
- Install
npmwith your distribution's package manager. Also, don't forget to installgjsand gobject introspection bindings, which is packaged under namegir1.2-javascriptcoregtk-4.0in Ubuntu 20.04. - Create a demo shadow cljs project with
npx create-cljs-project gjs-demo. This should create a project directory namedgjs-demo. Change current directory to it. - Create a file named
gjs_demo.cljsunder directorysrc/main/with the following content -
(ns gjs-demo
(:require [clojure.string :as str]
["gjs.gi.Gtk" :as Gtk]
["gjs.system" :as system]))
(defn ^:export main [& args]
(println "Hello from console!")
(println "Command line arguments are: " (str/join ", " args))
(let [msg (str "Hello, Gtk + Clojurescript!\ngjs version = "
(.-version system))]
(Gtk/init nil)
(let [win (Gtk/Window.)
label (Gtk/Label. #js {:label msg})]
(doto win
(.set_size_request 400 150)
(.connect "delete-event" (fn [] (Gtk/main_quit)))
(.add label)
(.show_all))
(Gtk/main))))- Edit the
shadow-cljs.ednfile. Change it's content to -
;; shadow-cljs configuration
{:source-paths
["src/dev"
"src/main"
"src/test"]
:dependencies
[[titonbarua/shadow-cljs-gjs-target "0.1.0"]]
:builds
{:app {:target shadow-cljs-gjs-target.core
:output-dir "./jslibs"
:output-to "./app.js"
:main gjs-demo/main}}}-
Run
npx shadow-cljs compile app. This should emit a development javascript file namedapp.jsat project root. Run it withgjs app.js. If everything is ok, you should see a tiny Gtk window with some text. -
To produce a release build, run
npx shadow-cljs release.
Take a look at examples directory for more robust usage examples.
You can compile them by running the relevant compile.sh script.
- Fix release mode compilation.
- Source maps don't work.
- REPL does not work.
- There needs to be a way to explicitly set gi versions before import, like:
imports.gi.versions.Gtk = "3.0"; - Needs to add tests.
- Take care of undefined property errors.
Copyright © 2020 Titon Barua
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

