corgi-emacs / corgi

Unbundled Emacs configuration aimed at Clojure developers
179 stars 18 forks source link

clj-refactor, clj-kondo, clojure-lsp #22

Open plexus opened 2 years ago

plexus commented 2 years ago

Corgi aims to be a fairly minimal config, while at the same time being fairly complete when it comes to Clojure development. You should have a setup out of the box that gives you the amenities you would expect from a Clojure editing environment. But what does that mean, what do we include out of the box, and what don't we? I'm somewhat torn on some of these choices. Below I'll try to lay out my mental framework of how I'm thinking about these choices.

Currently we include clojure-mode, CIDER, clj-ns-name, and cider-connection-indicator. We still have clj-refactor listed as a dependency in corgi-clojure, so it gets installed, but we don't do anything to enable it (the dependency is a leftover that was intended to be removed).

So currently we don't include clj-refactor, clj-kondo, clojure-lsp, even though a lot of people are using these, and clearly get value out of them. The reason is that I personally don't use linters, and I've tried clojure-lsp and found it too immature. High CPU usage, a few times I had to kill Emacs. I've also had plenty of issues with clj-refactor in the past, although that's been a few years and I feel like it's pretty stable now.

The trade-off we need to think about is that each of these packages adds significant complexity, which means higher resource usage, more things that can go wrong, more layers to wade through when troubleshooting, and more things the user needs to learn about. That complexity can only be justified if we get enough value in return. key phrase: return on complexity

This value I think can be split into "passive" value, and "active" value. For instance: clj-ns-name automatically renames your buffers so they have the same name as the namespace name. That passively provides value, you don't have to know that that package exist or even that something is actively doing that, You automatically get value out of that. Syntax highlighting is another good example of passive value, and I imagine having a good clj-kondo setup out of the box can also provide passive value. You get warnings in your code without having to ask for them or having to know what is doing that. That means even complete beginners immediately get something out of it. passive return on complexity vs active return on complexity

clj-refactor provides some passive value, it automatically adds an ns declaration, but mostly it's active, you need to learn what it is, what it can do, and what the key bindings are to trigger it. I think clojure-lsp is similar (I may be wrong), there's a bit of passive value, but it's mostly active, you need to learn more things to make good use of it. Just setting it up involves a lot of informed choices. For packages like that the return on complexity is high for power users who take the time to study the docs and practice the key bindings, but it's low for a less advanced user who's still figuring out the basics of vim-style editing and interactive development. In fact it might be negative for new users who get overwhelmed with things they don't understand. "Smart" functionality can very easily get into people's way.

One of my annoyances with Spacemacs is that it loads a lod of things that only provide active value. Even after using it for years I would learn about packages that had been active all this time, that I didn't know exist, and that I had never used. I want to avoid that in Corgi. No "latent" functionality, we load the stuff that we know 90% of Clojure devs will get value out of.

So given all of the above I think the current situation is not wrong, we're being conservative so as not to load things that people might not get value out of, or that get into people's way. That said a lot of users are starting to swear by clj-kondo it seems, and I'm seeing a lot of appreciation for clojure-lsp as well, so I do want us to provide some kind of solution for those. My current thinking is a separate meta-package, maybe called corgi-clojure-smarts, that loads these two and sets them up.

But then we have to do it in a good way, make sure they have good defaults and integrate seamlessly, that any bindings are consistent with Corgi's approach to key bindings, and making sure that these things are properly explained in the Corgi manual. Our docs still leave a lot to be desired, but the goal is to have everything that is included with Corgi and that you need to actively know about to get value out of, to be explained in our own docs. You should be able to read the Corgi manual top to bottom and be productive, without having to branch out to other package's docs. (I guess I should write a separate issue for my vision on docs).

theophilusx commented 2 years ago

My 2 cents worth ....

Iff we wanted to include LSP support (either eglot or lsp-mode), the key would likely be in having a configuration which turns off LSP features already provided by cider and only leave functionality which adds benefit. Not yet convinced this is worth it. Will likely take a bit of time playing with it before I know for certain.

I think I only partially agree with your active value argument. For me, I don't really care about things being loaded that I don't use/need provided they don't get in the way. My biggest gripe with spacemacs was too often, my workflow was broken by additional packages I didn't use. I guess it is really the same argument in the end. For me, the more things you have installed and configured, the more complex and the more complex, the more opportunity for breakage and more time wasted tracking down issues. I don't mind complex configurations, provided that additional complexity does give me value.

So I would say no to clj-refactor, yes to flymake and clj-kondo and a watch and wait on LSP mode support. If we do decide to include LSP support, then we would remove flymake and clj-kondo.

plexus commented 2 years ago

Thanks Tim, that largely tracks with how I feel about things. Even though I'm not a Kondo user myself I do think its adoption is wide enough at this point that we need to have a good answer for that out of the box. The others we'll punt on, perhaps indefinitely.

practicalli-johnny commented 2 years ago

I have found clojure-lsp most valuable when joining an existing project, especially when it comes to a significant refactor or rewrite of the code (which is typically not well documented).

My own experience with clojure-lsp has very positive over the last 6 months and performance has been greatly optomised in that time. I no longer notice the analysis that takes place when opening a new project.

The visual components from emacs-lsp/lsp-ui used to be very disruptive, but are much more subtle default settings now. The only visual feature I disable is the documentation pop-ups - lsp-ui-doc-enable nil

I also found the cljfmt based formatting a little too opinionated, although there are documented settings to tone that down too. The formatting was where I found the most tension between LSP and CIDER in the past.

Hopefully Corgi will provide clojure-lsp as an optional feature, which is off by default. Providing a simple configuration to enable clojure-lsp with sensible key bindings would be much appreciated. I think this is less work that previous, but appreciate its still some amount of work.

plexus commented 2 years ago

We're erring on the side of doing less here, which is a general principle we're following. Corgi is meant to be a baseline config that people can build on, for it to do that it's better to not have things that some people might want, than to have things that some people might not want.

I'm going out on a limb with Kondo, since it means adding something that I have no intention of using, that I have no experience with, and where I don't have a clear image of what people expect of it. I have to rely on others to implement the integration, and try to muddle through the inevitable support issues as best as I can.

We'll see how that goes, adding Kondo seems an order of magnitude less risky to me than adding LSP. When dozens to hundreds of people are happily using our Kondo setup without a hitch then we can say we did a good job and can maybe reopen this conversation. No is temporary, yes is forever.

I also don't want this to become a snowball project that drags in ever more stuff. We're just a collection of packages. Other people can create their own packages. They can set up their own straight repos. Let's encourage a marketplace of ideas. Maybe someone makes a Corgi-style package for lsp that becomes so widely used that we decide to add it to the sample config, or we go a step further and link to their project from our straight repo and pin it in our version file. That would be a fantastic outcome because it'll feel like an integrated whole, but the package will have its own git repo, maintained by people who actually use and care about lsp.

theophilusx commented 1 year ago

Yes, I agree. For those who want a big all encompassing config, there are plenty already - spacemacs, doom, prelude, etc. All with decent clojure support. What we want here is something fairly minimal which sets up a decent key bindings scheme and does things in a way where it is easy for users to add/drop bits they do/don't need. I'm also hopeful that this will also result in people slowly extending and enhancing their personal config as demands/skills develop, leaving them with something they understand and can fix if/when it breaks rather than be stuck waiting for someone else to fix their issue because the setup is too complicated for them to udnerstand it fully.

I also don't want this to become a snowball project that drags in ever more stuff. We're just a collection of packages. Other people can create their own packages. They can set up their own straight repos. Let's encourage a marketplace of ideas. Maybe someone makes a Corgi-style package for lsp that becomes so widely used that we decide to add it to the sample config, or we go a step further and link to their project from our straight repo and pin it in our version file. That would be a fantastic outcome because it'll feel like an integrated whole, but the package will have its own git repo, maintained by people who actually use and care about lsp.

I see a strong similarity here with Clojure's approach re: collections of small libraries rather than large frameworks. In some ways, we have corkey providing a base interface (like an API) and a mimimal set of packages to provide a decent base configuration. Users can swap out packages for more complex or feature rich or with a different design philosophy. Just like you might swap out component for mount or integrant, you might swap out the corgi-clojure.el module for one which is based around lsp-mode (or eglot) instead or you might just add that functionality by drawing in anotgher package.

I've nearly finished a corgi-clojure-kondo package to add clj-kondo and once that is done, I would like to break out the corgi completion frameworks into their own corgi-completions package. My aim here is to make corgi a little more modular so that you can swap out parts easily without affecting other bits you want to keep. Having corgi-completions seems like a useful division as different people have different preferences in this area. Being able to swap out one for another while keeping all the other settings in corgi-editing would be useful.

My plan is to create a couple of packages which I will host on my github pages that are corgi compatible, but are not actually part of corgi main. People will be able to pull them in with use-package (got to love straight.el as there is no way I could be bothered creating and maintaining MELPA packages!). I will be responsible for handling issues against those packages. At this stage, I'm planning

I also plan to make my personal corgi setup repo available as I think people often find such examples useful. It should also demonstrate how easily you can build on and extend corgi to be your configuraiton.

theophilusx commented 1 year ago

I am currently working on an optional module for clj-kondo support. I also plan to add a module for LSP support, but not sure yet if this will be based on lsp-mode or eglot. I've used lsp-mode a bit and your right, current versions work quite well. However, I like the design pricipals of eglot as it also provides LSP support, but leverages of existing built-in funcitonality of Emacs rather than re-implementing or relying on additional external packages.

At this stage, how to add or reference additional modules for corgi-emacs is still at the discussion stage. One of the main aims of corgi-emacs is to keep it as lean as possible. It may be that corgi-emacs compatible packages live externally. Due to the use of straight to manage packages, adding such external optional modules would be trivial. This would also make the distinction between what is core (and maintained by core members) and what is a contrib module (maintained by external contributors) clear.