Fork me on GitHub
#clojure
<
2023-11-15
>
macrobartfast06:11:14

Is there anything that adds a dependency to deps.edn with only the name? For example, the user only has to type 'clj-http' and the tool finds the latest version and adds it to the file.

macrobartfast06:11:03

Oh, that's perfect!

practicalli-johnny10:11:53

https://practical.li/clojure/clojure-cli/practicalli-config/ aliases include :search/libraries that has a --format:save option to add the matching libraries to the project deps.edn file, e.g. to add the jetty library

clojure -M:search/libraries '-F:save' jetty 

imborge11:11:16

There's also clj-refactor if you use emacs

seancorfield18:11:21

And just so folks know the plain ol' tools.deps / CLI way to find versions:

clojure -X:deps find-versions :lib clj-http
Downloading: clj-http/clj-http/maven-metadata.xml from clojars
{:mvn/version "3.10.1"}
{:mvn/version "3.10.2"}
{:mvn/version "3.10.3"}
{:mvn/version "3.11.0"}
{:mvn/version "3.12.0"}
{:mvn/version "3.12.1"}
{:mvn/version "3.12.2"}
{:mvn/version "3.12.3"}
You'd have to add it manually but this lets you find the most recent n (default 8 ) versions:
(~/clojure)-(!2005)-> clojure -X:deps find-versions :lib clj-http :n 2
{:mvn/version "3.12.2"}
{:mvn/version "3.12.3"}

clojure-spin 1
marc12:11:10

How can I make a parameter dynamic in https://github.com/oliyh/martian? (more context in thread)

👀 1
1
marc12:11:15

I am trying to use the Brevo API https://developers.brevo.com/reference/intro/my-requests from Martian. There is the concept of Attributes which are dynamic (configured at account level) and thus are not expressed via the Swagger spec. See for example :create-contact which accepts attributes . When I try to set that I always get Invalid key errors. How can I order Martian to ignore the schema of attributes or better still: specify the schema for the field (because I do know it)?

marc12:11:15

Current code:

(defn create-brevo-contact [brevo-api {:keys [email name control periodicidad]}]
  (martian/response-for brevo-api :create-contact
                        {::martian/body 
                         {:email email
                          :update-enabled true ;; should never happen, but who knows.
                          :attributes
                          {:NOMBRE name
                           :FISCAL_GRIST control
                           :PERIODICIDAD_DOCS periodicidad}}}))
The keys inside attributes are my custom Brevo fields. I guess this would be the appropiate schema:
(def brevo-attributes-schema
  {:NOMBRE s/Str
   :FISCAL_GRIST s/Bool
   :PERIODICIDAD_DOCS s/Str})
But I have no idea on how to plug this schema inside the :create-contact so...:
Execution error (ExceptionInfo) at schema-tools.coerce/coerce-or-error! (coerce.cljc:24).
Could not coerce value to schema: {:createContact {:attributes {:NOMBRE disallowed-key, :FISCAL_GRIST disallowed-key, :PERIODICIDAD_DOCS disallowed-key}}}

oliy13:11:24

Ideally the API would specify that additional keys are ok, or even that there is an attributes key which is a map - that would at least prevent the errors

oliy13:11:24

If you are bootstrapping from the swagger json I'm not sure there is a way currently to merge in any other schema. The alternative is to specify the schema yourself and call the other bootstrap function

marc15:11:01

Thanks! I'll try to dump the API to an EDN, change it and work from there then. I'll open an issue on Martian to see if merging schemas is a thing!

wcohen16:11:25

dumb macro question — i’m trying to ensure thread safety on an operation, which requires entering and exiting a native context before and after statements:

(defmacro foo
[body]
`(locking lock
    (.enter context)
    ~body
    (.exit context)))
seems like it’ll get the job done, but will simply return the exit result rather than the results from the body text. I see that with-open performs a recursive set of opening and closing files using bindings and finally. If I want to get the output of body above as what returns from the macro, should I just be wrapping the ~body in a try clause with the .exit in finally?

p-himik16:11:51

Even if you don't want to get the result of ~body, you should be using try+`finally`.

☝️ 2
oyakushev16:11:46

Also, I suggest using https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html instead of locking.

(def lock (java.util.concurrent.locks.ReentrantLock.))

(defmacro foo [body]
  `(do (.lock lock)
       (try (.enter context)
            (try ~body
                 (finally (.exit context)))
       (finally (.unlock lock)))

wcohen16:11:38

You all are fantastic. Many, many thanks. After all these years, my first macro!

🎉 3
emccue16:11:13

Does anyone remember the name of that SQL library that is built on honeysql and you tell it about your relationships then it can query nested structures in one go?

emccue17:11:43

hmm no it had a query language that was all edn

emccue17:11:53

That might be it

lukasz17:11:06

ah nice, I was looking for something like this too

p4ulcristian19:11:51

Hello, I am trying to use clojure-lsp.refactor/move-form , but I don't know how to create the components parameter in`(move-form zloc source-uri {:keys [db*] :as components} dest-filename)` https://cljdoc.org/d/com.github.clojure-lsp/clojure-lsp/2023.10.30-16.25.41/api/clojure-lsp.feature.move-form?q=move-form#move-form I am trying to build my own editor, and I try to add some refactor capabilities. 🙂 Can I get some help with understanding this? I found clojure-lsp.db/db* but this is only part of the components map

ericdallo19:11:51

Hey, interesting use case

ericdallo19:11:04

But that is not supposed to be used publicly, it's a internal ns

ericdallo19:11:29

the ones intended to be used publicly are in the clojure-lsp.api but move-form is not exposed there, although it could be

p4ulcristian19:11:40

Thank you! But is it possible to use move forms with clojure.lsp? Into other namespace? I already tried with rename, it worked only in the same namespace

ericdallo19:11:07

rename is supposed to work on multiple ns, the move-form one is still "alpha" as has lots of corner cases to make it work

ericdallo19:11:15

but rename should work on other ns as well

ericdallo19:11:28

if you are using via clojure-lsp.api is supposed to work.

ericdallo19:11:26

but TBH, since you are creating your own editor, why not just use as an LSP and not an API? then all clojure-lsp features would work out of the box

p4ulcristian19:11:44

I am not familiar with the concept yet. In the first the first place I wrote an S-expression editor, a basic one. And I found clojure-lsp, started the server, using rename function, and wanted to iterate on that. Any guides on how to implement an lsp?

ericdallo19:11:49

yes, you should first learn what is and how an LSP works, let me share with you some content

❤️ 1
ericdallo19:11:14

https://microsoft.github.io/language-server-protocol/overviews/lsp/overview/ is a overview on how it works • https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/, it contains all detailed information about how clients (editors) should communicate with servers (clojure-lsp) • there is a talk I teach the basic of LSP https://www.youtube.com/watch?v=grL3DQyvneI&amp;ab_channel=LondonClojurians

ericdallo19:11:29

LMK if you need more help on that, I'm always available on #CPABC1H61 as well

ericdallo19:11:25

By any chance your client is made in Clojure? if so, you should consider using https://github.com/clojure-lsp/lsp4clj to build the client LSP part

p4ulcristian19:11:01

I read the files with clojure, then handle it with rewrite-clj on the clien-side with ClojureScript. Now I tried out clojure-lsp started it, and using it from clojure, through POST requests. So I guess my client is made in Clojure?

ericdallo19:11:10

I see, you can use the clojure-lsp.api but I suggest use as the LSP protocol recommends, spawning a process and exchanging JSONRPC messages between your editor and the server as this is way more tested and how it works for all other editors, lsp4clj should help a lot on this communication as already has functions to do all this complex stuff and it's how I built https://github.com/clojure-lsp/clojure-lsp-intellij/blob/master/src/main/clojure/com/github/clojure_lsp/intellij/server.clj#L23 as well

❤️ 1
p4ulcristian19:11:44

Thank you for the starting points, I'll look into it!

👍 1
p4ulcristian21:11:52

I looked into it, way too complex for my usecase. When move-form comes out from alpha. will it be a part of the clojure-lsp.api ?

ericdallo21:11:47

Yes, but it's one of the most complex refractors to implement, there is a open issue describing all the cases

p4ulcristian21:11:47

For me a half baked solution would also work. I have read the issue. I use Clojure for a while now, hobby and work also, and refactoring is a major pain. But I understand that until it's not ready, for many people it would just break things. I hope someday it will be solved :)

p4ulcristian21:11:21

or maybe an clojure.lsp.alpha.api namespace for the brave and true :DD

ericdallo22:11:21

but there are like more than 40 existing stable refactors if you check clojure.feature.refactor and move-form is the only one that is alpha, even so, they are not on clojure-lsp.api but could be added easily, similar to the rename feature

p4ulcristian22:11:41

I checked them out. Nice work! In my workflow rename is most important, move to other namespace is second most important. I am sure that sooner or later a solution will come out, How do you move your functions around? Find and replace?

ericdallo22:11:01

unfortunately, yes. You can see all the corner cases in https://github.com/clojure-lsp/clojure-lsp/issues/566, we should evolve the feature considering those cases

p4ulcristian23:11:27

I'll have a run at it myself. Last week I thought a lot about this. I see the problem divided in three sections. Moving to child, parent, or neighbour namespace. The other question is if the moved function calls functions or is called by functions from/in the same namespace. If they do, sometimes we need to move all the caller functions, or all the called functions, depending if we copy to child , parent or neighbour namespace. The rest is playing around with the require vector. Of course saying something is easier then doing it, but I feel like I need this tool, because I want to use clojure for a long time, as comfortably as I can. I hope to find some helpers to find the references for a little head start.

ericdallo23:11:09

feel free to help with Pull requests or issue describing the problem and how you intend to fix it so we can confirm it makes sense, help is really welcome :)

p4ulcristian23:11:02

I'll try a proof a concept first, that would be the most helpful, also clears up my misunderstandings about the problem. If I achieve something worth checking out I'll link it here.

Bailey Kocin19:11:03

Are there are any tools that can take compojure defined routes and produce some OpenAPI documentation, much like Swagger in Python or something like that. Or anything like that for the Clojure ring ecosystem I guess?

p-himik19:11:30

Reitit has it.

hiredman19:11:11

there are things like https://github.com/metosin/compojure-api which is a compojure like routing library that can do it

hiredman19:11:55

compojure itself is all just functions, which are really only setup to do one thing, which is to be invoked on a request map, so extracting metadata about routes to generate documentation is tricky

jumar19:11:14

Just that compojure-api is unmaintained I think so I would not use it for anything new

Bailey Kocin19:11:13

Perhaps I can write something quick and dirty just to get the URLs and params for my routes and spit it into an openapi spec then from there use an existing tool to convert that to HTML

Bailey Kocin19:11:17

Thanks all 😄

lukasz19:11:13

I had the same need from Compojure, but due to how it works it's not easy to list the routes - moving to a declarative, data driven router was the solution (in my case it was just a... map of endpoints -> handlers + schemas, all routes were POST only. Regarding generating HTML - if you get the spec, then you can use Swagger UI to get the HTML - there's a 100% standalone version of it: https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/installation.md#plain-old-htmlcssjs-standalone

practicalli-johnny09:11:12

If there is a yaml or json spec for the API it can be used with https://editor.swagger.io/

1