Fork me on GitHub
#cider
<
2023-07-12
>
bozhidar05:07:29

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! cider

cider 35
joost-diepenmaat10:07:08

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}

lassemaatta10:07:25

clojure-lsp has a code action for Sort map

joost-diepenmaat11:07:35

Ah nice! Thanks.

frozenlock12:07:30

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
frozenlock12:07:53

[:z
 :d
 ;; comment for :abc
 :abc
 :e]
Will become
[;; comment for :abc
 :abc
 :d
 :e
 :z]

Benjamin06:07:53

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
joost-diepenmaat10:07:23

I’ve got a whole bunch of these entries