jbang icon indicating copy to clipboard operation
jbang copied to clipboard

feat: add Clojure to supported languages

Open albertocavalcante opened this issue 8 months ago • 7 comments

Is your feature request related to a problem? Please describe.

JBang currently lacks support for Clojure despite supporting other JVM languages (Java, Kotlin, Groovy). This creates a significant gap for developers who use Clojure on the JVM and need the streamlined scripting capabilities that JBang provides.

Describe the solution you'd like

Implement Clojure support in JBang with the following features:

  • Script initialization via jbang init -t hello.clj filename.clj
  • Direct execution with jbang filename.clj
  • Version specification through //CLOJURE x.y.z directive
  • Integration with JBang's editing features
  • Standard Maven dependency resolution

Describe alternatives you've considered

  • Clojure REPL - Focuses on interactive development rather than scripting
  • ClojureScript - Targets JavaScript runtimes, not applicable for JVM use cases
  • Leiningen/tools.deps - Project-oriented rather than script-oriented
  • Babashka - Separate ecosystem without JVM interoperability benefits

Additional context

Clojure is a production-ready JVM language with significant industry adoption. As a hosted language that compiles to JVM bytecode, Clojure fits well within JBang's architecture. This addition would complete JBang's coverage of mainstream JVM languages and expand its utility for functional programming use cases.

Resources:

Disclaimer: polished using gen-ai

albertocavalcante avatar Apr 05 '25 04:04 albertocavalcante

Want to make a pr?

maxandersen avatar Apr 05 '25 12:04 maxandersen

@maxandersen definitely interested - just won't have bandwidth for now. Will keep in the backlog and revisit it sometime.

albertocavalcante avatar Apr 06 '25 04:04 albertocavalcante

Explored the concept of supporting Clojure a bit and assembled these example scripts.

clojure_cli.java:

///usr/bin/env jbang "$0" "$@" ; exit $?

//DEPS org.clojure:clojure:1.12.0
//JAVA 21

import clojure.main;

public class clojure_cli {
    public static void main(String[] args) {
        main.main(args);
    }
}

hello.clj:

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)
$ jbang run clojure_cli.java  hello.clj
Hello World
3

clojure_cli.java can be registered in the jbang-catalog.json as clojure-cli and then installed as a jbang app to allow it to be used as follows:

$ clojure-cli  hello.clj
Hello World
3

wfouche avatar May 08 '25 09:05 wfouche

A minimalistric way to start Clojure using only JBang functionality.

$ jbang run --main clojure.main org.clojure:clojure:1.12.0  hello.clj 
Hello World
3

wfouche avatar May 08 '25 14:05 wfouche

So clojure doesn't use a compile step? Then this could probably be easily implemented using something similar to JshSource and JshCmdGenerator in the main code. (And given the fact there seems to be a lot less issues with different kinds of runtimes and compatibilities when compared to Python, it's more likely to get merged quickly as well)

Edit: the clarify a bit more: Clojure doesn't use a_separate_ compile step? So you can point its runtime directly to a .clj file and it will work? (I don't really care if internally it compiles and then runs the result. The important part is if there are class files somewhere or not. No class files -> treat as Jsh, Yes class files -> treat as Java/Kotlin/Groovy)

quintesse avatar May 08 '25 16:05 quintesse

So clojure doesn't use a compile step?

Correct.

https://blog.kdgregory.com/2016/05/how-and-when-clojure-compiles-your-code.html?m=1

"Clojure is very much a scripting language, even though it compiles its scripts into JVM bytecode. All Clojure source files are processed one expression at a time: the reader reads characters from the source until it finds a valid expression (a list of symbols delimited by balanced parentheses), expands any macros, compiles the result to bytecode, then executes that bytecode."

wfouche avatar May 09 '25 03:05 wfouche

@quintesse , a side note about Jython and JBang. I've figured out today how to run Jython by just using JBang. This might be applicable to Clojure as well.

$ jbang run --java 21 \
    -Dpython.console.encoding=UTF-8 \
    --deps io.leego:banana:2.1.0 \
    --main org.python.util.jython \
    org.python:jython-slim:2.7.4 \
    banner.py

[jbang] Resolving dependencies...
[jbang]    org.python:jython-standalone:2.7.4
[jbang]    io.leego:banana:2.1.0
[jbang] Dependencies resolved
['banner.py']
sys.stdout.encoding = UTF-8
sys.stdin.encoding = UTF-8
      _       _   _                   ____   _____ 
     | |_   _| |_| |__   ___  _ __   |___ \ |___  |
  _  | | | | | __| '_ \ / _ \| '_ \    __) |   / / 
 | |_| | |_| | |_| | | | (_) | | | |  / __/ _ / /  
  \___/ \__, |\__|_| |_|\___/|_| |_| |_____(_)_/   
        |___/                                      
# banner.py
import sys

import io.leego.banana.BananaUtils as BananaUtils
import io.leego.banana.Font as Font

def main():
    print(sys.argv)
    print("sys.stdout.encoding = " + sys.stdout.encoding)
    print("sys.stdin.encoding = " + sys.stdin.encoding)

    text0 = "Jython 2.7"
    text1 = BananaUtils.bananaify(text0, Font.STANDARD)

    print(text1)

main()

wfouche avatar May 09 '25 08:05 wfouche