(defun dss/clojure-ignore-form () "Inserts, toggles, or moves Clojure's #_ ignore-next-form reader macro." (interactive) (flet ((in-string-p () (eq 'string (syntax-ppss-context (syntax-ppss)))) (in-comment-p () (eq 'comment (syntax-ppss-context (syntax-ppss))))) (skip-chars-forward " ") (while (in-string-p) (backward-char)) (cond ;; switch from a comment to an ignore form, if paredit is enabled ;; This bit might not work if mark-sexp fails inside the comment. ((and (featurep 'paredit) (or (looking-at-p ";") (in-comment-p)) (looking-at-p "[ ;]*\(")) (progn (back-to-indentation) (mark-sexp) (paredit-comment-dwim) (insert "#_"))) ;; if the command is repeated move the ignore macro up a syntax level ((and (equal last-command this-command) (> (syntax-ppss-depth (syntax-ppss)) 0) (looking-back "#_ *" (- (point) 5))) (progn (replace-match "") (backward-up-list) (insert "#_"))) ;; if the cursor is right on top of the ignore macro, remove it ((looking-at-p "#_") (delete-char 2)) ;; ditto, if in the middle of it ((and (looking-at-p "_") (looking-back "#")) (progn (backward-char) (delete-char 2))) ;; if an outer form is already ignored, un-ignore (sic) it ((save-excursion (while (and (> (syntax-ppss-depth (syntax-ppss)) 0) (not (looking-back "#_ *" (- (point) 10)))) (backward-up-list)) (looking-back "#_ *" (- (point) 10))) (save-excursion (replace-match ""))) ;; else, just ignore this form (t (insert "#_"))))) ;;; add this (or another key) to your clojure-mode-hook ;;; (define-key clojure-mode-map (kbd "M-'") 'dss/clojure-ignore-form)