emacs

enn 2025-09-29T14:09:05.174499Z

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.)?

ag 2025-10-01T18:26:52.799739Z

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))

vemv 2025-09-29T14:12:02.106809Z

Sounds like a lot of work for Elisp Maybe zprint does this? In which case graalvm makes it palatable for emacs integration

vemv 2025-09-29T14:15:53.147709Z

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"

enn 2025-09-29T14:17:25.161179Z

oh hmm, looks like zprint might do this. I was looking at cljfmt (which doesn't, afaict).

enn 2025-09-29T14:17:38.305819Z

I also do sort-lines but every time I do I think, there has to be a better way

lassemaatta 2025-09-29T14:23:50.424779Z

clojure-lsp + "sort map literal" (or something like that) code action is what I usually use

🎯 1
enn 2025-09-29T14:26:52.988679Z

ooh, that's exactly what I wanted, I had no idea. Thank you!

karol.adamiec 2025-09-29T14:29:35.867659Z

https://github.com/kkinnear/zprint/blob/main/doc/options/maps.md just for completeness :)

2025-09-29T14:36:15.512539Z

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')))))

2025-09-29T14:37:24.206299Z

hehehe

2025-09-29T14:39:22.433049Z

oh sorry I misunderstood the task, I though you wanted to see bigger maps sorted in the evaluation output