What's your Emacs setup for writing Clojure code?
Coming from Common Lisp, I am quite used to Paredit, and I would like to continue using it while editing Clojure code.
The problem is it does not behave correctly with clojure-mode and clojure-ts-mode: when I hit Return or ( it auto-indents in a weird way (like, elements in the line after a (defn foo would indent to align with foo, instead of being just indented with 2 spaces).
From a cursory examination of the Paredit implementation, it seems to me the problem is that Paredit assumes the code is written in Lisp or Emacs Lisp, and that it delegates indentation to lisp-mode.
lisp-mode, in turns, has special behaviours encoded only for Lisp and Emacs Lisp, and does not treat Clojure special forms differently.
I could not find traces of plans to address this problem in Paredit, so I'm wondering how people work around the problem. Do you have other tools to recommend to do structural editing? Did you manage to setup Paredit so that it better behaves with Clojure?
I've tried them all, and ended up with Vanilla emacs sexp commands with electric-pair-mode (plus one custom slurp command derived from those), a good overview can be found here: https://dawranliou.com/blog/structural-editing-in-vanilla-emacs/. The nice thing about the inbuilt commands is that they are useful with stuff like xml, and even text selection. Lispy pulls in too many conflicting packages and paredit kidnaps way too many keybindings.
It sounds like you would enjoy CIDER #cider https://docs.cider.mx/cider/index.html
If you don't want to use packages other than paredit and clojure-mode, and your main concerns are about indentation, then you might like the cljfmt program (#cljfmt / https://github.com/weavejester/cljfmt) which quickly and reliably and correctly indents Clojure code files.
My Emacs setup for writing Clojure code is CIDER + projectile + rainbow-delimiters + smartparens + lsp, and it's great. π Others will have other opinions, naturally.
thanks @hhausman! I'm already using CIDER (and enjoying it indeed). Sounds like what I need is smartparens, I'll give it a try
oh, interesting! tbh, my setup has evolved slowly over many many years, so I'm not quite sure what's giving me the correct indentation - there are many paredit users here and in the #cider channel, so I'm sure someone else could help you make that work as well. I do prefer smartparens over paredit, but for a different reason... Sometimes I need to briefly have files with unmatched parens, and workflows that involved temporarily turning paredit off eventually grated on me. smartparens is much more flexible, but also lets me make mistakes that paredit would have prevented. π
yeah, it's true that Paredit is quite strict and if one has a buffer with an unbalanced parenthesis, it's pretty hard to recover the situation unless paredit is temporarily disabled. My current setup is the result of an attempt to replace the few components I had for Common Lisp with their counterparts for Clojure. Essentially, that boiled down to Slime -> CIDER; some other component provides decent dynamic docs in their popup frame (not sure which it is, to be honest: I think it's eldoc), and Company seems to be working out of the box (whereas it needed adjustments for Slime). I had assumed that Paredit could cover both languages, but I was wrong. My main problem is muscle memory. I can edit CL code without much thinking, and I guess I'll have to develop the same agility for editing Clojure
completely understood - sounds like you're going about it in a very smart way... If I were you, I would seek some clojurists that use paredit to make sure there isn't some easy way to proceed. Stay rad - happy to chat about setups any time.
Paredit is extremely commonly used in emacs with clojure (I've been using it with clojure for 14 or 15 years now)
It should work fine?
I get the indent to under the e in defn on hitting enter
I only use the inbuilt structured editing commands with electric-pair-mode and I also get correct indentation. I doubt that's something paredit or smartparens messes with directly.
For Emacs I use https://github.com/Fuco1/smartparens to provide the paredit functionality. Smartparens can be made as strict as you want. I've used Smartparens for a long time with clojure-mode without issue. I assume the issues mentioned are due to using both clojure-mode and clojure-ts-mode. I would have thought only one of these modes should be used.
clojure-ts-mode's indentation strategy is 'semantic by default. you can change it to 'fixed. it also doesn't read cljfmt files and you have to configure it manually. i switched to emacs from vs code a month ago, installed clojure-ts-mode, clojure-lsp/lsp-mode, and cider and am finding it a struggle to configure because they have feature overlaps. i looked at the emacs configs of more seasoned devs and was surprised to see they get by on the bare minimum- you will not see clojure-ts-mode, clojure-lsp, or cider in many of their configs.
@hiredman thanks. Is your Emacs conf published somewhere? I should probably try emacs -Q and the enable packages one by one and when it "breaks"
No, but I don't believe I have any customization of paredit or clojure-mode
Are you on windows?
no. Same behaviour on Mac and Linux
but I have a quite articulated configuration for multiple use cases of Emacs. I can't rule out there's a package interfering with another one (but my analysis above seemed reasonable)
@ianchow Some people would call me an Emacs veteran as well, and I do use CIDER, but admittedly my setup is pretty basic https://github.com/bbatsov/emacs.d/blob/master/init.el#L781 π I donβt need much more than a good REPL integration for any Lisp-like language, but thatβs just me. Too much time spent with CL and Emacs I guess. π
Paredit has always worked well for me and clojure-mode, but it does have some glitches with clojure-ts-mode
See https://github.com/clojure-emacs/clojure-ts-mode/issues/81 for details and a workaround
@stefano.rodighiero my choice is https://github.com/abo-abo/lispy, which behaves "lispy" only when the cursor is in special position, eg a parens or brackets. It's super fast to navigate around the code. It's like vim without manually switching between navigate and edit mode.