For large map literals in Clojure source with keyword keys and no meaningful key ordering, I like to sort the alphabetically by key. Has anyone found a nice way to do this automatically in Emacs (ideally otherwise preserving formatting--comments, indentation, etc.)?
zprint is pretty good for tasks like that. I recently was having to deal with a big Python map, I converted it to EDN, but oh boy... it made a clj map with nested levels so wide, that I had to travel all the way to Long Island part of my Emacs frame - back and forth. I just needed to squish the map by adding a bunch of line-breaks so it ain't so wide, but doing it naively with elisp turned out to be error-prone - elisp doesn't understand Clojure maps. This has worked:
(defun clj-zprint-region (start end)
"Format region with zprint using clj.
good for squishing wide nested maps."
(interactive "r")
(shell-command-on-region
start end
"clj -Sdeps '{:deps {zprint/zprint {:mvn/version \"1.3.0\"}}}' -M -m zprint.main 2>/dev/null"
nil t))
Sounds like a lot of work for Elisp Maybe zprint does this? In which case graalvm makes it palatable for emacs integration
In practice I do M-x sort-lines , which of course isn't perfect
I have a command that can turn sexps into one line:
(defun vemv/onelineize ()
"Turns the current sexpr into a oneliner"
(interactive)
(when (member (vemv/current-char-at-point) `("(" "[" "{"))
(let ((replacement (replace-regexp-in-string "[\s|\n]+" " " (vemv/sexpr-content))))
(vemv/kill nil t t)
(insert (concat replacement " "))
(when (string-equal " " (vemv/char-at-left))
(paredit-backward-delete))
(call-interactively 'paredit-backward))))
I do that where needed, sort, and then maybe undo the "onelineize"oh hmm, looks like zprint might do this. I was looking at cljfmt (which doesn't, afaict).
I also do sort-lines but every time I do I think, there has to be a better way
clojure-lsp + "sort map literal" (or something like that) code action is what I usually use
ooh, that's exactly what I wanted, I had no idea. Thank you!
https://github.com/kkinnear/zprint/blob/main/doc/options/maps.md just for completeness :)
for a super dirty hack that may work only for the basic situations (just tried), you can eval :
(extend-protocol nrepl.bencode/BencodeSerializable
String
(write-bencode* [s output]
(let [s' (if (.startsWith s "{")
(pr-str (into (sorted-map) (read-string s)))
s)]
(#'nrepl.bencode/write-netstring* output (#'nrepl.bencode/string>payload s')))))hehehe
oh sorry I misunderstood the task, I though you wanted to see bigger maps sorted in the evaluation output