-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathphp-edit.el
258 lines (242 loc) · 9.37 KB
/
php-edit.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
;;; php-edit.el --- Functions that deal with PHP text editing
;; Version: 1.0
;; Created: 11-01-2011
;; Copyright © 2011 Michael Dwyer
;; Author(s):
;; Michael Dwyer <[email protected]>
;;; *****
;;; About
;;; *****
;; php-edit.el is a part of the php+-mode suite and contains convenience
;; functions for PHP text editing, such as killing the current
;; structure and formatting the whitespace around it.
;; ********************************************************************
;; ************
;; REQUIREMENTS
;; ************
(require 'php-parse)
(require 'php-format)
(require 'php-funcs)
(require 'php-structure)
;; *********
;; FUNCTIONS
;; *********
(defun php-mark-current (&optional type)
"Put point at beginning and mark at end of current structure.
Optionally force TYPE of structure. You probably should not use
this function in Lisp programs; it is usually a mistake for a
Lisp function to use any subroutine that uses or sets the mark."
(interactive)
(let* ((type (or type '(constant property method)))
(parse (php-parse-current type)))
(when (php-parse-p parse)
(push-mark (point))
(push-mark (rest (assoc 'begin parse)) nil t)
(goto-char (rest (assoc 'end parse)))
(exchange-point-and-mark))))
(defun php-comment-current (&optional type)
"Comments or uncomments the current or given thing."
(interactive)
(save-excursion
(php-mark-current (when type type))
(comment-or-uncomment-region (region-beginning) (region-end))))
(defun php-kill-sexp-innard ()
"Kills everything within the current sexp"
(interactive)
(kill-region (1+ (php-find-current-sexp-begin))
(1- (php-find-current-sexp-end))))
(defun php-kill-current (&optional type no-fix-spacing)
"Kills the current TYPE PHP structure at point. TYPE follows
the semantics of php-parse-current. Returns the parsed
structure. If NO-FIX-SPACING is non-nil, don't run
``php-format-spacing'' afterwards. Although you may yank what is
deleted, only undo is guaranteed to return the previous structure
to its previous placement. You may want to use ``php-yank''
instead."
(interactive)
(save-match-data
(let ((parse (php-parse-current '(constant property method))))
(when (php-parse-p parse)
(let ((begin (rest (assoc 'begin parse)))
(end (rest (assoc 'end parse))))
(goto-char begin)
(when (looking-at-p ws-re)
(re-search-forward non-ws-re nil t)
(backward-char))
(let ((begin (point)))
(goto-char end)
(when (looking-at-p ws-re)
(re-search-backward non-ws-re nil t)
(forward-char)
(setq end (point)))
(re-search-forward non-ws-re nil t)
(backward-char)
(if (not (looking-at-p "}"))
(setq end (point))
(goto-char begin)
(re-search-backward non-ws-re nil t)
(forward-char)
(setq begin (point)))
(setf (rest (assoc 'begin parse)) begin)
(setf (rest (assoc 'end parse)) end)
(setf (rest (assoc 'text parse))
(buffer-substring-no-properties begin end))
(kill-region begin end)
(unless no-fix-spacing
(php-format-spacing t))
(goto-char begin)
parse))))))
(defun php-yank (&optional pos no-fix-spacing trim-prefixed-whitespace)
"Yanks a PHP structure at position POS (or (point)) and then
corrects the whitespace around it. If NO-FIX-SPACING is non-nil,
don't run ``php-format-spacing'' afterwards. It may be told to
TRIM-PREFIXED-WHITESPACE even if NO-FIX-SPACING is non-nil. Puts
point at end and set mark at beginning."
(interactive)
(let ((pos (if (integerp pos) pos (point))))
(goto-char pos)
(let ((correct-previous-spacing (looking-at-p "}")))
(yank)
(let ((end (point)))
(when trim-prefixed-whitespace
(goto-char pos)
(re-search-forward non-ws-re nil t)
(backward-char)
(let ((gap (- (point) pos)))
(delete-region pos (point))
(setq end (- end gap))))
(goto-char end)
(unless no-fix-spacing
(php-format-region pos (point) correct-previous-spacing)
(php-format-spacing t))))))
(defun php-format-region (begin end &optional correct-previous-spacing)
"Corrects the whitespace around a region from BEGIN to END. If
CORRECT-PREVIOUS-SPACING is non-nil, correct spacing before BEGIN
as well."
(interactive (when (region-active-p) `(,(region-beginning) ,(region-end))))
(save-excursion
(goto-char begin)
(when correct-previous-spacing
(re-search-backward non-ws-re nil t)
(forward-char)
(setq begin (point)))
(save-match-data
(when (save-excursion (re-search-forward non-ws-re end t))
(let ((e (1- (match-end 0))))
(setf end (- end (- e (point))))
(delete-region (point) e))))
(setq end (+ end (indent-according-to-mode)))
(when correct-previous-spacing
(let ((temp (point)))
(newline)
(newline-and-indent)
(setq end (+ end (- (point) temp)))))
(goto-char end)
(re-search-backward non-ws-re nil t)
(forward-char)
(let ((end (point)))
(re-search-forward non-ws-re nil t)
(backward-char)
(when (not (looking-at-p "}"))
(delete-region end (point))
(newline)
(newline-and-indent)
(setq end (point))))))
; defined for compiler
(defvar php+-mode-delete-trailing-whitespace)
(defun php-format-spacing (&optional no-indent-all-lines)
"Formats the spacing in the current class/interface according
to defcustoms ``php-blank-line-at-start-of-class'' and
``php-blank-line-at-end-of-class''. Will run
``indent-according-to-mode'' on all lines in the structure unless
passed NO-INDENT-ALL-LINES."
(interactive)
(save-excursion
(save-match-data
(let ((parse (php-parse-current '(class interface))))
(when (php-parse-p parse)
(let ((begin (rest (assoc 'begin parse)))
(end (rest (assoc 'end parse))))
(goto-char begin)
(php-jump-to-first-statement)
(re-search-backward "{" nil t)
(forward-char)
(let ((begin (point)))
(re-search-forward non-ws-re nil t)
(backward-char)
(let ((gap (- (point) begin)))
(delete-region begin (point))
(setf end (- end gap)))
(when php-blank-line-at-start-of-class
(newline)
(setf end (1+ end)))
(setf end (+ end (newline-and-indent))))
(goto-char end)
(when (not (looking-at-p "}"))
(re-search-backward "}" nil t))
(let ((end (point)))
(re-search-backward non-ws-re nil t)
(forward-char)
(delete-region (point) end)
(when php-blank-line-at-end-of-class
(newline))
(newline-and-indent)
;; Something in here causes undo ring corruption
(unless no-indent-all-lines
(let ((end (point)))
(goto-char begin)
(setf end (+ end (indent-according-to-mode)))
(while (and (< (point) end) (< (forward-line) 1))
(when (not (looking-at-p "^$"))
(setf end
(+ end
(indent-according-to-mode)))))))))))
(when php+-mode-delete-trailing-whitespace
(delete-trailing-whitespace)))))
(defun fixup-whitespace ()
"Fixup white space between objects around point.
Leave one space or none, according to the context. This version
overrides the one built into Emacs, and respects PHP accessor
operators."
(interactive "*")
(save-excursion
(save-match-data
(php-delete-horizontal-space)
(if (or (looking-at "^\\|\\s)")
(looking-at "->\\|::")
(save-excursion (forward-char -1)
(looking-at "$\\|\\s(\\|\\s'"))
(save-excursion (forward-char -2)
(looking-at "->\\|::")))
nil
(insert ?\s)))))
(defun php-kill-chain-link ()
"Kills the chain link around point."
(interactive)
(let ((begin (save-excursion
(let ((ident-begin (php-in-identifierp)))
(if (re-search-backward ">" ident-begin t)
(1+ (point))
ident-begin))))
(end (save-excursion
(save-match-data
(catch 'done
(let ((ident-end (save-excursion
(php-skip-this-identifier))))
(while (re-search-forward "[-(]" ident-end t)
(if (not (string= (match-string-no-properties 0) "("))
(throw 'done (1+ (point)))
(backward-char)
(forward-sexp)))
(if (not (looking-back-p "-"))
(goto-char ident-end)
(backward-char)
(1+ (point)))))))))
(let ((begin (if (save-excursion
(goto-char end)
(looking-back-p ">"))
begin
(- begin 2))))
(delete-region begin end)
(- end begin))))
(provide 'php-edit)