Closed borkdude closed 5 years ago
Not yet, I think I would like to purposefully delay support for that. Closh is still very early in the development, syntax may change a bit. Which is bearable for interactive use but I don't want to break people's scripts.
It is actually quite nice to write scripts on top of lumo itself with shelljs used for more convenience. Maybe I can write a guide with some examples how to do that.
As long as the changes are listed somewhere (e.g. in a CHANGES.md
), so I know what to upgrade, I wouldn't mind having breaking scripts. Example of lumo + shelljs is more than welcome!
I think that second example should read:
#!/usr/local/bin/closh
ls |> #(println (count %))
(I.e. transpose the space and "t" before "%".)
FWIW, I'm toying with the idea of re-implementing portions of my email-server (MTA) setup, currently a hacked version of qmail, in some variant of Clojure, and was looking to closh for fast script startup times (having investigated ClojureC earlier this year and been pointed to ClojureScript on v8 generally by its author in a nice chat we had).
It's still unclear to me whether I want to write scripts in closh, lumo, ClojureScript, or even Clojure (since the startup time I'm measuring for java -jar clojure.jar < /dev/null
seems close to that of closh < /dev/null
and not much worse than lumo < /dev/null
-- though still some 400x slower than bash < /dev/null
).
Anyway, I was thinking that perhaps experimental support for this could be provided by requiring a --VBETA=n argument that must match the version of the shell language and features implemented therein, in order to read the input file (and/or the rest of the command-line arguments)?
That way, only those of us willing to take risks here would be able to get something like this to work:
#!/usr/bin/closh --VBETA=0
ls |> (count)
(And, yes, I'm willing to help out here...or elsewhere with Clojure, once I find my feet and some time.)
Hi, if startup time is priority and you don't mind the compilation step then I can think of two options:
1) Write it in ClojureScript, then compile to JS and run it with vanilla node.js (which uses the V8 engine). That should be like an order of magnitute faster than lumo. 2) Write it in Clojure and then try to compile it into native executable with Graal.
An interesting option might be to utilize 1) or 2) and use closh as a library to make it easier to shell out to existing commands. When you type commands in closh it internally wraps them in sh
macro which does the transformation.
Closh's relationship to lumo is that closh is just a program that runs using lumo. I am currently focused on the interactive mode and haven't spend any time making the script mode work. Therefore if the compilation step is not acceptable then it might be better just to run lumo directly and use closh as a library:
#!/usr/bin/env lumo
; require closh macros here
(sh ls |> (count))
I am in currently in the process of porting closh to also run on JVM, so very soon it will also be possible to run it with Clojure proper. Here is running the code from dev branch:
#!/bin/sh
clojure -Sdeps '{:deps {closh {:git/url "https://github.com/dundalek/closh.git" :sha "f6416f81bf132a037fcf437ed07dc09adb4c14b7"}}}' - <<END
(require '[closh.zero.macros :refer :all]
'[closh.zero.core :refer :all]
'[closh.zero.pipeline :refer :all])
(println "hello clojure")
(sh echo hello closh)
(println "Number of files:" (sh-val ls |> (count)))
END
Please note were at the frontier here pushing boundaries so expect some rough edges and unexpected bugs. I am happy for any help and bug reports.
Another idea to support scripting from a closh shell (to have fast boot time) is to have a command say closh-script
. This command would be built from another command eval-clj
[1]:
Unfortunately, evaluation in cljs is asynchronous and namespaces need to be required upfront I believe (see output [2]). I'm guessing though that this approach could work quite well for the Java version, as this tackles both issues. I wasn't able to test this with the dependency mentioned here though [3]
[1]
(defcmd eval-clj [script] (cljs.js/eval-str (cljs.js/empty-state) script "dontcare" {:eval cljs.js/js-eval} cljs.core/identity))
[2]
$ echo "(cljs.core/range 10)" | (eval-clj)
WARNING: Use of undeclared Var cljs.user/sh
⬆
WARNING: Use of undeclared Var cljs.core/range at line 1
[3] Output of clj script
org.eclipse.jgit.api.errors.JGitInternalException: Missing unknown f6416f81bf132a037fcf437ed07dc09adb4c14b7
I've written initial design proposal for the script mode here: https://www.reddit.com/r/closh/comments/a71usj/script_mode_design_proposal_for_closh/
Any feedback appreciated.
Initial iteration of script mode has now landed in the latest release v0.4, you can read how to use it in the scripting docs. I will be glad for any feedback, experience or issue reports.
Is it possible to pass a script to closh, so you can execute a script from, say, bash?
or