Skip to content

Instantly share code, notes, and snippets.

@duelinmarkers
Created August 13, 2013 03:28
Show Gist options
  • Save duelinmarkers/6217642 to your computer and use it in GitHub Desktop.
Save duelinmarkers/6217642 to your computer and use it in GitHub Desktop.
A paredit-based attempt at local rename for Clojure in emacs. M-x parfactor-rename-local.
(defun parfactor-rename-local (new-name)
(interactive "Mnew-name: ")
(save-excursion
(if (not (region-active-p))
(er/mark-clj-word))
(let* ((old-name (buffer-substring-no-properties (region-beginning) (region-end)))
(start-of-declaring-sexp (find-start-of-form-declaring old-name)))
(message "Renaming %s to %s" old-name new-name)
(goto-char start-of-declaring-sexp)
(while (re-search-forward old-name (scan-sexps start-of-declaring-sexp 1) t)
(replace-match new-name t t)))))
(defun find-start-of-form-declaring (local-name)
(paredit-backward)
(if (string= "(" (string (following-char)))
(let ((where-we-left-off (point)))
(if (form-declares local-name)
where-we-left-off
(progn (goto-char where-we-left-off)
(find-start-of-form-declaring local-name))))
(find-start-of-form-declaring local-name)))
(setq locally-binding-forms '(("let" search-bindings)
("if-let" search-bindings)
("doseq" search-bindings)))
(defun form-declares (local-name)
(right-char)
(er/mark-clj-word)
(let* ((form-op (buffer-substring-no-properties (region-beginning) (region-end)))
(search-fn (car (cdr (assoc form-op locally-binding-forms)))))
(and search-fn
(funcall search-fn local-name))))
(defun search-bindings (local-name)
(paredit-forward)
(right-char)
(assert (string= "[" (string (following-char))) t)
(right-char)
(cl-labels ((f (local-name)
(if (string= "]" (string (following-char)))
nil ; end of binding vector
(progn
(er/mark-clj-word)
(let ((this-local (buffer-substring-no-properties (region-beginning) (region-end))))
(message "Checking match on %s" this-local)
(if (string= local-name this-local)
t
(progn
(paredit-forward) ; after this-local
(paredit-forward) ; after this-local's val
(paredit-forward) ; after next local
(f local-name))))))))
(f local-name)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment