This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-12
Channels
- # announcements (2)
- # babashka (22)
- # babashka-sci-dev (15)
- # beginners (62)
- # calva (2)
- # cider (8)
- # clj-kondo (33)
- # clojure (52)
- # clojure-europe (46)
- # clojure-losangeles (1)
- # clojure-norway (5)
- # clojure-spec (7)
- # clojurescript (31)
- # conjure (20)
- # data-science (4)
- # datalevin (16)
- # fulcro (28)
- # hyperfiddle (71)
- # introduce-yourself (3)
- # lsp (50)
- # off-topic (16)
- # polylith (8)
- # portal (3)
- # practicalli (1)
- # reitit (1)
- # releases (2)
- # tools-build (22)
- # vim (8)
- # xtdb (17)
In other news - yesterday marked 11 years since CIDER's first public release (back then the project was named nrepl.el
)! 🎂Here's to many more birthdays to come!
35
Is there a way in cider (or clojure-mode or clojure-lsp) to sort map literal entries by key? I.e. i’ve got
{:foo 1
:bar 2
:baz 3}
and I want to get
{:bar 2
:baz 3
:foo 1
}
clojure-lsp
has a code action for Sort map
Ah nice! Thanks.
I have this long function I use to sort a bunch of things, including vectors and maps. It can even deal with comments between lines
(defun me/sort-sexp ()
"Sort sexps between point and end of current sexp.
With multilines sexp, comments and blank lines are considered part of the following
sexp. Comments at the end of a line (after some other content)
are considered part of the preceding sexp."
(interactive)
(save-excursion
(save-restriction
(up-list)
(backward-sexp)
(let* ((map? (looking-at "{"))
(start (1+ (point)))
(end (progn (forward-sexp)
(1- (point))))
(multiline? (< (line-number-at-pos start)
(line-number-at-pos end)))
;; Should really check every line, but the only the first with a sexp should be enough
(one-sexp-per-line? (save-excursion
(goto-char start)
;; Skip start comment, if any
(let ((sexp2-end (progn (clojure-forward-logical-sexp 2) (point)))
(sexp2-start (progn (clojure-forward-logical-sexp -2) (point))))
(< (line-number-at-pos sexp2-start)
(line-number-at-pos sexp2-end))))))
(narrow-to-region start end)
;; Delete last empty line, if any
(save-excursion
(beginning-of-line)
(when (looking-at "[[:blank:]]*$")
(backward-char)
(delete-region (point) (point-max))))
(goto-char start)
(sort-subr nil
(lambda ()
(if (and multiline? one-sexp-per-line?)
(progn (message "forward line")
(forward-line))
(search-forward-regexp "[^:blank:]" nil :no-error)))
;; Move to end of current top-level thing.
(lambda ()
(condition-case nil
(while t (up-list))
(scan-error nil))
;; We could be inside a symbol instead of a sexp.
(unless (looking-at "\\s-\\|$")
(clojure-forward-logical-sexp))
(when (and multiline? one-sexp-per-line?)
;; move past comments at the end of the line.
(search-forward-regexp "$")))
;; Start of record
(lambda ()
(when multiline?
(skip-chars-forward "\r\n[:blank:]")
(comment-forward)
(skip-chars-forward "[:blank:]\n\r[("))
(condition-case nil
(progn (clojure-forward-logical-sexp)
(forward-sexp -1))
(scan-error nil))
nil)
;; End of record
(lambda ()
(clojure-forward-logical-sexp (if map? 2 1)))
(lambda (a b)
(let* ((s1 (buffer-substring (car a) (cdr a)))
(s2 (buffer-substring (car b) (cdr b)))
;; Ignore namespaces for keywords
(s1* (replace-regexp-in-string
"^::" ""
(if (string-match "^::.*/\\(.*\\)" s1)
(match-string 1 s1)
s1)))
(s2* (replace-regexp-in-string
"^::" ""
(if (string-match "^::.*/\\(.*\\)" s2)
(match-string 1 s2)
s2))))
(string< s1* s2*))))
;; Delete starting whitespaces
(goto-char (point-min))
(delete-region (point) (progn (skip-chars-forward "[:blank:]") (point)))
;; Go to the end and insert newline if we end with a comment.
(goto-char (point-max))
(when (nth 4 (parse-partial-sexp (point-min) (point)))
(insert "\n"))
;; Clean superfluous spaces
(when (not multiline?)
(goto-char (point-min))
(while (re-search-forward "\\s-+" nil t)
(replace-match " ")))
;; Fill paragraph
(when (and (not map?) (not one-sexp-per-line?))
(fill-region-as-paragraph start end))))
;; Indent
(let ((end (progn (up-list) (point)))
(start (progn (progn (clojure-forward-logical-sexp -1)) (point))))
(indent-region start end))))
🛠️ 2
[:z
:d
;; comment for :abc
:abc
:e]
Will become
[;; comment for :abc
:abc
:d
:e
:z]
I ended up using zprint
for this
(defun mm/zprint-region ()
(interactive)
(save-excursion
(shell-command-on-region (mark) (point) "zprint" (buffer-name) t)))
👍 2
I’ve got a whole bunch of these entries