-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrewriter-fn-to-method.el
97 lines (90 loc) · 3.01 KB
/
rewriter-fn-to-method.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
;; Rewrite F(x, ...) -> x->f(...)
;; Usage: fn-to-method [-z] FUNC METHOD [N]
;; Rewrite FUNC to METHOD
;; If -z is given, FUNC is a regexp and METHOD can contain
;; substitutions. FIXME can't use -r due to some emacs bug
;; If N is given, it is the argument number of the 'this' argument.
;; Defaults to 0; arguments start at 0. Incompatible with -z.
(defvar rw-is-rx nil)
(when (equal (car argv) "-z")
(setq rw-is-rx t)
(pop argv))
(defvar rw-original-rx
(if rw-is-rx
(pop argv)
(regexp-quote (pop argv))))
(defvar rw-function
;; Allow an optional "::" before the function name.
(concat "[^.>]\\(::\\)?\\_<\\("
rw-original-rx
"\\)\\_>[ \t\n]*(\\s *"))
(defvar rw-new-name (pop argv))
(defvar rw-arg (if (and (stringp (car argv))
(string-match "^[0-9]+$ " (car argv)))
(string-to-number (pop argv))
0))
(defun rw-remove-comma ()
(when (looking-at ",")
(let ((start (point)))
(forward-char)
(skip-chars-forward " \t\n")
(delete-region start (point)))))
(defun rw-rewrite-fn-name (text)
(if rw-is-rx
(progn
(cl-assert (string-match rw-original-rx text))
(replace-match rw-new-name t nil text))
rw-new-name))
(defun rw-fn-to-method ()
(while (re-search-forward rw-function nil t)
(goto-char (match-end 2))
(let ((starting-text (buffer-substring (match-beginning 2)
(match-end 2))))
;; Delete the original function name.
(delete-region (match-beginning 2) (match-end 2))
;; If there was a "::", delete it too.
(when (match-beginning 1)
(delete-region (match-beginning 1) (match-end 1)))
;; Now rewrite the function name if needed.
(let ((new-name (rw-rewrite-fn-name starting-text))
(saved-text nil))
(save-excursion
;; Move forward past the "(".
(skip-chars-forward " \t\n")
(when (looking-at "(")
(forward-char))
(skip-chars-forward " \t\n")
(let ((remove-comma t))
(save-excursion
;; Skip leading arguments.
(dotimes (_ignore rw-arg)
(when (looking-at ",")
(setq remove-comma nil)
(forward-char)
(skip-chars-forward " \t\n"))
(rw-skip-expr "[,)]"))
;; Could be at the start of the arguments, or at the ","
;; before the argument we want to extract. Delete the "," if
;; it is there.
(rw-remove-comma)
;; Extract the argument.
(let ((start (point)))
(rw-skip-expr "[,)]")
(setq saved-text (buffer-substring start (point)))
(delete-region start (point)))
;; If we need the ",", re-insert it.
(when (and remove-comma (looking-at ","))
(rw-remove-comma)))))
;; Insert the argument again, this time as 'this'.
(if (string-match "^&" saved-text)
;; Turn f(&x) -> x.m()
(insert (substring saved-text 1) "." new-name)
;; Turn f(*x) -> (*x)->m()
(if (string-match "^\\*" saved-text)
(insert "(" saved-text ")->" new-name)
;; Turn f(x) -> x->m().
(insert saved-text "->" new-name)))
(let ((start (point)))
(forward-list)
(indent-region start (point)))))))
(rw-rewrite #'rw-fn-to-method)