Last active
April 24, 2020 11:35
-
-
Save yuhan0/38ac43c764017917fc3f3e5dc9104f1b to your computer and use it in GitHub Desktop.
Toggle Clojure #_ ignore forms in Emacs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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