Skip to content

Commit

Permalink
Rename ns aliases in region
Browse files Browse the repository at this point in the history
  • Loading branch information
yuhan0 committed Apr 21, 2021
1 parent a959a1b commit 2b22f03
Showing 1 changed file with 73 additions and 44 deletions.
117 changes: 73 additions & 44 deletions clojure-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -2670,38 +2670,6 @@ lists up."
(insert sexp)
(clojure--replace-sexps-with-bindings-and-indent)))

(defun clojure-collect-ns-aliases (ns-form)
"Collect all namespace aliases in NS-FORM."
(with-temp-buffer
(delay-mode-hooks
(clojure-mode)
(insert ns-form)
(goto-char (point-min))
(let ((end (point-max))
(rgx (rx ":as" (+ space)
(group-n 1 (+ (not (in " ,]\n"))))))
(res ()))
(while (re-search-forward rgx end 'noerror)
(unless (or (clojure--in-string-p) (clojure--in-comment-p))
(push (match-string-no-properties 1) res)))
res))))

(defun clojure--rename-ns-alias-internal (current-alias new-alias)
"Rename a namespace alias CURRENT-ALIAS to NEW-ALIAS."
(clojure--find-ns-in-direction 'backward)
(let ((rgx (concat ":as +" (regexp-quote current-alias) "\\_>"))
(bound (save-excursion (forward-list 1) (point))))
(when (search-forward-regexp rgx bound t)
(replace-match (concat ":as " new-alias))
(save-excursion
(while (re-search-forward (concat (regexp-quote current-alias) "/") nil t)
(when (not (nth 3 (syntax-ppss)))
(replace-match (concat new-alias "/")))))
(save-excursion
(while (re-search-forward (concat "#::" (regexp-quote current-alias) "{") nil t)
(replace-match (concat "#::" new-alias "{"))))
(message "Successfully renamed alias '%s' to '%s'" current-alias new-alias))))

;;;###autoload
(defun clojure-let-backward-slurp-sexp (&optional n)
"Slurp the s-expression before the let form into the let form.
Expand Down Expand Up @@ -2745,21 +2713,82 @@ With a numeric prefix argument the let is introduced N lists up."
(interactive)
(clojure--move-to-let-internal (read-from-minibuffer "Name of bound symbol: ")))


;;; Renaming ns aliases

(defun clojure--alias-usage-regexp (alias)
"Regexp for matching usages of ALIAS in qualified symbols, keywords and maps.
ALIAS is a regexp-quoted string. When nil, match all alias usages.
The first match-group is the alias."
(let ((alias (if alias (regexp-quote alias)
"\\(?:\\s_\\|\\sw\\)+")))
(concat
"#::\\(?1:" alias "\\)[ ,\r\n\t]*{"
"\\|"
"\\(?1:" alias "\\)/")))

(defun clojure--rename-ns-alias-usages (current-alias new-alias beg end)
"Rename all usages of CURRENT-ALIAS in region BEG to END with NEW-ALIAS."
(let ((rgx (clojure--alias-usage-regexp current-alias)))
(save-excursion
(goto-char end)
(setq end (point-marker))
(goto-char beg)
(while (re-search-forward rgx end 'noerror)
(when (not (clojure--in-string-p)) ;; replace in comments, but not strings
(goto-char (match-beginning 1))
(delete-region (point) (match-end 1))
(insert new-alias))))))

(defun clojure--collect-ns-aliases (beg end ns-form-p)
"Collect all aliases between BEG and END.
When NS-FORM-P is non-nil, treat the region as a ns form
and pick up aliases from [... :as alias] forms,
otherwise pick up alias usages from keywords / symbols."
(let ((res ()))
(save-excursion
(let ((rgx (if ns-form-p
(rx ":as" (+ space)
(group-n 1 (+ (not (in " ,]\n")))))
(clojure--alias-usage-regexp nil))))
(goto-char beg)
(while (re-search-forward rgx end 'noerror)
(unless (or (clojure--in-string-p) (clojure--in-comment-p))
(cl-pushnew (match-string-no-properties 1) res
:test #'equal)))
(reverse res)))))

(defun clojure--rename-ns-alias-internal (current-alias new-alias)
"Rename a namespace alias CURRENT-ALIAS to NEW-ALIAS.
Assume point is at the start of ns form."
(clojure--find-ns-in-direction 'backward)
(let ((rgx (concat ":as +" (regexp-quote current-alias) "\\_>"))
(bound (save-excursion (forward-list 1) (point-marker))))
(when (search-forward-regexp rgx bound t)
(replace-match (concat ":as " new-alias))
(clojure--rename-ns-alias-usages current-alias new-alias bound (point-max)))))

;;;###autoload
(defun clojure-rename-ns-alias ()
"Rename a namespace alias."
"Rename a namespace alias.
If a region is active, only pick up and rename aliases within the region."
(interactive)
(save-excursion
(clojure--find-ns-in-direction 'backward)
(let* ((current-alias (completing-read "Current alias: "
(clojure-collect-ns-aliases
(thing-at-point 'list))))
(rgx (concat ":as +" (regexp-quote current-alias) "\\_>"))
(bound (save-excursion (forward-list 1) (point))))
(if (save-excursion (search-forward-regexp rgx bound t))
(let ((new-alias (read-from-minibuffer "New alias: ")))
(clojure--rename-ns-alias-internal current-alias new-alias))
(message "Cannot find namespace alias: '%s'" current-alias)))))
(if (use-region-p)
(let* ((beg (region-beginning))
(end (region-end))
(current-alias (completing-read "Current alias: "
(clojure--collect-ns-aliases
beg end nil)))
(new-alias (read-from-minibuffer (format "Replace %s with: " current-alias))))
(clojure--rename-ns-alias-usages current-alias new-alias beg end))
(save-excursion
(clojure--find-ns-in-direction 'backward)
(let* ((bounds (bounds-of-thing-at-point 'list))
(current-alias (completing-read "Current alias: "
(clojure--collect-ns-aliases
(car bounds) (cdr bounds) t)))
(new-alias (read-from-minibuffer (format "Replace %s with: " current-alias))))
(clojure--rename-ns-alias-internal current-alias new-alias)))))

(defun clojure--add-arity-defprotocol-internal ()
"Add an arity to a signature inside a defprotocol.
Expand Down

0 comments on commit 2b22f03

Please sign in to comment.