Skip to content

Instantly share code, notes, and snippets.

@yuhan0
Last active April 24, 2020 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuhan0/38ac43c764017917fc3f3e5dc9104f1b to your computer and use it in GitHub Desktop.
Save yuhan0/38ac43c764017917fc3f3e5dc9104f1b to your computer and use it in GitHub Desktop.
Toggle Clojure #_ ignore forms in Emacs
(defun clojure--toggle-ignore-next-sexp (&optional n)
"Insert or delete N `#_' ignore macros at the current point.
Point must be directly before a sexp or the #_ characters.
When acting on a top-level form it inserts #_ on a new line
preceding the form."
(let ((rgx (rx-to-string `(repeat ,(or n 1) (seq "#_" (* (in "\r\n" blank)))))))
(backward-prefix-chars)
(skip-chars-backward "#_")
(cond
((looking-at rgx) ;; point is before #_
(delete-region (point) (match-end 0)))
((looking-back rgx) ;; point is after #_
(delete-region (match-beginning 0) (point)))
(t
(dotimes (_ (or n 1)) (insert "#_"))
(when (zerop (car (syntax-ppss)))
(insert "\n"))))))
(defun clojure-toggle-ignore-surrounding-form (&optional arg)
"Toggle the #_ ignore reader form for the surrounding form at point.
With optional ARG, move up by ARG surrounding forms first.
With universal argument \\[universal-argument], act on the current top level defun. "
(interactive "P")
(save-excursion
(cond
;; called with C-u, act on defun
((consp arg)
(beginning-of-defun)
(clojure--toggle-ignore-next-sexp))
;; navigate to start of sexp
((not (looking-at-p (rx (or "#_" "(" "[" "{"))))
;; guard against moving past top level
(condition-case nil
(backward-up-list arg t t)
(scan-error nil))
(clojure--toggle-ignore-next-sexp))
;; looking at start of sexp
(t (clojure--toggle-ignore-next-sexp)))))
(defun clojure-toggle-ignore-form (&optional n)
"Toggle the #_ ignore reader form for the sexp at point.
With numeric argument, toggle N number of #_ forms at the same point.
e.g. with N = 2:
|a b c => #_#_a b c
If a region is selected, the (comment ...) form is used instead
to surround the active region, which is assumed to be balanced."
(interactive "p")
(save-excursion
(if (region-active-p)
;; multiple forms selected, use (comment ...) syntax
(let ((beg (region-beginning)))
(goto-char (region-end))
(insert " )\n")
(goto-char beg)
(save-excursion (insert "(comment\n"))
(prog-indent-sexp))
(skip-chars-forward "[:space:]\r\n")
(ignore-errors (beginning-of-thing 'symbol))
(clojure--toggle-ignore-next-sexp n))))
;; spacemacs config:
(spacemacs|forall-clojure-modes m
(spacemacs/set-leader-keys-for-major-mode m
"cc" #'clojure-toggle-ignore-surrounding-form
"cs" #'clojure-toggle-ignore-form))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment