This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-05-01
Channels
- # announcements (6)
- # babashka (8)
- # beginners (16)
- # calva (36)
- # clara (3)
- # clerk (6)
- # clj-commons (9)
- # clj-kondo (59)
- # clojure (174)
- # clojure-europe (13)
- # clojure-nl (1)
- # clojure-norway (3)
- # clojure-uk (7)
- # conjure (1)
- # cursive (44)
- # datomic (8)
- # events (1)
- # gratitude (1)
- # hyperfiddle (7)
- # introduce-yourself (1)
- # keechma (1)
- # london-clojurians (1)
- # missionary (2)
- # off-topic (20)
- # ring-swagger (1)
- # squint (37)
is --dependencies
like a --quiet
flag? or does it only lint dependencies?
purely for curiosity: i see pretty different times when running with and without the flag. any idea why that would be the case?
interesting, thanks
just in case it's helpful:
$ time bin/clj-kondo
+ clj-kondo --parallel --lint .clj-kondo/config.edn dev src test
linting took 12150ms, errors: 0, warnings: 0
real 12.23s
user 12.98s
sys 1.00s
vs
$ time bin/clj-kondo --dependencies
+ clj-kondo --parallel --lint .clj-kondo/config.edn dev src test --dependencies
real 9.94s
user 11.07s
sys 0.77s
Not sure about this. But could clj-kondo figure out if a lib is callable with -M, -X or -T ? I don't know if it's easy to infer from the code itself? Or if it could given the lib annotated its entry points ? Either way, then maybe we could have Zsh completion leverage clj-kondo or something to auto complete tools aliases
If the lib annotated being able to called with -X, then you could query it using clj-kondo using metadata from the analysis
-X
could invoke any function in the entire codebase that can accept a single hash map argument (it will happily invoke private functions). Same with -T
.
-M
can invoke any -main
in any namespace anywhere in the codebase.
Since clojure.main
exists in every Clojure program, all libraries are invokable with -M
, and core contains several functions that will accept a single hash map so -X
can be used with all libraries too.
In other words, you'd have to have some sort of metadata annotation -- but then the completion would not be able to offer -M
/`-X` in cases not specifically annotated but that would also work.
And those options can have multiple aliases so I'm not sure how completion would work since the invokable functions available depends on the aliases used to construct the classpath which appear after the option itself?
Ya, the annotation is probably better. Can't you just show all of them? If the classpath has 3 aliases, the you can execute any of their -X or -M no?
A classpath has no aliases.
I don't even think the runtime basis knows which aliases were used (on the command-line) to build the classpath...
I'm confused, why the classpath? This would be based of the clj -X:deps aliases list. Or what you typed in the command, like clj -M:foo <tab> shows all annotated -M of foo
So like, for all aliases listed by clj -X:deps aliases it would analyze them and also list all their -M and -X and -T from their annotations.
Maybe we don't even need clj-kondo if we just come up with some convention of a file in the libs that can document their -X, -M and -Ts
You said "If the classpath has 3 aliases"
So I looked at the runtime basis and there is :basis-config
in that which lists the :aliases
used as part of building it. So a program started via the CLI can tell what aliases were used to run it (I think that's relatively new?).
clojure -X:deps aliases
just lists aliases and where they are from (root, user, project). It does, currently, assume aliases have hash maps as their values which is an incorrect assumption (there's an Ask and a Jira for that).
Looking at :aliases
in deps.edn
files alone does not give you enough information to determine whether -M
or -X
is appropriate (or -T
or -A
).
To find annotations in source code, you'd need the classpath computed to know where to look.
I just want clj <tab> to auto-complete with available aliases, but also their sub-commands. Or some some way at the command line I can see what I can do in a project basically.
I understand what you want. I just don't think it's possible.
Currently, I open the deps.edn, look at the list of aliases, google them, look at their readme, and that's how I know how to call them, if I need -X, -T, and what sub-commands they take. If that doc was some easy to lookup thing, then we could automate that entire lookup no.
How exactly do you envisage that actually working?
At what point in typing clojure -M:thing ...
or clojure -X:other ...
do you imagine <tab>
completion to provide something useful?
You're saying it's hard to know whether to use -M
or -X
with an alias, but on the command-line you've already had to type either -M
or -X
before you type the alias names...
Well, there's two possible UX. First one is something that just lists the available aliases and their commands(or help). Listing aliases is already here, though there's a bug but I'm assuming it works. So the bit missing is fetching for each some documentation to display. If that doc is in some structured format by convention, it could have a unified rendering. Ideally this is a feature of the Clojure cli itself (or -X:deps). But it could be something else that offers it. It means that either lib authors have to provide this file with this structured doc, or someone else has to provide it externally. The second UX is autocomplete. This is probably shell dependent. But it would be that when you type clj <tab> it just list all aliases and their available commands flattened. If you type clj -X:<tab> it lists the same filtered on those that can be called with -X, same for clj -T:<tab>, etc.
> available aliases and their commands(or help) What is "their commands(or help)"? Where does that come from?
Where exactly is TBD. But here's one possibility. It comes from a file called doc.edn which is top level in the package
Top-level in what package? Aliases don't correspond to single packages.
Aliases might have :extra-deps
or might not. They might specify multiple libraries.
> If you type clj -X:<tab> it lists the same filtered on those that can be called with -X
The problem here is that any alias can follow -X
. Consider an alias that just has :jvm-opts
to enable some Clojure behavior. That can be used with other aliases which may or may not have :exec-fn
or :exec-args
.
You can say clojure -X:lots:of:aliases some-ns/my-fn
and it will execute (some-ns/my-fn ...)
regardless of what's in those aliases.
For each package in :deps, :extra-deps or override-deps lookup their doc.edn if they have one at the root, and is so, display their current on a formated way or use it to auto complete
Even if aliases include :ns-default
, :exec-fn
, or :exec-args
, you can still use them with -A
or -M
.
> For each package in :deps, :extra-deps or override-deps lookup their doc.edn if they have one at the root
This would require fetching every possible dependency/version and looking in the downloaded artifact for doc.edn
... and different aliases can pull down different versions of those artifacts that might have different doc.edn
files.
Well, alternatively, I thought it might be the alias itself that would expose the doc. So on the alias you might need :doc key where it points to the structured doc for that alias. Could be a git repo or local file or inline doc
Ya, deps already pulled them all down and looks inside them to retrieve the deps.edn so I don't see the problem?
Then it would be up to the user to put that :doc
key into each alias -- which means they'd have to figure that out by looking at the repo where the instructions were on how to "install" the library's alias -- which seems like what you're trying to avoid?
I'd love a way to also auto-install the alias the first time, ala brew install, but I'm not tackling this here haha. It's less of a big deal if it's a one time thing.
I don't think you've thought this through... the artifacts that you want to look inside depend on processing the aliases... so you can't know whether to use -M
or -X
until after you've already selected the aliases.
As for annotating deps.edn
manually, sure, you could do that. But everyone would have to do it for each alias they added to each project's deps.edn
file, and that annotation would either need to be in the library's readme/docs or the user would have to figure it out when they added the alias manually, and also add this "documentation annotation".
It wouldn't be too bad. If say I want to use antq. I copy/paste the alias from it's readme. If that alias includes the doc or a reference to it's doc. Now I should be able to list the aliases in my deps.edn or it's parents and also show the antq doc next to it's alias entry.
Now if I have an alias to compile my project. I can add doc to it saying that "Used to compile project, options are X, Y, ..." And I mean the doc could be a bit better than a plaintext string. So maybe it has a :subcommands, and what not.
OK, so "by convention" pick a key that is used for documentation, and have that key used by some tool that displays it... sounds like it really needs to be part of the CLI and -X:deps aliases
would use it... so go create an Ask for that (I'd upvote it).
And if a user decides to combine multiple libraries into a single alias, they can use that doc key as they wish.
And if users want a library to explain usage automatically, they can create an issue or submit a PR to add this doc key to the library's readme/docs.
(it needs to be a standard key across all libraries/tools which is why I think it needs to be in the core CLI itself)
Ya, I think that be good enough. Now if I pull down a project for example, I know how to quickly list everything I "can" do in this project. By seeing the aliases and a doc about how to use each one and what they are for.
And the "nice" thing about this approach is that it is totally opt-in, open-ended, and doesn't require tooling to try to locate/inspect artifacts at all.
LMK when you've created the Ask so I can go upvote it π
Sounds good. I'm juggling a baby so it might take some time, but I'll remind you when I do haha.
I suspect I'll have that image in my head every time I see you post messages for the next several days π
didbus types with one hand while throwing a baby in the air with the other... π¨βπΌ:skin-tone-2:
I resisted that urge... barely...
Itβs expected that (#'myfun this arity is wrong)
will go unreported right?
Hmm, good point:
$ clj-kondo --lint - <<< "(#'inc 1 2)"
linting took 10ms, errors: 0, warnings: 0
I guess this could be improvedKinda off topic, but I'm curious now, what is the point of using #'
before the function name?
We use it in tests to add unit tests for private functions. We configure clj-kondo to allow this kind of private var access in tests, but not in production code, e.g. something like:
:ns-groups [{:pattern ".*-test$" :name test-namespaces}]
:config-in-ns {test-namespaces {:linters {:private-call {:level :off}}}}