Reputation: 27236
I'd like to make an application available in the form of a Clojure REPL. Ie. something the user runs from the terminal and has a full Clojure REPL with a bunch of extra functionality included as Clojure functions.
I want the whole thing to live in a stand-alone JAR and not depend on the user already having Clojure installed or knowing how to install Clojure or import extra libraries. The whole thing should just be there when run.
Is there a straightforward way to make this? Ie. reusing the existing Clojure REPL code?
Upvotes: 3
Views: 201
Reputation: 37073
All you have to do is to run the clojure.main/repl
in your own main.
The docs explain the entry points you have:
"Generic, reusable, read-eval-print loop. By default, reads from *in*, writes to *out*, and prints exception summaries to *err*. If you use the default :read hook, *in* must either be an instance of LineNumberingPushbackReader or duplicate its behavior of both supporting .unread and collapsing CR, LF, and CRLF into a single \\newline. Options are sequential keyword-value pairs. Available options and their defaults: - :init, function of no arguments, initialization hook called with bindings for set!-able vars in place. default: #() - :need-prompt, function of no arguments, called before each read-eval-print except the first, the user will be prompted if it returns true. default: (if (instance? LineNumberingPushbackReader *in*) #(.atLineStart *in*) #(identity true)) - :prompt, function of no arguments, prompts for more input. default: repl-prompt - :flush, function of no arguments, flushes output default: flush - :read, function of two arguments, reads from *in*: - returns its first argument to request a fresh prompt - depending on need-prompt, this may cause the repl to prompt before reading again - returns its second argument to request an exit from the repl - else returns the next object read from the input stream default: repl-read - :eval, function of one argument, returns the evaluation of its argument default: eval - :print, function of one argument, prints its argument to the output default: prn - :caught, function of one argument, a throwable, called when read, eval, or print throws an exception or error default: repl-caught"
Common things to do here:
:init
: add your own setup for the REPL to use. E.g. use
some libraries:prompt
: display a differnt "state" than the ns:print
: use a pretty printer of some kindIt's worth mentioning, that every program you build (e.g. uberjaring), that contains the clojure.main
(e.g. the clojure-$VERSION.jar
) can run the REPL from that uberjar so you can run differn main
:s from there.
Self-advertisement: If you need further inspiration, these are "modified" REPLs I have done in the past:
Upvotes: 4