Fork me on GitHub
#clojure
<
2023-05-24
>
bherrmann01:05:52

If I have a project at ~/somepath/deps.edn and I want to execute the '-main' in namespace 'hello', how do I do that from an arbitrary directory - other than writing a 3 line shell script;

#!/bin/bash
      cd ~/somepath/
      clojure -X hello/-main $*
I want something like, $ clojure ??? ~/somepath/deps.edn -X hello/-main ...

2
Alex Miller (Clojure team)01:05:21

You can’t, but you can include it as a local dep somewhat cumbersomely

Alex Miller (Clojure team)01:05:07

clojure -Sdeps ‘{:deps {a/b {:local/root “/some/path”}}}’ -X hello/-main

💡 4
seancorfield01:05:28

Depending on what you're really trying to do, I'd probably do:

(cd ~/somepath; clojure -X hello/-main ...)
which leaves you back in the directory you started in.

seancorfield01:05:22

(I often run (cd <somewhere>; <do something>) style commands when I want to stay where I am but run a command somewhere else)

bherrmann01:05:04

True... well since you asked... I'm trying to write a todo cli app which uses datomic. So I want to do a "list", "add", "delete", "all" and have it invoke 4 functions (or main with an extra argument.) Sort of a datomic hello world of sorts. My thought was to use three aliases. $ alias tlist = 'bla bla; clojure bla bla main bla tlist' <-- lists todo items not yet done $ alias tadd= 'bla bla; clojure bla bla main bla tadd' <-- adds a new todo item $ alias tdone = 'bla bla; clojure bla bla main bla tdone xx' <-- marks a todo item done $ alias tall = 'bla bla; clojure bla bla main bla tall xx' <- shows all todos current and marked done

bherrmann01:05:15

Seems a tad clunky, but my goal is to be able to invoke these from any directory in the filesystem...

bherrmann01:05:19

so I could do the alias xx='pushd; cd ....; clojure ....; popd' or use a shellscript for dispatch... its fine.

bherrmann01:05:14

oh, I see you did the () so it runs in a subshell... clever that bit.

seancorfield01:05:47

Right, then you don't need pushd/`popd`

👍 2
seancorfield01:05:44

I have a ~/bin directory on my PATH and tend to drop stuff in there rather than use aliases much -- then you don't have to worry about how to process command-line arguments in an alias...

skylize03:05:24

> I often run (cd <somewhere>; <do something>) style commands when I want to stay where I am but run a command somewhere else > Great tip! This feels like something I should have already been doing regularly for a long time. Yet I have never used it before.

seancorfield03:05:38

A common one:

for d in oss/*; do (cd $d && git pull); done
Updates all of my open source projects.

borkdude06:05:18

babashka supports this pattern now: when you invoke a script in a "remote" directory, it respects the bb.edn in that remote directory. This turned out to be pretty handy for system-wide scripts, so you don't have to change the current working directory or write a bash wrapper

pesterhazy06:05:57

Babashka also supports the --config argument, which allows you to specify the location of its config file. Relative paths are resolved based on that file's location.

pesterhazy06:05:44

This would be a very useful addition to clojure cli, as it avoids messing with the current working directory or wrangling edn on the command line

pesterhazy06:05:20

Would this be appropriate as an Ask Clojure @U064X3EF3?

borkdude07:05:21

deps.clj already supports -Sdeps-file which is similar

borkdude07:05:21

except that it won't compensate for relative paths, local/roots, etc unlike bb's --config

borkdude07:05:14

you can test this with bb clojure -Sdeps-file if you have bb installed

pesterhazy10:05:15

(Just to be clear, because I was confused initially – deps.clj is a faithful but unofficial port of the tools.deps bash script)

borkdude10:05:00

yes, deps.clj is the clojure CLI rewritten from bash to clojure

Joshua Suskalo16:05:02

So the original question is about being able to invoke an arbitrary clojure application from any directory. The trouble with cd-ing into the directory is it changes your working directory, which means you no longer have access to the files at the shell's pwd. I would recommend in this case that you use a clojure tool installation with a local dep coordinate.

clj -Ttools install com.myself.local/my-tool '{:local/root "/some/absolute/path"}' :as local-tool
This can then be invoked from anywhere as
clj -Tlocal-tool fun-name :some '"args"'

👍 2
2
Joshua Suskalo16:05:41

Although if you intend to distribute this to anyone besides yourself, I might recommend that instead of using the clojure tools cli in order to provide arguments, you might look into using jlink and jpackage to produce a standalone version of your application which you can then distribute via a package manager, and invoke like a normal command line tool.

borkdude16:05:07

or graalvm binary

borkdude16:05:11

or babashka CLI

Joshua Suskalo16:05:22

Yeah, both are also good options.

Joshua Suskalo16:05:05

For my own part I think that graalvm native binaries are good but losing classloader stuff is a pretty big cost for some applications and with AOT and jpackage you can still get pretty good startup time.

👍 2