Take a look at example config files. Also get inspired by community configs.
Pomegranate is included on the classpath so you can dynamically load other libraries. Using pomegranate nREPL server can be included and started. For example you can put following into your ~/.closhrc
:
(defn start-nrepl
([] (start-nrepl 7888))
([port]
(eval
`(do
(require '[cemerick.pomegranate])
(cemerick.pomegranate/add-dependencies
:coordinates '[[org.clojure/tools.nrepl "0.2.13"]]
:repositories (merge cemerick.pomegranate.aether/maven-central
{"clojars" "https://clojars.org/repo"}))
(require '[clojure.tools.nrepl.server])
(println "Starting nrepl at" ~port)
(defonce server (clojure.tools.nrepl.server/start-server :port ~port))))))
Then start the nREPL server with:
(start-nrepl)
Connect to it from other client, for example:
lein repl :connect 7888
The current nREPL support is limited, for example the custom reader is not included. It can probably be added via middleware. If you have some experience creating nREPL middleware please leave a note in #88. So shelling out via nREPL at the momemnt needs to be done with sh
macros:
$ (sh-str echo hello nrepl)
$ (sh-value ls *.txt)
To enable Autojump refer to a following configuration.
If you are using direnv to switch an environment based on a working directory you can augment the closh-prompt
definition in the ~/.closhrc
like this:
(defn closh-prompt []
(source-shell "bash" "eval \"$(direnv export bash)\"")
; your prompt logic here
)
To use nvm put the following into your ~/.closhrc
:
(source-shell "export NVM_DIR=\"$HOME/.nvm\"; [ -s \"$NVM_DIR/nvm.sh\" ] && . \"$NVM_DIR/nvm.sh\"")
(defn args->str [args]
(->> args
(map #(str "'" (clojure.string/replace % #"'" "'\"'\"'") "'"))
(clojure.string/join " ")))
(defcmd nvm [& args]
(print (source-shell (str ". \"$NVM_DIR/nvm.sh\"; nvm " (args->str args)))))
cljaws is a project that integrates with closh and allows you to run AWS API commands with pure Clojure from the command line.
To use conda put the following into your ~/.closhrc
:
(source-shell ". ~/anaconda/etc/profile.d/conda.sh; conda activate")
Liquid is a text editor written in Clojure inspired by Emacs and Vim. There is a plugin that integrates Closh with Liquid. One cool feature is that command output is written into a text buffer and can be later edited and manipulated within the text editor.
Closure library is built in, so you can use it like so:
(require 'goog.string.format)
(goog.string.format "%03d" 7)
; => "007"
Often there is a need to do some work with multiple files. An example might be to convert all text files in a directory to PDFs for printing. A single file can be converted with unoconv abc.txt abc.pdf
.
To convert all txt files in a directory with bash
you can do:
for f in *.txt; do unoconv "$f" `echo "$f" | sed 's/\.txt$/.pdf/'`; done
Here is an example how you could do that with closh
:
(doseq [f (expand "*.txt")] (sh unoconv (str f) (str/replace f #"\.txt$" ".pdf")))
In bash it is usually done using subshell or directory stack:
# Using subshell
(cd SOME_PATH && exec_some_command)
# Using directory stack
pushd SOME_PATH
exec_some_command
popd
Possible solution in closh with a macro:
(defmacro with-cwd [dir & body]
`(binding [closh.zero.platform.process/*cwd*
(atom (closh.zero.platform.process/resolve-path ~dir))]
(sh ~@body)))
Then it can be used as:
(with-cwd "src"
pwd \;
ls -l)
Useful to reference files relatively to a location of running script. In bash usually done with a following idiom:
__dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
It can be done in closh with:
(def dir (-> *file* clojure.java.io/as-file .getParentFile .getCanonicalPath))
You can use datoteka library which provides helper functions for tests on files like path?
, file?
, absolute?
, relative?
, executable?
, exists?
, directory?
, regular-file?
, link?
, hidden?
, readable?
, writable?
.
Add following into your ~/.closhrc
.
#?(:clj
(do
(require '[cemerick.pomegranate])
(cemerick.pomegranate/add-dependencies
:coordinates '[[funcool/datoteka "1.1.0"]]
:repositories (merge cemerick.pomegranate.aether/maven-central
{"clojars" "https://clojars.org/repo"}))
(require '[datoteka.core :as f])))
Then you can use those functions for example like:
(f/executable? "myapp") && ./myapp