cursive icon indicating copy to clipboard operation
cursive copied to clipboard

Allow using cljfmt configuration

Open justinstoller opened this issue 8 years ago • 14 comments

Currently my company has a clj formatting guide. Emacs and Vim users have taken up using cljfmt to enforce this standard (using a shared lein-parent project). Getting IntelliJ/Cursive users to adopt changes is problematic as it requires building and updating a second artifact outside of the project's code base.

I would prefer if Cursive could read any configuration in lein's :cljfmt section (ideally honoring any lein-parent settings) and use that data as an input to format a project.

justinstoller avatar May 13 '16 21:05 justinstoller

Just so I'm clear, is the problem that the formatting is specified in two places, or can you not match cljfmt's output from Cursive?

cursive-ide avatar May 14 '16 01:05 cursive-ide

In my case I can match cljfmt, so my vote on this issue is because I have configuration in two places.

a613 avatar Feb 10 '17 15:02 a613

Any updates on this?

matan129 avatar Apr 01 '21 18:04 matan129

Sorry, I've moved on. Feel free to close.

justinstoller avatar Apr 02 '21 20:04 justinstoller

This issue is actually very relevant for me, so I'd actually like to keep it open until resolved.

matan129 avatar Apr 02 '21 23:04 matan129

Our team has temporarily shrunk to a few people, so it would be the least painful time to converge on some solution, which works well with many editors and convert our codebase.

I'm personally drawn towards the hyper-minimalistic https://tonsky.me/blog/clojurefmt/ approach. since it works out of the box with Cursive and clojure-mode in Emacs (if I understood the discussions well).

According to the discussions on https://github.com/clj-commons/formatter/issues/9 , it can even work with parinfer and with a few extra simple rules, it can cover vast amounts of situations, supporting lots of different schools of thoughts.

Low complexity, zero configuration solution, without the need for static analysis or a REPL connection or spawning an external formatting tool, at the cost of a few weird formatting situations, which could be pretty much remedied by adding an extra line. Sounds like a great compromise to me...

But, I don't understand the problem and the potential pitfalls fully and I haven't even tested it yet across Cursive and Emacs...

For example, I'm unclear on how does indentation is computed during editing, when you press Enter. It's not like an external formatter would care about cursor position... but this is also discussed to some extent on that GitHub thread.

onetom avatar Aug 06 '21 13:08 onetom

More generically, if cursive could use and cli formatter instead of the built in, that would fix this issue. cljfmt has a lein plug in and can be called like lein cljfmt fix /src/somefile.clj. If the format code command called that based on the active file, then any lein available formatter can be used instead.

sirmspencer avatar Jun 22 '22 18:06 sirmspencer

@sirmspencer as i understand, the problem with external formatters is maintaining the cursor position, since batch-mode/non-interactive formatters has no concept of a cursor. as a result, reloading the formatted file, there might be something entirely different at the same row and column, as it was before formatting.

That being said, I would rather live with such a small annoyance, just to achieve code-formatting consistency across tools.

onetom avatar Jun 25 '22 11:06 onetom

@sirmspencer Yes, this is something I need to put in a FAQ somewhere, since it comes up periodically. The formatter in IntelliJ is deeply embedded in many operations, and simply replacing it with an external formatter isn't really possible. As just one example, when you press enter at any point in the code to create a new line, the formatter is invoked to figure out where the caret should be placed on the next line. Similarly, as @onetom mentions, if an external formatter is invoked to reformat a file, your caret position as you perceive it will almost certainly not be maintained.

cursive-ide avatar Jun 25 '22 22:06 cursive-ide

I found a file watcher plugin after posting this. I think that mostly takes care of everything. I have the beginning of some instructions on how to set that up for cljfmt. Its on my work computer, so ill try to remember to look that up tomorrow.

sirmspencer avatar Jul 19 '22 00:07 sirmspencer

Hey @sirmspencer it'd be nice to share what you found here. I'm having the same problems.

reify-marcio-faria avatar Aug 12 '22 17:08 reify-marcio-faria

Hey @sirmspencer it'd be nice to share what you found here. I'm having the same problems.

Here is the section from my internal wiki. It may have some company specific policies, but is generally about getting different envs to be set up the same.

Auto formatting
Following a guide is a great start towards easy to read code. Using tools that does the formatting for you, makes the whole process seamless. The tool with the most reach at this time is [cljfmt](https://github.com/weavejester/cljfmt). cljfmt can be configure inside the project.clj file so that the rules are a part of the project and easily reused by any developer.

There are other formatters out there that may be the default formatter on installation. Notably intellij with Cursive has its own formatter built in. The rules in the intellij editor are hard to export, share, and update. The overall goal is to avoid conflicts between formatters and incorporate the best of each. However, this will not initially be 100% possible.

Dev installation
Emacs, VIM, VSCode, and Atom have native plug ins or tools that run cljfmt. A quick google search should lead to set up instructions. Don't forget to enable format on save

intellij with Cursive does not come with a direct plug in for cljfmt, but can still be set up to do run it.

Disable auto format for the built in formatter
https://www.jetbrains.com/help/idea/reformat-and-rearrange-code.html#reformat-on-save
Install file watcher plugin from file
https://plugins.jetbrains.com/plugin/7177-file-watchers/versions
https://www.jetbrains.com/help/idea/managing-plugins.html#install_plugin_from_disk
Set up file watcher to run lein cljfmt
https://www.jetbrains.com/help/idea/using-file-watchers.html
You can import the [provided task](https://github.comcast.com/mc/wiki/blob/master/multipass/style-guide/watchers.xml) instead of creating a new one
Project setup
Copy (.cljfmt.edn)[.cljfmt.edn] into the project root

Add [lein-cljfmt "0.8.0"] to the plugins section of project.clj

Add :cljfmt to the top level of defproject in project.clj. Add the contents of (.cljfmt.edn)[.cljfmt.edn] as the value for :cljfmt

Implementation
Unfortunately running a formatter on an entire repo leads to problems like merge conflicts. The simplest approach is for each dev to enable auto formatting and let the changes happen as each file is worked on. If a section of code isn't being worked on it can be updated at once to make quicker progress.

Some non default indentation exists in the code. While using the formatter, if the indentation changes when it shouldn't, a new indentation rule will need to be created.

IDE specific settings
intellij
When following the style guide above, the intellij formatter and cljfmt should not conflict for the most part. The following settings are also good to set.

General

Align Map Values selected
Align Let Bindings selected
One space list indent selected
Comment alignment column 0
Namespaces

Keep namespace elements in sorted order NOT selected

sirmspencer avatar Aug 12 '22 19:08 sirmspencer

I'm reading here that IntelliJ user's have tried to configure it to match the cljfmt rules, how well has that worked out?

drewverlee avatar Mar 31 '23 18:03 drewverlee

Its been fine for me with some formatting policies to get closer. Literally my post above shows how to get them to match closely.

sirmspencer avatar Mar 31 '23 22:03 sirmspencer