Merge lp:~a-roehler/python-mode/myrkwid into lp:python-mode
- myrkwid
- Merge into python-mode
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
python-mode.el developers | Pending | ||
Review via email:
|
Commit message
Description of the change
"Myrkwid"s majore rewrite of internals
API should be unchanged, beside some extras delivered
Should meet bug fixing goal of Milestone "Myrkwid"
Functions moving point rely on
`py-beginning-
with `py-travel-
Also `py-compute-
- 411. By Andreas Roehler
-
py-statement-
opens-block- p interactive, py-travel-indent fixed - 412. By Andreas Roehler
-
tests rewritten, beg-end-of-defun-lp:303622 test added
- 413. By Andreas Roehler
-
py-mark-base, py-travel-
current- indent fixed - 414. By Andreas Roehler
-
py-beg-
of-defun- function added - 415. By Andreas Roehler
-
beg-end-of-defun-lp:303622 test added
- 416. By Andreas Roehler
-
py-beginning-
of-def- or-class fixed, bod test changed - 417. By Andreas Roehler
-
fore-#00007F-
breaks- indentation lp:328788 test added - 418. By Andreas Roehler
-
flexible-
indentation-lp:328842-test added - 419. By Andreas Roehler
-
remove the
whole of an "if" or "while" block: py-kill-block and other deleting forms introduced - 420. By Andreas Roehler
-
py-beginning-
of-clause- p new function - 421. By Andreas Roehler
-
py-travel-
current- indent simplified - 422. By Andreas Roehler
-
empty-line-p added
- 423. By Andreas Roehler
-
py-end-
of-block- or-clause fixed - 424. By Andreas Roehler
-
py-mark-base simplified
- 425. By Andreas Roehler
-
new vars py-lhs-
inbound- indent, py-rhs- inbound- indent - 426. By Andreas Roehler
-
sexp-commands-lp:328778-test added
- 427. By Andreas Roehler
-
honor py-lhs-
inbound- indent - 428. By Andreas Roehler
-
flexible-
indentation-lp:328842-test added - 429. By Andreas Roehler
-
python-
mode-tests. sh added - 430. By Andreas Roehler
-
beg-end-of-defun-lp:303622 fixed
- 431. By Andreas Roehler
-
py-continuati
on-offset docu changed - 432. By Andreas Roehler
-
indentation-
of-continuation -lines-lp:691185 changed - 433. By Andreas Roehler
-
backslashed-
continuation- line-indent-lp:742993-test added - 434. By Andreas Roehler
-
backslashed-
continuation- line-indent-lp:742993-test added - 435. By Andreas Roehler
-
mark/kill functions cleaned up
- 436. By Andreas Roehler
-
use run-mode-hooks
- 437. By Andreas Roehler
-
py-compute-
indentation fix on empty line at eob - 438. By Andreas Roehler
-
sit-for
- 439. By Andreas Roehler
-
py-decorators-face, Thanks David Miller
- 440. By Andreas Roehler
-
py-decorators
-face-lp:744335 test added - 441. By Andreas Roehler
-
run py-decorators-face-lp:744335 test
- 442. By Andreas Roehler
-
exceptions-
not-highlighted -lp:473525-test added - 443. By Andreas Roehler
-
while bobp followed by backward-
to-indentation - 444. By Andreas Roehler
-
indent after return lp:745208
- 445. By Andreas Roehler
-
indent-
after-return-lp:745208 test added - 446. By Andreas Roehler
-
indent-
after-return-lp:745208 test added - 447. By Andreas Roehler
-
redundant form py-beginning-
of-form- base removed - 448. By Andreas Roehler
-
indent-
after-return-lp:745208 test extended - 449. By Andreas Roehler
-
py-end-
of-statement fixed - 450. By Andreas Roehler
-
new py-beginning-
of-def, py-end-of-def - 451. By Andreas Roehler
-
py-run-tests added
- 452. By Andreas Roehler
-
typo
- 453. By Andreas Roehler
-
test-buffer-name
- 454. By Andreas Roehler
-
clean-up
- 455. By Andreas Roehler
-
python-
mode-teststring var-name fixed - 456. By Andreas Roehler
-
py-fill-string at beginning too
- 457. By Andreas Roehler
-
bullet-
lists-in- comments-lp:328782-test-intern fixed - 458. By Andreas Roehler
-
non-numbered tests added
- 459. By Andreas Roehler
-
py-electric-
delete, py-electric- backspace reconsidered - 460. By Andreas Roehler
-
py-electric-
delete, py-electric- backspace tests added - 461. By Andreas Roehler
-
compute closing keywords fix
- 462. By Andreas Roehler
-
indent-
after-return-lp:745208 fixed - 463. By Andreas Roehler
-
py-in-comment-p, py-in-string-p
- 464. By Andreas Roehler
-
return values fixed
- 465. By Andreas Roehler
-
var honor-block-close-p dropped as unused
- 466. By Andreas Roehler
-
py-compute-
indentation fixed, tests added - 467. By Andreas Roehler
-
py-statement-
opens-class- p, py-statement- opens-def- p - 468. By Andreas Roehler
-
mark decorators with class or def, customizable, test provided, lp:328851
- 469. By Andreas Roehler
-
copying functions added
- 470. By Andreas Roehler
-
$EMACS
- 471. By Andreas Roehler
-
end forms refactored
- 472. By Andreas Roehler
-
use defface, patch lp:328838
- 473. By Andreas Roehler
-
known keys for c-hungry-delete forms enabled, py- alias and tests provided,
- 474. By Andreas Roehler
-
python-
mode-tests. sh load cc-cmds.el - 475. By Andreas Roehler
-
define-
derived- mode - 476. By Andreas Roehler
-
indent-
triplequoted- to-itself bug lp:752252 fixed, test delivered - 477. By Andreas Roehler
-
py-current-defun fixed, test added
- 478. By Andreas Roehler
-
use py-current-
defun-show - 479. By Andreas Roehler
-
menu re-enabled, unused forms removed
- 480. By Andreas Roehler
-
py-beginning-
of-def- or-class defaults to py-def-or-class-re, which cures imenu-matches- in-docstring bug lp:436285, test added - 481. By Andreas Roehler
- 482. By Andreas Roehler
-
py-python-mode typo
- 483. By Andreas Roehler
-
py-in-
triplequoted- string- p fixed - 484. By Andreas Roehler
-
tests cleaned-up
When interactively called, test buffers will be closed
per default, unless ARG greater 1 is delivered.In batch-mode: fontifying messages silenced.
- 485. By Andreas Roehler
-
enable M-x beginning-
end-of- defun lp:303622 - 486. By Andreas Roehler
-
py-help-at-point simplified
report indicated a deleted buffer, where the mark got lost
Nonetheless simplified proceeding:
`py-symbol-
near-point' replaced by `symbol-at-point' cl makro `search' replaced by resp. Emacs Lisp
- 487. By Andreas Roehler
-
defalias py-describe-symbol py-help-at-point, lp:328854
- 488. By Andreas Roehler
-
cls py-pseudo-
keyword- face lp:328849 - 489. By Andreas Roehler
-
syntaxerror-
on-py-execute- region lp:691542 patch applied Thanks to Yuri Goncharov, who sent the patch.
Thanks also to Maik Beckmann, who provided a test
confirming it. - 490. By Andreas Roehler
-
Allow different indents of multiline-listings
Indents according to new boolean variable: py-indent-
honor-listing "If `t', indents to one column more than column of
opening delimiter. If `nil', indent adds one level to
the beginning of statement. Default is `nil'. "fixes lp:761946
- 491. By Andreas Roehler
-
new-page char bug lp:762498 fixed, "py-indent-
honor-listing" renamed "py-indent- honors- multiline- listing" - 492. By Andreas Roehler
-
py-newline-
and-dedent at [(control return)] - 493. By Andreas Roehler
-
looking-back XEmacs compat
- 494. By Andreas Roehler
-
nested-dicts-indent lp:763756, thanks Eric S. Johansson for the report
- 495. By Andreas Roehler
-
py-emacs-features dropped
- 496. By Andreas Roehler
-
UnicodeEncodeError lp:550661 fixed
That section is to re-consider.
Parts are useless now, others have been that before.
So far a fix-in-transition. .. - 497. By Andreas Roehler
-
UnicodeEncodeError lp:550661 minor fix
Preview Diff
1 | === added file 'UnicodeEncodeError-lp:550661-test.py' |
2 | --- UnicodeEncodeError-lp:550661-test.py 1970-01-01 00:00:00 +0000 |
3 | +++ UnicodeEncodeError-lp:550661-test.py 2011-04-18 19:44:32 +0000 |
4 | @@ -0,0 +1,4 @@ |
5 | +#! /usr/bin/env python |
6 | +# -*- coding: utf-8 -*- |
7 | +print u'\xA9' |
8 | +print u'\xe5' |
9 | |
10 | === modified file 'py-bug-numbered-tests.el' |
11 | --- py-bug-numbered-tests.el 2011-03-15 21:27:59 +0000 |
12 | +++ py-bug-numbered-tests.el 2011-04-18 19:44:32 +0000 |
13 | @@ -16,14 +16,12 @@ |
14 | ;; |
15 | ;;; Code: |
16 | |
17 | +(require 'python-mode-test) |
18 | + |
19 | + |
20 | (add-to-list 'load-path default-directory) |
21 | - |
22 | -(require 'thingatpt-utils-base) |
23 | -(require 'thing-at-point-utils) |
24 | -(require 'beg-end) |
25 | -(require 'ar-comment-lor) |
26 | - |
27 | -;; (require 'python-components-mode) |
28 | +(defvar bug-numbered-tests nil |
29 | + "Tests following reports at https://bugs.launchpad.net/python-mode") |
30 | |
31 | (setq bug-numbered-tests |
32 | (if (featurep 'xemacs) |
33 | @@ -34,65 +32,140 @@ |
34 | 'previous-statement-lp:637955-test) |
35 | (list |
36 | 'mark-block-region-lp:328806-test |
37 | + 'mark-decorators-lp:328851-test |
38 | 'nested-dictionaries-indent-lp:328791-test |
39 | 'triple-quoted-string-dq-lp:302834-test |
40 | + 'fore-00007F-breaks-indentation-lp:328788-test |
41 | 'dq-in-tqs-string-lp:328813-test |
42 | + 'flexible-indentation-lp:328842-test |
43 | + 'py-current-defun-lp:328846-test |
44 | + 'cls-pseudo-keyword-lp:328849-test |
45 | + 'hungry-delete-backwards-lp:328853-test |
46 | + 'hungry-delete-forward-lp:328853-test |
47 | + 'beg-end-of-defun-lp:303622-test |
48 | 'bullet-lists-in-comments-lp:328782-test |
49 | + 'imenu-newline-arglist-lp:328783-test |
50 | + 'imenu-matches-in-docstring-lp:436285-test |
51 | + 'exceptions-not-highlighted-lp:473525-test |
52 | 'fill-paragraph-problems-lp:710373-test |
53 | 'nested-indents-lp:328775-test |
54 | 'previous-statement-lp:637955-test |
55 | - 'multiline-assignment-indentation-lp:629916-test |
56 | + 'inbound-indentation-multiline-assignement-lp:629916-test |
57 | 'indentation-of-continuation-lines-lp:691185-test |
58 | - 'goto-beginning-of-tqs-lp:735328-test))) |
59 | + 'syntaxerror-on-py-execute-region-lp:691542-test |
60 | + 'goto-beginning-of-tqs-lp:735328-test |
61 | + 'class-treated-as-keyword-lp:709478-test |
62 | + 'py-decorators-face-lp:744335-test |
63 | + 'indent-after-return-lp:745208-test |
64 | + 'keep-assignements-column-lp:748198-test |
65 | + 'indent-triplequoted-to-itself-lp:752252-test |
66 | + 'multiline-listings-indent-lp:761946-test |
67 | + 'new-page-char-causes-loop-lp:762498-test |
68 | + 'nested-dicts-indent-lp:763756-test |
69 | + |
70 | + ))) |
71 | + |
72 | |
73 | (defun py-run-bug-numbered-tests (&optional arg) |
74 | + "With ARG greater 1 keep test buffers open. " |
75 | (interactive "p") |
76 | (dolist (ele bug-numbered-tests) |
77 | (funcall ele arg))) |
78 | |
79 | +(defun py-bug-tests-intern (testname &optional arg teststring) |
80 | + (if arg |
81 | + (progn |
82 | + (set-buffer (get-buffer-create (replace-regexp-in-string "-base$" "-test" (prin1-to-string testname)))) |
83 | + (switch-to-buffer (current-buffer)) |
84 | + (erase-buffer) |
85 | + (insert teststring) |
86 | + (fundamental-mode) |
87 | + (python-mode) |
88 | + (funcall testname) |
89 | + (message "%s" (concat (replace-regexp-in-string "-base$" "-test" (prin1-to-string testname)) " passed")) |
90 | + (unless (< 1 arg) |
91 | + (set-buffer-modified-p 'nil) |
92 | + (kill-buffer (current-buffer)))) |
93 | + (with-temp-buffer |
94 | + (let ((font-lock-verbose nil)) |
95 | + (insert teststring) |
96 | + (funcall testname))))) |
97 | + |
98 | + |
99 | +(defun sexp-commands-lp:328778-test (&optional arg load-branch-function) |
100 | + "With ARG greater 1 keep test buffer open. |
101 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. |
102 | + |
103 | +Reported by Montanaro on 2003-08-05 |
104 | +\[ ... ] |
105 | + You can kill balanced expressions on a |
106 | + particular line but it's not possible to remove the |
107 | + whole of an 'if' or 'while' block." |
108 | + (interactive "p") |
109 | + (let ((teststring "# Examples from http://diveintopython.org/ |
110 | + |
111 | +def main(argv): |
112 | + grammar = \"kant.xml\" |
113 | + try: |
114 | + opts, args = getopt.getopt(argv, \"hg:d\", [\"help\", \"grammar=\"]) |
115 | + except getopt.GetoptError: |
116 | + usage() |
117 | + sys.exit(2) |
118 | + for opt, arg in opts: |
119 | + if opt in (\"-h\", \"--help\"): |
120 | + usage() |
121 | + sys.exit() |
122 | + elif opt == '-d': |
123 | + global _debug |
124 | + _debug = 1 |
125 | + elif opt in (\"-g\", \"--grammar\"): |
126 | + grammar = arg |
127 | +")) |
128 | + (when load-branch-function (funcall load-branch-function)) |
129 | + (py-bug-tests-intern 'sexp-commands-lp:328778 arg teststring))) |
130 | + |
131 | +(defun sexp-commands-lp:328778 () |
132 | + (let ((size (buffer-size))) |
133 | + (goto-char (point-min)) |
134 | + (forward-line 15) |
135 | + (py-kill-clause) |
136 | + (assert (< (buffer-size) size) nil "sexp-commands-lp:328778 test failed") |
137 | + (assert (eq (buffer-size) 526) nil "sexp-commands-lp:328778 test failed") |
138 | + (kill-line 1) |
139 | + (indent-according-to-mode) |
140 | + (forward-line -4) |
141 | + (py-kill-block) |
142 | + (assert (eq (buffer-size) 324) nil "sexp-commands-lp:328778 test failed") |
143 | + )) |
144 | + |
145 | (defun nested-dictionaries-indent-lp:328791-test (&optional arg load-branch-function) |
146 | + "With ARG greater 1 keep test buffer open. |
147 | + |
148 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
149 | (interactive "p") |
150 | (when load-branch-function (funcall load-branch-function)) |
151 | - (nested-dictionaries-indent-lp:328791-intern arg)) |
152 | - |
153 | -(defun nested-dictionaries-indent-lp:328791-intern (&optional arg) |
154 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
155 | - (lexical-let ((nested-dictionaries-indent-lp:328791-teststring " |
156 | + (let ((teststring " |
157 | d = {'a':{'b':3, |
158 | 'c':4}} |
159 | ")) |
160 | - (if arg |
161 | - (progn |
162 | - (set-buffer (get-buffer-create "nested-dictionaries-indent-lp:328791")) |
163 | - (switch-to-buffer (current-buffer)) |
164 | - (erase-buffer) |
165 | - (insert nested-dictionaries-indent-lp:328791-teststring) |
166 | - (fundamental-mode) |
167 | - (nested-dictionaries-indent-lp:328791-base)) |
168 | - (with-temp-buffer |
169 | - (insert nested-dictionaries-indent-lp:328791-teststring) |
170 | - (nested-dictionaries-indent-lp:328791-base))))) |
171 | - |
172 | -(defun nested-dictionaries-indent-lp:328791-base () |
173 | - (python-mode) |
174 | - (goto-char (point-min)) |
175 | - (forward-line 2) |
176 | - (assert (eq 14 (py-compute-indentation t))) |
177 | - (message "%s" "nested-dictionaries-indent-lp:328791-test passed")) |
178 | - |
179 | -(defun mark-block-region-lp:328806-test (&optional arg load-branch-function) |
180 | - (interactive "p") |
181 | - (when load-branch-function (funcall load-branch-function)) |
182 | - (mark-block-region-lp:328806-intern arg)) |
183 | - |
184 | -(defun mark-block-region-lp:328806-intern (&optional arg) |
185 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
186 | - (lexical-let ((mark-block-region-lp:328806-teststring "def f(): |
187 | + (py-bug-tests-intern 'nested-dictionaries-indent-lp:328791 arg teststring))) |
188 | + |
189 | +(defun nested-dictionaries-indent-lp:328791 () |
190 | + (let ((py-indent-honors-multiline-listing t)) |
191 | + (goto-char (point-min)) |
192 | + (forward-line 2) |
193 | + (assert (eq 14 (py-compute-indentation)))) |
194 | + |
195 | + (defun mark-block-region-lp:328806-test (&optional arg load-branch-function) |
196 | + "With ARG greater 1 keep test buffer open. |
197 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
198 | + (interactive "p") |
199 | + (when load-branch-function (funcall load-branch-function)) |
200 | + (let ((teststring "def f(): |
201 | \"\"\" |
202 | class blah blah |
203 | \"\"\" |
204 | if a: |
205 | - |
206 | ar_atpt_python_list_roh = ([ |
207 | 'python-expression', |
208 | |
209 | @@ -101,98 +174,206 @@ |
210 | 'python-statement', |
211 | ]) |
212 | ")) |
213 | - (if arg |
214 | - (progn |
215 | - (set-buffer (get-buffer-create "mark-block-region-lp:328806")) |
216 | - (switch-to-buffer (current-buffer)) |
217 | - (erase-buffer) |
218 | - (insert mark-block-region-lp:328806-teststring) |
219 | - (fundamental-mode) |
220 | - (mark-block-region-lp:328806-base)) |
221 | - (with-temp-buffer |
222 | - (insert mark-block-region-lp:328806-teststring) |
223 | - (mark-block-region-lp:328806-base))))) |
224 | + (py-bug-tests-intern 'mark-block-region-lp:328806 arg teststring)))) |
225 | |
226 | -(defun mark-block-region-lp:328806-base () |
227 | - (python-mode) |
228 | +(defun mark-block-region-lp:328806 () |
229 | (forward-line -2) |
230 | (py-mark-block) |
231 | - (assert (< (region-beginning) (region-end)) nil "mark-block-region-lp:328806 test failed!") |
232 | - (message "%s" "mark-block-region-lp:328806 test passed")) |
233 | + (assert (< (region-beginning) (region-end)) nil "mark-block-region-lp:328806 test failed!")) |
234 | + |
235 | +(defun flexible-indentation-lp:328842-test (&optional arg load-branch-function) |
236 | + "With ARG greater 1 keep test buffer open. |
237 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
238 | + (interactive "p") |
239 | + (let ((teststring " |
240 | +\(long, sequence, of_items, |
241 | + that, needs, to_be, wrapped) = input_list |
242 | + |
243 | +packed_entry = (long, sequence, of_items, |
244 | +that, needs, to_be, wrapped) |
245 | + |
246 | +\( whitespaced, long, sequence, of_items, |
247 | + that, needs, to_be, wrapped) = input_list |
248 | +")) |
249 | + (when load-branch-function (funcall load-branch-function)) |
250 | + (py-bug-tests-intern 'flexible-indentation-lp:328842 arg teststring))) |
251 | + |
252 | +(defun flexible-indentation-lp:328842 () |
253 | + (let ((py-indent-honors-multiline-listing t)) |
254 | + (goto-char (point-min)) |
255 | + (forward-line 2) |
256 | + (indent-according-to-mode) |
257 | + (assert (eq 1 (current-indentation)) nil "flexible-indentation-lp:328842 test failed") |
258 | + (forward-line 3) |
259 | + (indent-according-to-mode) |
260 | + (assert (eq 16 (current-indentation)) nil "flexible-indentation-lp:328842 test failed") |
261 | + (forward-line 3) |
262 | + (indent-according-to-mode) |
263 | + (assert (eq 2 (current-indentation)) nil "flexible-indentation-lp:328842 test failed"))) |
264 | + |
265 | +(defun py-current-defun-lp:328846-test (&optional arg load-branch-function) |
266 | + "With ARG greater 1 keep test buffer open. |
267 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
268 | + (interactive "p") |
269 | + (let ((teststring python-mode-teststring)) |
270 | + (when load-branch-function (funcall load-branch-function)) |
271 | + (py-bug-tests-intern 'py-current-defun-lp:328846-base arg teststring))) |
272 | + |
273 | +(defun py-current-defun-lp:328846-base () |
274 | + (goto-char 331) |
275 | + (assert (string= "OrderedDict1" (py-current-defun)) nil "py-current-defun-lp:328846 test failed")) |
276 | + |
277 | +(defun cls-pseudo-keyword-lp:328849-test (&optional arg load-branch-function) |
278 | + (interactive "p") |
279 | + (let ((teststring "class Foo(object): |
280 | + def summat(cls, x): |
281 | + ..... |
282 | + summat = classmethod(summat) |
283 | +")) |
284 | + (when load-branch-function (funcall load-branch-function)) |
285 | + (py-bug-tests-intern 'cls-pseudo-keyword-lp:328849-base arg teststring))) |
286 | + |
287 | +(defun cls-pseudo-keyword-lp:328849-base () |
288 | + (let ((font-lock-verbose nil)) |
289 | + (font-lock-mode 1) |
290 | + (font-lock-fontify-buffer) |
291 | + (goto-char 36) |
292 | + (sit-for 0.1) |
293 | + (assert (eq (get-char-property (point) 'face) 'py-pseudo-keyword-face) nil "cls-pseudo-keyword-lp:328849 test failed "))) |
294 | + |
295 | +(defun mark-decorators-lp:328851-test (&optional arg load-branch-function) |
296 | + "With ARG greater 1 keep test buffer open. |
297 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
298 | + (interactive "p") |
299 | + (let ((teststring "@foo.bar |
300 | +def baz(): |
301 | + pass |
302 | +")) |
303 | + (when load-branch-function (funcall load-branch-function)) |
304 | + (py-bug-tests-intern 'mark-decorators-lp:328851-base arg teststring))) |
305 | + |
306 | +(defun mark-decorators-lp:328851-base () |
307 | + (goto-char 10) |
308 | + (py-mark-def t) |
309 | + (assert (eq 28 (- (region-end)(region-beginning))) nil "mark-decorators-lp:328851 test failed")) |
310 | + |
311 | +(defun beg-end-of-defun-lp:303622-test (&optional arg load-branch-function) |
312 | + "With ARG greater 1 keep test buffer open. |
313 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
314 | + (interactive "p") |
315 | + (when load-branch-function (funcall load-branch-function)) |
316 | + (let ((teststring " |
317 | +class f(): |
318 | + \"\"\" |
319 | + class blah blah |
320 | + \"\"\" |
321 | + if a: |
322 | + ar_atpt_python_list_roh = ([ |
323 | + 'python-expression', |
324 | + |
325 | + # def ar_thingatpt_write_lists (&optional datei): |
326 | + 'python-partial-expression', |
327 | + 'python-statement', |
328 | + ]) |
329 | +")) |
330 | + (py-bug-tests-intern 'beg-end-of-defun-lp:303622 arg teststring))) |
331 | + |
332 | +(defun beg-end-of-defun-lp:303622 () |
333 | + (goto-char (point-min)) |
334 | + (forward-line 2) |
335 | + (end-of-defun) |
336 | + (assert (eq 292 (point)) nil "beg-end-of-defun-lp:303622 test failed!") |
337 | + (beginning-of-defun) |
338 | + (assert (eq 2 (point)) nil "beg-end-of-defun-lp:303622 test failed!")) |
339 | |
340 | (defun dq-in-tqs-string-lp:328813-test (&optional arg load-branch-function) |
341 | + "With ARG greater 1 keep test buffer open. |
342 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
343 | (interactive "p") |
344 | (when load-branch-function (funcall load-branch-function)) |
345 | - (dq-in-tqs-string-lp:328813-test-intern arg)) |
346 | - |
347 | -(defun dq-in-tqs-string-lp:328813-test-intern (&optional arg) |
348 | - (set-buffer (get-buffer-create "tqs-string-lp:328813-test")) |
349 | - (erase-buffer) |
350 | - (insert |
351 | - " |
352 | + (let ((teststring " |
353 | # Bug #328813 (sf1775975) |
354 | print \"\"\" \"Hi!\" I'm a doc string\"\"\" |
355 | print ''' 'Hi!' I'm a doc string''' |
356 | print \"\"\" ''' \"Hi!\" I'm a doc string ''' \"\"\" |
357 | print ''' \"\"\" \"Hi!\" I'm a doc string \"\"\" ''' |
358 | -") |
359 | - (when arg (switch-to-buffer (current-buffer))) |
360 | - (python-mode) |
361 | - (font-lock-mode 1) |
362 | - (font-lock-fontify-buffer) |
363 | - (goto-char 78) |
364 | - (lexical-let ((erg (face-at-point))) |
365 | - (insert "\"") |
366 | - (assert (ar-triplequoted-in-p-atpt) nil "tqs-string-lp:328813 failed: In triplequoted string not recognised!") |
367 | +")) |
368 | + (py-bug-tests-intern 'dq-in-tqs-string-lp:328813 arg teststring))) |
369 | + |
370 | +(defun dq-in-tqs-string-lp:328813 () |
371 | + (let ((font-lock-verbose nil)) |
372 | + (font-lock-mode 1) |
373 | (font-lock-fontify-buffer) |
374 | - (assert (eq erg (face-at-point)) "Being stuck inside triple-quoted-string 328813 test. ")) |
375 | - (goto-char 122) |
376 | - (assert (ar-triplequoted-in-p-atpt) nil "tqs-string-lp:328813 failed: In triplequoted at point 122 not recognised!") |
377 | - (when arg (message "%s" "dq-in-tqs-string-lp:328813-test passed"))) |
378 | + (goto-char 78) |
379 | + (let ((erg (get-char-property (point) 'face))) |
380 | + (message "%s" erg) |
381 | + (insert "\"") |
382 | + (font-lock-fontify-buffer) |
383 | + (message "%s" erg) |
384 | + (message "%s" (get-char-property (point) 'face)) |
385 | + (assert (eq erg (get-char-property (point) 'face)) nil "dq-in-tqs-string-lp:328813 test failed ") |
386 | + (goto-char 122)))) |
387 | + |
388 | +(defun imenu-matches-in-docstring-lp:436285-test (&optional arg load-branch-function) |
389 | + "With ARG greater 1 keep test buffer open. |
390 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
391 | + (interactive "p") |
392 | + (let ((teststring " |
393 | +class foo(): |
394 | + \"\"\" |
395 | + class hello(object): |
396 | + def __init__(self): |
397 | + ... |
398 | + \"\"\" |
399 | + pass |
400 | +")) |
401 | + (when load-branch-function (funcall load-branch-function)) |
402 | + (py-bug-tests-intern 'imenu-matches-in-docstring-lp:436285-base arg teststring))) |
403 | + |
404 | +(defun imenu-matches-in-docstring-lp:436285-base () |
405 | + (goto-char 40) |
406 | + (assert (eq (py-beginning-of-def-or-class) 2) nil "imenu-matches-in-docstring-lp:436285 test failed")) |
407 | |
408 | (defun fill-paragraph-problems-lp:710373-test (&optional arg load-branch-function) |
409 | + "With ARG greater 1 keep test buffer open. |
410 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
411 | (interactive "p") |
412 | (when load-branch-function (funcall load-branch-function)) |
413 | - (fill-paragraph-problems-lp:710373-test-intern arg)) |
414 | + (let ((teststring " |
415 | + \"\"\" |
416 | + triple-quoted string containing \"quotation\" marks. |
417 | + triple-quoted string containing \"quotation\" marks. |
418 | + triple-quoted string containing \"quotation\" marks. |
419 | + triple-quoted string containing \"quotation\" marks. |
420 | + triple-quoted string containing \"quotation\" marks. |
421 | + \"\"\" |
422 | +")) |
423 | + (fill-paragraph-problems-lp:710373-test-intern arg teststring))) |
424 | |
425 | -(defun fill-paragraph-problems-lp:710373-test-intern (&optional arg) |
426 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
427 | +(defun fill-paragraph-problems-lp:710373-test-intern (arg teststring) |
428 | (let ((tmp-dir "/tmp/") |
429 | (fpp-exec-buffer "fill-paragraph-problems-lp:710373") |
430 | - (diff-buffer "fpp-lp:710373-old") |
431 | - (fpp-teststring " |
432 | - \"\"\" |
433 | - triple-quoted string containing \"quotation\" marks. |
434 | - triple-quoted string containing \"quotation\" marks. |
435 | - triple-quoted string containing \"quotation\" marks. |
436 | - triple-quoted string containing \"quotation\" marks. |
437 | - triple-quoted string containing \"quotation\" marks. |
438 | - \"\"\" |
439 | -")) |
440 | + (diff-buffer "fpp-lp:710373-old")) |
441 | (set-buffer (get-buffer-create diff-buffer)) |
442 | (erase-buffer) |
443 | (fundamental-mode) |
444 | - (insert fpp-teststring) |
445 | + (insert teststring) |
446 | (write-file (concat tmp-dir diff-buffer)) |
447 | (if arg |
448 | (progn |
449 | (set-buffer (get-buffer-create fpp-exec-buffer)) |
450 | (switch-to-buffer (current-buffer)) |
451 | (erase-buffer) |
452 | - (insert fpp-teststring) |
453 | + (insert teststring) |
454 | (fundamental-mode) |
455 | - (fill-paragraph-problems-lp:710373-test-base tmp-dir fpp-exec-buffer diff-buffer)) |
456 | + (fill-paragraph-problems-lp:710373-test-base arg tmp-dir fpp-exec-buffer diff-buffer) |
457 | + ) |
458 | (with-temp-buffer |
459 | - (insert fpp-teststring) |
460 | - (fill-paragraph-problems-lp:710373-test-base tmp-dir fpp-exec-buffer diff-buffer))))) |
461 | - |
462 | -(defun fill-paragraph-problems-lp:710373-test-base (tmp-dir fpp-exec-buffer diff-buffer) |
463 | - (python-mode) |
464 | - (goto-char 48) |
465 | - ;; the following lines work when called from edebug |
466 | -;; (message "%s" (get-text-property 6 'syntax-table)) |
467 | -;; (assert (eq 15 (car (get-text-property 6 'syntax-table)))) |
468 | -;; (assert (eq 6 (nth 8 (parse-partial-sexp (point-min) (point))))) |
469 | + (insert teststring) |
470 | + (fill-paragraph-problems-lp:710373-test-base arg tmp-dir fpp-exec-buffer diff-buffer))))) |
471 | + |
472 | +(defun fill-paragraph-problems-lp:710373-test-base (arg tmp-dir fpp-exec-buffer diff-buffer) |
473 | + (goto-char 48) |
474 | (if (functionp 'py-fill-paragraph) |
475 | (py-fill-paragraph) |
476 | (python-fill-paragraph)) |
477 | @@ -205,213 +386,525 @@ |
478 | (set-buffer "*Diff*") |
479 | (sit-for 1) |
480 | (assert (numberp (progn (goto-char (point-min))(search-forward "no differences" nil t 1))) t) |
481 | - (message "%s" "fill-paragraph-problems-lp:710373 passed"))) |
482 | - |
483 | + (message "%s" "fill-paragraph-problems-lp:710373 passed")) |
484 | + (set-buffer "fill-paragraph-problems-lp:710373") |
485 | + (unless (< 1 arg) |
486 | + (set-buffer-modified-p 'nil) |
487 | + (kill-buffer (current-buffer)))) |
488 | + |
489 | (defun triple-quoted-string-dq-lp:302834-test (&optional arg load-branch-function) |
490 | + "With ARG greater 1 keep test buffer open. |
491 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
492 | (interactive "p") |
493 | (when load-branch-function (funcall load-branch-function)) |
494 | - (triple-quoted-string-dq-lp:302834-test-intern arg)) |
495 | - |
496 | -(defun triple-quoted-string-dq-lp:302834-test-intern (&optional arg) |
497 | - (with-temp-buffer |
498 | - (insert "class OrderedDict1(dict): |
499 | + (let ((teststring "class OrderedDict1(dict): |
500 | \"\"\" |
501 | This implementation of a dictionary keeps track of the order |
502 | in which keys were inserted. |
503 | - \"\"\"") |
504 | - (when arg (switch-to-buffer (current-buffer))) |
505 | - (python-mode) |
506 | + \"\"\"")) |
507 | + (py-bug-tests-intern 'triple-quoted-string-dq-lp:302834 arg teststring))) |
508 | + |
509 | +(defun triple-quoted-string-dq-lp:302834 () |
510 | + (let ((font-lock-verbose nil)) |
511 | (font-lock-mode 1) |
512 | (font-lock-fontify-buffer) |
513 | (goto-char 78) |
514 | - (lexical-let ((erg (face-at-point))) |
515 | + (let ((erg (get-char-property (point) 'face))) |
516 | (insert "\"") |
517 | - (assert (ar-triplequoted-dq-in-p-atpt) nil "In triplequoted string not recognised!") |
518 | (font-lock-fontify-buffer) |
519 | - (assert (eq erg (face-at-point)) "Being stuck inside triple-quoted-string. Did not reach beginning of class.")) |
520 | - (when arg (message "%s" "triple-quoted-string-dq-lp:302834-test passed")))) |
521 | + (assert (eq erg (get-char-property (point) 'face)) "Being stuck inside triple-quoted-string. Did not reach beginning of class.")))) |
522 | |
523 | -(defun multiline-assignment-indentation-lp:629916-test (&optional arg load-branch-function) |
524 | +(defun inbound-indentation-multiline-assignement-lp:629916-test (&optional arg load-branch-function) |
525 | + "With ARG greater 1 keep test buffer open. |
526 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
527 | (interactive "p") |
528 | (when load-branch-function (funcall load-branch-function)) |
529 | - (multiline-assignment-indentation-lp:629916-intern arg)) |
530 | - |
531 | -(defun multiline-assignment-indentation-lp:629916-intern (&optional arg) |
532 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
533 | - (lexical-let ((multiline-assignment-indentation-lp:629916-teststring "foo_long_long_long_long = ( |
534 | + (let ((teststring "foo_long_long_long_long = ( |
535 | bar_long_long_long_long[ |
536 | (x_long_long_long_long == X) & |
537 | (y_long_long_long_long == Y)]) |
538 | ")) |
539 | - (if arg |
540 | - (progn |
541 | - (set-buffer (get-buffer-create "multiline-assignment-indentation-lp:629916-test")) |
542 | - (switch-to-buffer (current-buffer)) |
543 | - (erase-buffer) |
544 | - (insert multiline-assignment-indentation-lp:629916-teststring) |
545 | - (fundamental-mode) |
546 | - (multiline-assignment-indentation-lp:629916-base)) |
547 | - (with-temp-buffer |
548 | - (insert multiline-assignment-indentation-lp:629916-teststring) |
549 | - (multiline-assignment-indentation-lp:629916-base))))) |
550 | - |
551 | -(defun multiline-assignment-indentation-lp:629916-base () |
552 | - (python-mode) |
553 | - (goto-char (point-min)) |
554 | - (forward-line 1) |
555 | - (indent-according-to-mode) |
556 | - (assert (eq 27 (current-indentation)) nil "multiline-assignment-indentation-lp:629916-test fails") |
557 | - (end-of-line) |
558 | - (search-backward "[") |
559 | - (newline) |
560 | - (indent-according-to-mode) |
561 | - (assert (eq 27 (current-indentation)) nil "multiline-assignment-indentation-lp:629916-test fails") |
562 | - (forward-line 1) |
563 | - (indent-according-to-mode) |
564 | - (assert (eq 28 (current-indentation)) nil "multiline-assignment-indentation-lp:629916-test fails") |
565 | - (forward-line 1) |
566 | - (indent-according-to-mode) |
567 | - (assert (eq 28 (current-indentation)) nil "multiline-assignment-indentation-lp:629916-test fails") |
568 | - (message "%s" "multiline-assignment-indentation-lp:629916-test passed" )) |
569 | + (py-bug-tests-intern 'inbound-indentation-multiline-assignement-lp:629916 arg teststring))) |
570 | + |
571 | + |
572 | +(defun inbound-indentation-multiline-assignement-lp:629916 () |
573 | + (let ((py-indent-honors-multiline-listing t)) |
574 | + (goto-char (point-min)) |
575 | + (forward-line 1) |
576 | + (indent-according-to-mode) |
577 | + (assert (eq 27 (current-indentation)) nil "inbound-indentation-multiline-assignement-lp:629916 test failed") |
578 | + (end-of-line) |
579 | + (search-backward "[") |
580 | + (newline) |
581 | + (indent-according-to-mode) |
582 | + (assert (eq 27 (current-indentation)) nil "inbound-indentation-multiline-assignement-lp:629916 test failed") |
583 | + (forward-line 1) |
584 | + (indent-according-to-mode) |
585 | + (assert (eq 28 (current-indentation)) nil "inbound-indentation-multiline-assignement-lp:629916 test failed") |
586 | + (forward-line 1) |
587 | + (indent-according-to-mode) |
588 | + (assert (eq 28 (current-indentation)) nil "inbound-indentation-multiline-assignement-lp:629916 test failed"))) |
589 | |
590 | (defun previous-statement-lp:637955-test (&optional arg load-branch-function) |
591 | + "With ARG greater 1 keep test buffer open. |
592 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
593 | (interactive "p") |
594 | (when load-branch-function (funcall load-branch-function)) |
595 | - (previous-statement-lp:637955-test-intern arg)) |
596 | - |
597 | -(defun previous-statement-lp:637955-test-intern (&optional arg) |
598 | - (set-buffer (get-buffer-create "previous-statement-lp:637955-test")) |
599 | - (erase-buffer) |
600 | - (insert "class OrderedDict1(dict): |
601 | + (let ((teststring "class OrderedDict1(dict): |
602 | \"\"\" |
603 | This implementation of a dictionary keeps track of the order |
604 | in which keys were inserted. |
605 | - \"\"\"") |
606 | - (when arg (switch-to-buffer (current-buffer))) |
607 | + \"\"\"")) |
608 | + (py-bug-tests-intern 'previous-statement-lp:637955 arg teststring))) |
609 | + |
610 | +(defun previous-statement-lp:637955 () |
611 | (beginning-of-line) |
612 | (py-previous-statement) |
613 | (assert (eq 31 (point)) nil "Being stuck inside triple-quoted-string 637955 test. Did not reach beginning of class.") |
614 | - (when arg (message "%s" "previous-statement-lp:637955-test passed"))) |
615 | + ) |
616 | |
617 | (defun nested-indents-lp:328775-test (&optional arg load-branch-function) |
618 | + "With ARG greater 1 keep test buffer open. |
619 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
620 | (interactive "p") |
621 | (when load-branch-function (funcall load-branch-function)) |
622 | - (nested-indents-lp:328775-test-intern arg)) |
623 | - |
624 | -(defun nested-indents-lp:328775-test-intern (&optional arg) |
625 | - (set-buffer (get-buffer-create "nested-indents-lp:328775")) |
626 | - (erase-buffer) |
627 | - (when arg (switch-to-buffer (current-buffer))) |
628 | - (insert " |
629 | + (let ((teststring " |
630 | if x > 0: |
631 | for i in range(100): |
632 | print i |
633 | -") |
634 | - (save-excursion (insert "else: |
635 | - print \"All done\"")) |
636 | - (when arg (switch-to-buffer (current-buffer))) |
637 | - (python-mode) |
638 | - (font-lock-mode 1) |
639 | - (font-lock-fontify-buffer) |
640 | - (assert (eq 4 (py-compute-indentation t)) nil "nested-indents-lp:328775-test fails!") |
641 | - (indent-according-to-mode) |
642 | - (goto-char (point-max)) |
643 | - (save-excursion (insert "\nelif x < 0: |
644 | - print \"x is negative\"")) |
645 | - (assert (eq 8 (py-compute-indentation t)) nil "nested-indents-lp:328775-test fails!") |
646 | - (forward-line 1) |
647 | - (assert (eq 0 (py-compute-indentation t)) nil "nested-indents-lp:328775-test fails!") |
648 | - (message "%s" "nested-indents-lp:328775-test passed")) |
649 | + else: |
650 | + print \"All done\" |
651 | +elif x < 0: |
652 | + print \"x is negative\" |
653 | +")) |
654 | + (py-bug-tests-intern 'nested-indents-lp:328775 arg teststring))) |
655 | + |
656 | +(defun nested-indents-lp:328775 () |
657 | + (let ((font-lock-verbose nil)) |
658 | + (font-lock-mode 1) |
659 | + (font-lock-fontify-buffer) |
660 | + (assert (eq 4 (py-compute-indentation)) nil "nested-indents-lp:328775 test failed!") |
661 | + (goto-char 41) |
662 | + (assert (eq 8 (py-compute-indentation)) nil "nested-indents-lp:328775 test failed!") |
663 | + (forward-line 1) |
664 | + (assert (eq 4 (py-compute-indentation)) nil "nested-indents-lp:328775 test failed!"))) |
665 | |
666 | (defun bullet-lists-in-comments-lp:328782-test (&optional arg load-branch-function) |
667 | + "With ARG greater 1 keep test buffer open. |
668 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
669 | (interactive "p") |
670 | (when load-branch-function (funcall load-branch-function)) |
671 | - (bullet-lists-in-comments-lp:328782-test-intern arg)) |
672 | + (let ((teststring)) |
673 | + (bullet-lists-in-comments-lp:328782-test-intern arg teststring))) |
674 | |
675 | -(defun bullet-lists-in-comments-lp:328782-test-intern (&optional arg) |
676 | - (set-buffer (get-buffer-create "bullet-lists-in-comments-lp:328782-test")) |
677 | - (erase-buffer) |
678 | - ;; (with-temp-buffer |
679 | - (insert " |
680 | +(defun bullet-lists-in-comments-lp:328782-test-intern (&optional arg teststring) |
681 | + (let ((font-lock-verbose nil)) |
682 | + (set-buffer (get-buffer-create "bullet-lists-in-comments-lp:328782-test")) |
683 | + (erase-buffer) |
684 | + ;; (with-temp-buffer |
685 | + (insert " |
686 | ## * If the filename is a directory and not a Maildir nor |
687 | ## an MH Mailbox, it will be processed as a Mailbox --this bug named here: bullet-lists-in-comments-lp:328782.htm-- |
688 | ## directory consisting of just .txt and .lorien files. |
689 | ") |
690 | - (when arg (switch-to-buffer (current-buffer))) |
691 | - (python-mode) |
692 | - (font-lock-mode 1) |
693 | - (font-lock-fontify-buffer) |
694 | - (goto-char 100) |
695 | - (if (functionp 'py-fill-paragraph) |
696 | - (py-fill-paragraph) |
697 | - (python-fill-paragraph) |
698 | -)) |
699 | + (when arg (switch-to-buffer (current-buffer))) |
700 | + (python-mode) |
701 | + (font-lock-mode 1) |
702 | + (font-lock-fontify-buffer) |
703 | + (goto-char 100) |
704 | + (if (functionp 'py-fill-paragraph) |
705 | + (py-fill-paragraph) |
706 | + (python-fill-paragraph))) |
707 | + (set-buffer "bullet-lists-in-comments-lp:328782-test") |
708 | + (unless (< 1 arg) |
709 | + (set-buffer-modified-p 'nil) |
710 | + (kill-buffer (current-buffer)))) |
711 | + |
712 | +(defun imenu-newline-arglist-lp:328783-test (&optional arg load-branch-function) |
713 | + "With ARG greater 1 keep test buffer open. |
714 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
715 | + (interactive "p") |
716 | + (let ((teststring "def editor(db, db_name, table_name, |
717 | + #api |
718 | + dbapi,dbapi_exceptions): |
719 | + pass")) |
720 | + (when load-branch-function (funcall load-branch-function)) |
721 | + (py-bug-tests-intern 'imenu-newline-arglist-lp:328783-base arg teststring))) |
722 | + |
723 | +(defun imenu-newline-arglist-lp:328783-base () |
724 | + (goto-char 60) |
725 | + (assert (eq (py-beginning-of-def-or-class) 1) nil "imenu-newline-arglist-lp:328783 test failed")) |
726 | + |
727 | +(defun hungry-delete-backwards-lp:328853-test (&optional arg load-branch-function) |
728 | + "With ARG greater 1 keep test buffer open. |
729 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
730 | + (interactive "p") |
731 | + (let ((teststring python-mode-teststring)) |
732 | + (when load-branch-function (funcall load-branch-function)) |
733 | + (py-bug-tests-intern 'hungry-delete-backwards-lp:328853 arg teststring))) |
734 | + |
735 | +(defun hungry-delete-backwards-lp:328853 () |
736 | + (goto-char 421) |
737 | + (py-hungry-delete-backwards) |
738 | + (assert (eq 416 (point)) nil "hungry-delete-backwards test failed")) |
739 | + |
740 | +(defun hungry-delete-forward-lp:328853-test (&optional arg load-branch-function) |
741 | + "With ARG greater 1 keep test buffer open. |
742 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
743 | + (interactive "p") |
744 | + (let ((teststring python-mode-teststring)) |
745 | + (when load-branch-function (funcall load-branch-function)) |
746 | + (py-bug-tests-intern 'hungry-delete-forward-lp:328853 arg teststring))) |
747 | + |
748 | +(defun hungry-delete-forward-lp:328853 () |
749 | + (goto-char 409) |
750 | + (py-hungry-delete-forward) |
751 | + (assert (looking-at "#") nil "hungry-delete-backwards test failed")) |
752 | |
753 | (defun indentation-of-continuation-lines-lp:691185-test (&optional arg load-branch-function) |
754 | + "With ARG greater 1 keep test buffer open. |
755 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
756 | (interactive "p") |
757 | (when load-branch-function (funcall load-branch-function)) |
758 | - (indentation-of-continuation-lines-lp:691185-test-intern arg)) |
759 | - |
760 | -(defun indentation-of-continuation-lines-lp:691185-test-intern (&optional arg) |
761 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
762 | - (lexical-let ((indentation-of-continuation-lines-lp:691185-test-teststring " def f(val): |
763 | + (let ((teststring " def f(val): |
764 | # current behavior - indent to just after the first space |
765 | a_verry_loonng_variable_nammmee = \\ |
766 | val |
767 | ")) |
768 | - (if arg |
769 | - (progn |
770 | - (set-buffer (get-buffer-create "indentation-of-continuation-lines-lp:691185-test")) |
771 | - (switch-to-buffer (current-buffer)) |
772 | - (erase-buffer) |
773 | - (insert indentation-of-continuation-lines-lp:691185-test-teststring) |
774 | - (fundamental-mode) |
775 | - (indentation-of-continuation-lines-lp:691185-test-base)) |
776 | - (with-temp-buffer |
777 | - (insert indentation-of-continuation-lines-lp:691185-test-teststring) |
778 | - (indentation-of-continuation-lines-lp:691185-test-base))))) |
779 | - |
780 | -(defun indentation-of-continuation-lines-lp:691185-test-base () |
781 | - (python-mode) |
782 | - (goto-char (point-min)) |
783 | - (forward-line 3) |
784 | - (indent-according-to-mode) |
785 | - (assert (eq 10 (current-indentation)) nil "indentation-of-continuation-lines-lp:691185-test failed!") |
786 | - (message "%s" "indentation-of-continuation-lines-lp:691185-test passed")) |
787 | - |
788 | + (py-bug-tests-intern 'indentation-of-continuation-lines-lp:691185 arg teststring))) |
789 | + |
790 | +(defun indentation-of-continuation-lines-lp:691185 () |
791 | + (let ((py-continuation-offset 2)) |
792 | + (goto-char (point-min)) |
793 | + (forward-line 3) |
794 | + (indent-according-to-mode) |
795 | + (assert (eq 10 (current-indentation)) nil "indentation-of-continuation-lines-lp:691185-test failed!"))) |
796 | |
797 | (defun goto-beginning-of-tqs-lp:735328-test (&optional arg load-branch-function) |
798 | + "With ARG greater 1 keep test buffer open. |
799 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
800 | (interactive "p") |
801 | (when load-branch-function (funcall load-branch-function)) |
802 | - (goto-beginning-of-tqs-lp:735328-test-intern arg)) |
803 | - |
804 | -(defun goto-beginning-of-tqs-lp:735328-test-intern (&optional arg) |
805 | - "If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked. " |
806 | - (lexical-let ((goto-beginning-of-tqs-lp:735328-test-teststring "class Foo(object): |
807 | + (let ((teststring "class Foo(object): |
808 | \"\"\" |
809 | This docstring isn't indented, test should pass anyway. |
810 | \"\"\" |
811 | ")) |
812 | - (if arg |
813 | - (progn |
814 | - (set-buffer (get-buffer-create "goto-beginning-of-tqs-lp:735328-test")) |
815 | - (switch-to-buffer (current-buffer)) |
816 | - (erase-buffer) |
817 | - (insert goto-beginning-of-tqs-lp:735328-test-teststring) |
818 | - (fundamental-mode) |
819 | - (goto-beginning-of-tqs-lp:735328-test-base)) |
820 | - (with-temp-buffer |
821 | - (insert goto-beginning-of-tqs-lp:735328-test-teststring) |
822 | - (goto-beginning-of-tqs-lp:735328-test-base))))) |
823 | + (py-bug-tests-intern 'goto-beginning-of-tqs-lp:735328 arg teststring))) |
824 | |
825 | -(defun goto-beginning-of-tqs-lp:735328-test-base () |
826 | - (python-mode) |
827 | +(defun goto-beginning-of-tqs-lp:735328 () |
828 | (goto-char (point-min)) |
829 | (forward-line 4) |
830 | (indent-according-to-mode) |
831 | (assert (eq 4 (current-column)) nil "goto-beginning-of-tqs-lp:735328-test failed") |
832 | - (message "goto-beginning-of-tqs-lp:735328-test passed")) |
833 | - |
834 | + ) |
835 | + |
836 | +(defun class-treated-as-keyword-lp:709478-test (&optional arg load-branch-function) |
837 | + "With ARG greater 1 keep test buffer open. |
838 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
839 | + (interactive "p") |
840 | + (when load-branch-function (funcall load-branch-function)) |
841 | + (let ((teststring "foo = [ |
842 | + T.div( |
843 | + T.tabl(*trows), |
844 | + |
845 | + CLASS='blok',) |
846 | +] |
847 | +")) |
848 | + (py-bug-tests-intern 'class-treated-as-keyword-lp:709478 arg teststring))) |
849 | + |
850 | +(defun class-treated-as-keyword-lp:709478 () |
851 | + (let ((font-lock-verbose nil)) |
852 | + (font-lock-fontify-buffer) |
853 | + (goto-char 63) |
854 | + (sit-for 0.1) |
855 | + (assert (eq (get-char-property (point) 'face) 'font-lock-string-face) nil "class-treated-as-keyword-lp:709478d 1th test failed") |
856 | + (goto-char 57) |
857 | + (assert (not (get-char-property (point) 'face)) nil "class-treated-as-keyword-lp:709478-test 2th failed"))) |
858 | + |
859 | + |
860 | +(defun fore-00007F-breaks-indentation-lp:328788-test (&optional arg load-branch-function) |
861 | + "With ARG greater 1 keep test buffer open. |
862 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
863 | + (interactive "p") |
864 | + (let ((teststring "class a: |
865 | + def __init__(self): |
866 | + self.StyleSetSpec(self.STYLE_FIELD, |
867 | +\"fore:#00007F\" ) |
868 | + self.StyleSetSpec(self.STYLE_FIELD, |
869 | +\"fore:#00007F\" ) |
870 | + self.StyleSetSpec(self.STYLE_FIELD, |
871 | +\"fore:#00007F\" ) |
872 | + self.StyleSetSpec(self.STYLE_FIELD, |
873 | +\"fore:#00007F\" ) |
874 | +")) |
875 | + (when load-branch-function (funcall load-branch-function)) |
876 | + (py-bug-tests-intern 'fore-00007F-breaks-indentation-lp:328788 arg teststring))) |
877 | + |
878 | +(defun fore-00007F-breaks-indentation-lp:328788 () |
879 | + (goto-char (point-min)) |
880 | + (forward-line 1) |
881 | + (indent-according-to-mode) |
882 | + (forward-line 1) |
883 | + (assert (eq 8 (py-compute-indentation)) nil "fore-00007F-breaks-indentation test failed") |
884 | + (indent-according-to-mode) |
885 | + (forward-line 1) |
886 | + (indent-according-to-mode) |
887 | + (forward-line 1) |
888 | + (assert (eq 8 (py-compute-indentation)) nil "fore-00007F-breaks-indentation test failed") |
889 | + (indent-according-to-mode) |
890 | + (forward-line 1) |
891 | + (indent-according-to-mode) |
892 | + (forward-line 1) |
893 | + (assert (eq 8 (py-compute-indentation)) nil "fore-00007F-breaks-indentation test failed") |
894 | + (indent-according-to-mode) |
895 | + (forward-line 1) |
896 | + (indent-according-to-mode) |
897 | + (forward-line 1) |
898 | + (assert (eq 8 (py-compute-indentation)) nil "fore-00007F-breaks-indentation test failed") |
899 | + (indent-according-to-mode) |
900 | + (forward-line 1) |
901 | + (indent-according-to-mode) |
902 | + ) |
903 | + |
904 | +(defun exceptions-not-highlighted-lp:473525-test (&optional arg load-branch-function) |
905 | + "With ARG greater 1 keep test buffer open. |
906 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
907 | + (interactive "p") |
908 | + (let ((teststring "excs = (SystemExit, Exception, KeyboardInterrupt)")) |
909 | + (when load-branch-function (funcall load-branch-function)) |
910 | + (py-bug-tests-intern 'exceptions-not-highlighted-lp:473525 arg teststring))) |
911 | + |
912 | +(defun exceptions-not-highlighted-lp:473525 () |
913 | + (let ((font-lock-verbose nil)) |
914 | + (goto-char 39) |
915 | + (font-lock-fontify-buffer) |
916 | + (sit-for 0.1) |
917 | + (assert (eq (get-char-property (point) 'face) 'py-exception-name-face) nil "exceptions-not-highlighted-lp:473525 test failed"))) |
918 | + |
919 | +(defun syntaxerror-on-py-execute-region-lp:691542-test (&optional arg load-branch-function) |
920 | + (interactive "p") |
921 | + (let ((teststring "# -*- coding: utf-8 -*- |
922 | +print \"Poet Friedrich Hölderlin\" |
923 | +")) |
924 | + (when load-branch-function (funcall load-branch-function)) |
925 | + (py-bug-tests-intern 'syntaxerror-on-py-execute-region-lp:691542-base arg teststring))) |
926 | + |
927 | +(defun syntaxerror-on-py-execute-region-lp:691542-base () |
928 | + (forward-line -1) |
929 | + (assert (py-execute-region (line-beginning-position) (line-end-position)) nil "syntaxerror-on-py-execute-region-lp:691542 test failed")) |
930 | + |
931 | +(defun backslashed-continuation-line-indent-lp:742993-test (&optional arg load-branch-function) |
932 | + "With ARG greater 1 keep test buffer open. |
933 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
934 | + (interactive "p") |
935 | + (let ((teststring " |
936 | +self.last_abc_attr = \ |
937 | +self.last_xyz_attr = \ |
938 | +self.last_abc_other = \ |
939 | +self.last_xyz_other = None |
940 | + |
941 | +self.last_abc_attr = \\ |
942 | +self.last_xyz_attr = \\ |
943 | +self.last_abc_other = \\ |
944 | +self.last_xyz_other = None |
945 | + |
946 | +self.last_abc_attr = \\ |
947 | +self.last_xyz_attr = \\ |
948 | +self.last_abc_other = \\ |
949 | +self.last_xyz_other = None |
950 | + |
951 | +self.last_abc_attr = \\ |
952 | +self.last_xyz_attr = \\ |
953 | +self.last_abc_other = \\ |
954 | +self.last_xyz_other = None |
955 | +")) |
956 | + (when load-branch-function (funcall load-branch-function)) |
957 | + (py-bug-tests-intern 'backslashed-continuation-line-indent-lp:742993 arg teststring))) |
958 | + |
959 | +(defun backslashed-continuation-line-indent-lp:742993 () |
960 | + (let ((py-continuation-offset 2)) |
961 | + (goto-char (point-min)) |
962 | + (forward-line 2) |
963 | + (insert (concat "\n# py-continuation-offset: " (number-to-string py-continuation-offset))) |
964 | + (forward-line 2) |
965 | + (indent-according-to-mode) |
966 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
967 | + (forward-line 1) |
968 | + (indent-according-to-mode) |
969 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
970 | + (forward-line 1) |
971 | + (indent-according-to-mode) |
972 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
973 | + |
974 | + (setq py-continuation-offset 4) |
975 | + (forward-line 1) |
976 | + (insert (concat "\n# py-continuation-offset: " (number-to-string py-continuation-offset))) |
977 | + (forward-line 2) |
978 | + (indent-according-to-mode) |
979 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
980 | + (forward-line 1) |
981 | + (indent-according-to-mode) |
982 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
983 | + (forward-line 1) |
984 | + (indent-according-to-mode) |
985 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
986 | + |
987 | + (setq py-continuation-offset 6) |
988 | + (forward-line 1) |
989 | + (insert (concat "\n# py-continuation-offset: " (number-to-string py-continuation-offset))) |
990 | + (forward-line 2) |
991 | + (indent-according-to-mode) |
992 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
993 | + (forward-line 1) |
994 | + (indent-according-to-mode) |
995 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
996 | + (forward-line 1) |
997 | + (indent-according-to-mode) |
998 | + (assert (eq (current-indentation) py-continuation-offset) nil "backslashed-continuation-line-indent-lp:742993 test failed") |
999 | +)) |
1000 | + |
1001 | +(defun py-decorators-face-lp:744335-test (&optional arg load-branch-function) |
1002 | + "With ARG greater 1 keep test buffer open. |
1003 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
1004 | + (interactive "p") |
1005 | + (let ((teststring "@foo.bar |
1006 | +def baz(): |
1007 | + pass |
1008 | +")) |
1009 | + (when load-branch-function (funcall load-branch-function)) |
1010 | + (py-bug-tests-intern 'py-decorators-face-lp:744335 arg teststring))) |
1011 | + |
1012 | +(defun py-decorators-face-lp:744335 () |
1013 | + (let ((font-lock-verbose nil)) |
1014 | + (goto-char 7) |
1015 | + (font-lock-fontify-buffer) |
1016 | + (sit-for 0.1) |
1017 | + (assert (eq (get-char-property (point) 'face) 'py-decorators-face) nil "py-decorators-face-lp:744335 test failed"))) |
1018 | + |
1019 | +(defun indent-after-return-lp:745208-test (&optional arg load-branch-function) |
1020 | + "With ARG greater 1 keep test buffer open. |
1021 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
1022 | + (interactive "p") |
1023 | + (let ((teststring "class FOO\(): |
1024 | + if len(sys.argv)==1: |
1025 | + usage\() |
1026 | + sys.exit\() |
1027 | + |
1028 | + def build_extension\(self, ext): |
1029 | + |
1030 | + if ext.name == '_ctypes': |
1031 | + if not self.configure_ctypes\(ext): |
1032 | + return |
1033 | + |
1034 | + try: |
1035 | + build_ext.build_extension\(self, ext) |
1036 | + except \(CCompilerError, DistutilsError) as why: |
1037 | + self.announce\('WARNING: building of extension \"%s\" |
1038 | +failed: %s' % |
1039 | + \(ext.name, sys.exc_info()\[1])) |
1040 | + self.failed.append(ext.name) |
1041 | + return |
1042 | + # Workaround for Mac OS X: The Carbon-based modules cannot be |
1043 | + # reliably imported into a command-line Python |
1044 | + if 'Carbon' in ext.extra_link_args: |
1045 | + self.announce\( |
1046 | + 'WARNING: skipping import check for Carbon-based |
1047 | +\"%s\"' % |
1048 | + ext.name) |
1049 | + return |
1050 | +")) |
1051 | + (when load-branch-function (funcall load-branch-function)) |
1052 | + (py-bug-tests-intern 'indent-after-return-lp:745208 arg teststring))) |
1053 | + |
1054 | +(defun indent-after-return-lp:745208 () |
1055 | + (goto-char (point-max)) |
1056 | + (assert (eq 8 (py-compute-indentation)) nil "indent-after-return-lp:745208 test failed") |
1057 | + ) |
1058 | + |
1059 | +(defun keep-assignements-column-lp:748198-test (&optional arg load-branch-function) |
1060 | + "With ARG greater 1 keep test buffer open. |
1061 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
1062 | + (interactive "p") |
1063 | + (let ((teststring "bar = foo(a=1, |
1064 | + b=2, |
1065 | + c=3) |
1066 | +")) |
1067 | + (when load-branch-function (funcall load-branch-function)) |
1068 | + (py-bug-tests-intern 'keep-assignements-column-lp:748198 arg teststring))) |
1069 | + |
1070 | +(defun keep-assignements-column-lp:748198 () |
1071 | + (goto-char 45) |
1072 | + (py-newline-and-indent) |
1073 | + (assert (eq 0 (current-column)) nil "py-vor test failed")) |
1074 | + |
1075 | +(defun indent-triplequoted-to-itself-lp:752252-test (&optional arg load-branch-function) |
1076 | + "With ARG greater 1 keep test buffer open. |
1077 | +If no `load-branch-function' is specified, make sure the appropriate branch is loaded. Otherwise default python-mode will be checked." |
1078 | + (interactive "p") |
1079 | + (let ((teststring "def foo(): |
1080 | + \"\"\"The real foo thing.\n")) |
1081 | + (when load-branch-function (funcall load-branch-function)) |
1082 | + (py-bug-tests-intern 'indent-triplequoted-to-itself-lp:752252-base arg teststring))) |
1083 | + |
1084 | +(defun indent-triplequoted-to-itself-lp:752252-base () |
1085 | + (assert (eq 4 (py-compute-indentation)) nil "indent-triplequoted-to-itself-lp:752252 test failed")) |
1086 | + |
1087 | +(defun multiline-listings-indent-lp:761946-test (&optional arg load-branch-function) |
1088 | + (interactive "p") |
1089 | + (let ((teststring "def foo(): |
1090 | + do_something_first( |
1091 | + a=1, |
1092 | + b=2, |
1093 | +")) |
1094 | + (when load-branch-function (funcall load-branch-function)) |
1095 | + (py-bug-tests-intern 'multiline-listings-indent-lp:761946-base arg teststring))) |
1096 | + |
1097 | +(defun multiline-listings-indent-lp:761946-base () |
1098 | + (goto-char (point-min)) |
1099 | + (forward-line 3) |
1100 | + (back-to-indentation) |
1101 | + (assert (eq 8 (py-compute-indentation)) nil "multiline-listings-indent-lp:761946 test failed")) |
1102 | + |
1103 | +(defun new-page-char-causes-loop-lp:762498-test (&optional arg load-branch-function) |
1104 | + (interactive "p") |
1105 | + (let ((teststring "class Foo: |
1106 | + def baz(self): |
1107 | + |
1108 | + |
1109 | |
1110 | +")) |
1111 | + (when load-branch-function (funcall load-branch-function)) |
1112 | + (py-bug-tests-intern 'new-page-char-causes-loop-lp:762498-base arg teststring))) |
1113 | + |
1114 | +(defun new-page-char-causes-loop-lp:762498-base () |
1115 | + (goto-char (point-min)) |
1116 | + (forward-line 2) |
1117 | + (assert (eq 8 (py-compute-indentation)) "new-page-char-causes-loop-lp:762498 test failed")) |
1118 | + |
1119 | +(defun nested-dicts-indent-lp:763756-test (&optional arg load-branch-function) |
1120 | + (interactive "p") |
1121 | + (let ((teststring "feature_operation_matrix = { |
1122 | + \"character\": { |
1123 | + \"kill\": \"{ctrl-k}\",{ |
1124 | + } |
1125 | + } |
1126 | + } |
1127 | +)) |
1128 | +")) |
1129 | + (when load-branch-function (funcall load-branch-function)) |
1130 | + (py-bug-tests-intern 'nested-dicts-indent-lp:763756-base arg teststring))) |
1131 | + |
1132 | +(defun nested-dicts-indent-lp:763756-base () |
1133 | + (let ((py-indent-honors-multiline-listing nil)) |
1134 | + (goto-char (point-min)) |
1135 | + (forward-line 1) |
1136 | + (assert (eq 4 (py-compute-indentation)) nil "nested-dicts-indent-lp:763756 test failed") |
1137 | + (forward-line 1) |
1138 | + (assert (eq 8 (py-compute-indentation)) nil "nested-dicts-indent-lp:763756 test failed") |
1139 | + (forward-line 1) |
1140 | + (assert (eq 12 (py-compute-indentation)) nil "nested-dicts-indent-lp:763756 test failed"))) |
1141 | |
1142 | (provide 'py-bug-numbered-tests) |
1143 | ;;; py-bug-numbered-tests.el ends here |
1144 | + |
1145 | + |
1146 | |
1147 | === added file 'python-mode-test.el' |
1148 | --- python-mode-test.el 1970-01-01 00:00:00 +0000 |
1149 | +++ python-mode-test.el 2011-04-18 19:44:32 +0000 |
1150 | @@ -0,0 +1,202 @@ |
1151 | +;;; python-mode-test.el --- tests for Emacs python-mode.el |
1152 | + |
1153 | +;; Copyright (C) 2011 Andreas Roehler |
1154 | + |
1155 | +;; Author: Andreas Roehler <andreas.roehler@online.de> |
1156 | +;; Keywords: lisp, languages |
1157 | + |
1158 | +;; This program is free software; you can redistribute it and/or modify |
1159 | +;; it under the terms of the GNU General Public License as published by |
1160 | +;; the Free Software Foundation, either version 3 of the License, or |
1161 | +;; (at your option) any later version. |
1162 | + |
1163 | +;; This program is distributed in the hope that it will be useful, |
1164 | +;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
1165 | +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1166 | +;; GNU General Public License for more details. |
1167 | + |
1168 | +;; You should have received a copy of the GNU General Public License |
1169 | +;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
1170 | + |
1171 | +;;; Commentary: |
1172 | + |
1173 | +;; A couple of test cases for python-mode.el |
1174 | + |
1175 | +;;; Code: |
1176 | + |
1177 | +(setq python-mode-tests |
1178 | + (if (featurep 'xemacs) |
1179 | + (list |
1180 | + 'py-beginning-of-block-or-clause-test) |
1181 | + (list |
1182 | + |
1183 | + 'py-beginning-of-block-test |
1184 | + 'py-end-of-block-test |
1185 | + 'py-beginning-of-block-or-clause-test |
1186 | + 'py-end-of-block-or-clause-test |
1187 | + 'py-beginning-of-def-test |
1188 | + 'py-end-of-def-test |
1189 | + 'py-beginning-of-def-or-class-test |
1190 | + 'py-end-of-def-or-class-test |
1191 | + 'py-electric-backspace-test |
1192 | + 'py-electric-delete-test |
1193 | + |
1194 | +))) |
1195 | + |
1196 | +(defun py-run-tests (&optional arg) |
1197 | + (interactive "p") |
1198 | + (dolist (ele python-mode-tests) |
1199 | + (funcall ele arg))) |
1200 | + |
1201 | +(defvar python-mode-teststring "class OrderedDict1(dict): |
1202 | + \"\"\" |
1203 | + This implementation of a dictionary keeps track of the order |
1204 | + in which keys were inserted. |
1205 | + \"\"\" |
1206 | + |
1207 | + def __init__(self, d={}): |
1208 | + self._keys = d.keys() |
1209 | + dict.__init__(self, d) |
1210 | + |
1211 | + def f(): |
1212 | + \"\"\" |
1213 | + class for in 'for in while with blah' |
1214 | + \"\"\" |
1215 | + if a: |
1216 | + |
1217 | + ar_atpt_python_list_roh = ([ |
1218 | + 'python-expression', |
1219 | + |
1220 | + # def ar_thingatpt_write_lists (&optional datei): |
1221 | + 'python-partial-expression', |
1222 | + 'python-statement', |
1223 | + ]) |
1224 | +" |
1225 | + "String used for tests by python-mode-test.el") |
1226 | + |
1227 | +(defun py-beginning-of-block-test (&optional arg load-branch-function) |
1228 | + (interactive "p") |
1229 | + (let ((teststring python-mode-teststring)) |
1230 | + (when load-branch-function (funcall load-branch-function)) |
1231 | + (py-bug-tests-intern 'py-beginning-of-block-base arg teststring))) |
1232 | + |
1233 | +(defun py-beginning-of-block-base () |
1234 | + (goto-char (point-max)) |
1235 | + (py-beginning-of-block) |
1236 | + (assert (looking-at "if") nil "py-beginning-of-block test failed")) |
1237 | + |
1238 | +(defun py-end-of-block-test (&optional arg load-branch-function) |
1239 | + (interactive "p") |
1240 | + (let ((teststring python-mode-teststring)) |
1241 | + (when load-branch-function (funcall load-branch-function)) |
1242 | + (py-bug-tests-intern 'py-end-of-block-base arg teststring))) |
1243 | + |
1244 | +(defun py-end-of-block-base () |
1245 | + (py-beginning-of-block) |
1246 | + (py-end-of-block) |
1247 | + (assert (eq (point) 556) nil "py-end-of-block test failed")) |
1248 | + |
1249 | +(defun py-beginning-of-block-or-clause-test (&optional arg load-branch-function) |
1250 | + (interactive "p") |
1251 | + (let ((teststring python-mode-teststring)) |
1252 | + (when load-branch-function (funcall load-branch-function)) |
1253 | + (py-bug-tests-intern 'py-beginning-of-block-or-clause-base arg teststring))) |
1254 | + |
1255 | +(defun py-beginning-of-block-or-clause-base () |
1256 | + (goto-char (point-max)) |
1257 | + (py-beginning-of-block-or-clause) |
1258 | + (assert (looking-at "if") nil "py-beginning-of-block-or-clause test failed")) |
1259 | + |
1260 | + |
1261 | +(defun py-end-of-block-or-clause-test (&optional arg load-branch-function) |
1262 | + (interactive "p") |
1263 | + (let ((teststring python-mode-teststring)) |
1264 | + (when load-branch-function (funcall load-branch-function)) |
1265 | + (py-bug-tests-intern 'py-end-of-block-or-clause-base arg teststring))) |
1266 | + |
1267 | +(defun py-end-of-block-or-clause-base () |
1268 | + (py-beginning-of-block-or-clause) |
1269 | + (py-end-of-block-or-clause) |
1270 | + (assert (eq (point) 556) nil "py-end-of-block-or-clause test failed")) |
1271 | + |
1272 | +(defun py-beginning-of-def-test (&optional arg load-branch-function) |
1273 | + (interactive "p") |
1274 | + (let ((teststring python-mode-teststring)) |
1275 | + (when load-branch-function (funcall load-branch-function)) |
1276 | + (py-bug-tests-intern 'py-beginning-of-def-base arg teststring))) |
1277 | + |
1278 | +(defun py-beginning-of-def-base () |
1279 | + (py-beginning-of-def) |
1280 | + (assert (eq (point) 238) nil "py-beginning-of-def test failed") |
1281 | + ) |
1282 | + |
1283 | +(defun py-end-of-def-test (&optional arg load-branch-function) |
1284 | + (interactive "p") |
1285 | + (let ((teststring python-mode-teststring)) |
1286 | + (when load-branch-function (funcall load-branch-function)) |
1287 | + (py-bug-tests-intern 'py-end-of-def-base arg teststring))) |
1288 | + |
1289 | +(defun py-end-of-def-base () |
1290 | + (py-beginning-of-def) |
1291 | + (py-end-of-def) |
1292 | + (assert (eq (point) 556) nil "py-end-of-def test failed") |
1293 | + ) |
1294 | + |
1295 | +(defun py-beginning-of-def-or-class-test (&optional arg load-branch-function) |
1296 | + (interactive "p") |
1297 | + (let ((teststring python-mode-teststring)) |
1298 | + (when load-branch-function (funcall load-branch-function)) |
1299 | + (py-bug-tests-intern 'py-beginning-of-def-or-class-base arg teststring))) |
1300 | + |
1301 | +(defun py-beginning-of-def-or-class-base () |
1302 | + (py-beginning-of-def-or-class t) |
1303 | + (assert (eq (point) 1) nil "py-beginning-of-def-or-class test failed")) |
1304 | + |
1305 | +(defun py-end-of-def-or-class-test (&optional arg load-branch-function) |
1306 | + (interactive "p") |
1307 | + (let ((teststring python-mode-teststring)) |
1308 | + (when load-branch-function (funcall load-branch-function)) |
1309 | + (py-bug-tests-intern 'py-end-of-def-or-class-base arg teststring))) |
1310 | + |
1311 | +(defun py-end-of-def-or-class-base () |
1312 | + (py-beginning-of-def-or-class t) |
1313 | + (py-end-of-def-or-class t) |
1314 | + (assert (eq (point) 556) nil "py-end-of-def-or-class test failed")) |
1315 | + |
1316 | +(defun py-electric-backspace-test (&optional arg load-branch-function) |
1317 | + (interactive "p") |
1318 | + (let ((teststring python-mode-teststring)) |
1319 | + (when load-branch-function (funcall load-branch-function)) |
1320 | + (py-bug-tests-intern 'py-electric-backspace-base arg teststring))) |
1321 | + |
1322 | +(defun py-electric-backspace-base () |
1323 | + (goto-char 232) |
1324 | + (py-newline-and-indent) |
1325 | + (assert (eq 241 (point)) nil "py-electric-backspace test #1 failed") |
1326 | + (py-electric-backspace) |
1327 | + (assert (eq 4 (current-column)) nil "py-electric-backspace test #2 failed") |
1328 | + (py-electric-backspace) |
1329 | + (assert (eq 0 (current-column)) nil "py-electric-backspace test #3 failed") |
1330 | + (py-electric-backspace) |
1331 | + (assert (eq 232 (point)) nil "py-electric-backspace test #4 failed")) |
1332 | + |
1333 | + |
1334 | +(defun py-electric-delete-test (&optional arg load-branch-function) |
1335 | + (interactive "p") |
1336 | + (let ((teststring python-mode-teststring)) |
1337 | + (when load-branch-function (funcall load-branch-function)) |
1338 | + (py-bug-tests-intern 'py-electric-delete-base arg teststring))) |
1339 | + |
1340 | +(defun py-electric-delete-base () |
1341 | + (goto-char 202) |
1342 | + (py-electric-delete) |
1343 | + (assert (eq 4 (length (progn (looking-at "[ \t]+")(match-string-no-properties 0)))) nil "py-electric-delete test #1 failed") |
1344 | + (py-electric-delete) |
1345 | + (assert (not (looking-at "[ \t]+")) nil "py-electric-delete test #2 failed") |
1346 | + (py-electric-delete) |
1347 | + (assert (looking-at "ict") nil "py-electric-delete test #2 failed") |
1348 | + ) |
1349 | + |
1350 | + |
1351 | +(provide 'python-mode-test) |
1352 | +;;; python-mode-test.el ends here |
1353 | |
1354 | === added file 'python-mode-tests.sh' |
1355 | --- python-mode-tests.sh 1970-01-01 00:00:00 +0000 |
1356 | +++ python-mode-tests.sh 2011-04-18 19:44:32 +0000 |
1357 | @@ -0,0 +1,88 @@ |
1358 | +#!/bin/bash |
1359 | + # -- |
1360 | + |
1361 | +# Author: Andreas Roehler <andreas.roehler@online.de> |
1362 | + |
1363 | +# This program is free software; you can redistribute it and/or modify |
1364 | +# it under the terms of the GNU General Public License as published by |
1365 | +# the Free Software Foundation, either version 3 of the License, or |
1366 | +# (at your option) any later version. |
1367 | +# This program is distributed in the hope that it will be useful, |
1368 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1369 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1370 | +# GNU General Public License for more details. |
1371 | +# You should have received a copy of the GNU General Public License |
1372 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1373 | +# Commentary: |
1374 | + |
1375 | +# tests Emacs python-mode |
1376 | +# |
1377 | +# Code: |
1378 | + |
1379 | +# Edit the vars pointing to the directories/files |
1380 | +# holding your python-mode for test |
1381 | + |
1382 | +# assumes python-mode files in current directory |
1383 | + |
1384 | +# the path |
1385 | +PDIR=`pwd` |
1386 | + |
1387 | +# python-mode file to load |
1388 | +if [ -s "python-components-mode.el" ]; |
1389 | + then |
1390 | + PYTHONMODE="python-components-mode.el" |
1391 | + else |
1392 | + PYTHONMODE="python-mode.el" |
1393 | +fi |
1394 | + |
1395 | +CCCMDS="~/emacs-23.2.94/lisp/progmodes/cc-cmds.el" |
1396 | +# file holding the tests |
1397 | +TESTFILE="py-bug-numbered-tests.el" |
1398 | +TESTFILE2="python-mode-test.el" |
1399 | +EMACS="/emacs-23.2.94/src/emacs" |
1400 | + |
1401 | +$HOME/$EMACS -Q --batch --eval "(message (emacs-version))" --eval "(when (featurep 'python-mode)(unload-feature 'python-mode t))" --eval "(add-to-list 'load-path \"$PDIR/\")" -load "$PDIR/$PYTHONMODE" -load "$PDIR/$TESTFILE" -load "$PDIR/$TESTFILE2" -load $CCCMDS \ |
1402 | +--funcall nested-dictionaries-indent-lp:328791-test \ |
1403 | +--funcall triple-quoted-string-dq-lp:302834-test \ |
1404 | +--funcall fore-00007F-breaks-indentation-lp:328788-test \ |
1405 | +--funcall dq-in-tqs-string-lp:328813-test \ |
1406 | +--funcall py-current-defun-lp:328846-test \ |
1407 | +--funcall cls-pseudo-keyword-lp:328849-test \ |
1408 | +--funcall mark-decorators-lp:328851-test \ |
1409 | +--funcall flexible-indentation-lp:328842-test \ |
1410 | +--funcall hungry-delete-backwards-lp:328853-test \ |
1411 | +--funcall hungry-delete-forward-lp:328853-test \ |
1412 | +--funcall beg-end-of-defun-lp:303622-test \ |
1413 | +--funcall bullet-lists-in-comments-lp:328782-test \ |
1414 | +--funcall imenu-newline-arglist-lp:328783-test \ |
1415 | +--funcall nested-indents-lp:328775-test \ |
1416 | +--funcall imenu-matches-in-docstring-lp:436285-test \ |
1417 | +--funcall exceptions-not-highlighted-lp:473525-test \ |
1418 | +--funcall previous-statement-lp:637955-test \ |
1419 | +--funcall inbound-indentation-multiline-assignement-lp:629916-test \ |
1420 | +--funcall indentation-of-continuation-lines-lp:691185-test \ |
1421 | +--funcall syntaxerror-on-py-execute-region-lp:691542-test \ |
1422 | +--funcall goto-beginning-of-tqs-lp:735328-test \ |
1423 | +--funcall class-treated-as-keyword-lp:709478-test \ |
1424 | +--funcall backslashed-continuation-line-indent-lp:742993-test \ |
1425 | +--funcall py-decorators-face-lp:744335-test \ |
1426 | +--funcall indent-after-return-lp:745208-test \ |
1427 | +--funcall keep-assignements-column-lp:748198-test \ |
1428 | +--funcall indent-triplequoted-to-itself-lp:752252-test \ |
1429 | +--funcall multiline-listings-indent-lp:761946-test \ |
1430 | +--funcall new-page-char-causes-loop-lp:762498-test \ |
1431 | +--funcall nested-dicts-indent-lp:763756-test \ |
1432 | +\ |
1433 | +--funcall py-beginning-of-block-test \ |
1434 | +--funcall py-end-of-block-test \ |
1435 | +--funcall py-beginning-of-block-or-clause-test \ |
1436 | +--funcall py-end-of-block-or-clause-test \ |
1437 | +--funcall py-beginning-of-def-test \ |
1438 | +--funcall py-end-of-def-test \ |
1439 | +--funcall py-beginning-of-def-or-class-test \ |
1440 | +--funcall py-end-of-def-or-class-test \ |
1441 | +--funcall py-electric-backspace-test \ |
1442 | +--funcall py-electric-delete-test |
1443 | + |
1444 | + |
1445 | + |
1446 | |
1447 | === modified file 'python-mode.el' |
1448 | --- python-mode.el 2011-03-15 21:31:20 +0000 |
1449 | +++ python-mode.el 2011-04-18 19:44:32 +0000 |
1450 | @@ -1,4 +1,4 @@ |
1451 | -;;; python-mode.el --- Major mode for editing Python programs |
1452 | +;; python-mode.el --- Major mode for editing Python programs |
1453 | |
1454 | ;; Copyright (C) 1992,1993,1994 Tim Peters |
1455 | |
1456 | @@ -86,13 +86,19 @@ |
1457 | ;; a texinfo manual would be very useful, but if you want to contribute one, |
1458 | ;; we'll certainly accept it! |
1459 | |
1460 | +;;; ToDo |
1461 | +;; Question calls of `py-guess-indent-offset', as |
1462 | +;; required indent may change throughout the buffer. |
1463 | +;; Rather may it be called by argument |
1464 | + |
1465 | + |
1466 | ;;; Code: |
1467 | |
1468 | (require 'comint) |
1469 | (require 'custom) |
1470 | -(require 'cl) |
1471 | (require 'compile) |
1472 | (require 'ansi-color) |
1473 | +(eval-when-compile (require 'cl)) |
1474 | |
1475 | |
1476 | |
1477 | ;; user definable variables |
1478 | @@ -109,6 +115,11 @@ |
1479 | :type 'boolean |
1480 | :group 'python) |
1481 | |
1482 | +(defcustom py-indent-honors-multiline-listing nil |
1483 | + "If `t', indents to 1+ column of opening delimiter. If `nil', indent adds one level to the beginning of statement. Default is `nil'. " |
1484 | + :type 'boolean |
1485 | + :group 'python) |
1486 | + |
1487 | (defcustom py-python-command "python" |
1488 | "*Shell command used to start Python interpreter." |
1489 | :type 'string |
1490 | @@ -158,12 +169,30 @@ |
1491 | you're editing someone else's Python code." |
1492 | :type 'integer |
1493 | :group 'python) |
1494 | +(make-variable-buffer-local 'py-indent-offset) |
1495 | + |
1496 | +(defcustom py-backslashed-continuation-indent 2 |
1497 | + "Indent of continuation-lines realised by backslashes. " |
1498 | + :type 'integer |
1499 | + :group 'python) |
1500 | +(make-variable-buffer-local 'py-indent-in-delimiter) |
1501 | + |
1502 | +(defcustom py-lhs-inbound-indent 1 |
1503 | + "When line starts a multiline-assignement: How many colums indent should be more than opening bracket, brace or parenthesis. " |
1504 | + :type 'integer |
1505 | + :group 'python) |
1506 | +(make-variable-buffer-local 'py-lhs-inbound-indent) |
1507 | + |
1508 | +(defcustom py-rhs-inbound-indent 1 |
1509 | + "When inside a multiline-assignement: How many colums indent should be more than opening bracket, brace or parenthesis. " |
1510 | + :type 'integer |
1511 | + :group 'python) |
1512 | +(make-variable-buffer-local 'py-rhs-inbound-indent) |
1513 | |
1514 | (defcustom py-continuation-offset 4 |
1515 | "*Additional amount of offset to give for some continuation lines. |
1516 | Continuation lines are those that immediately follow a backslash |
1517 | -terminated line. Only those continuation lines for a block opening |
1518 | -statement are given this extra offset." |
1519 | +terminated line. " |
1520 | :type 'integer |
1521 | :group 'python) |
1522 | |
1523 | @@ -289,13 +318,6 @@ |
1524 | :type 'function |
1525 | :group 'python) |
1526 | |
1527 | -(defcustom py-imenu-show-method-args-p nil |
1528 | - "*Controls echoing of arguments of functions & methods in the Imenu buffer. |
1529 | -When non-nil, arguments are printed." |
1530 | - :type 'boolean |
1531 | - :group 'python) |
1532 | -(make-variable-buffer-local 'py-indent-offset) |
1533 | - |
1534 | (defcustom py-pdbtrack-do-tracking-p t |
1535 | "*Controls whether the pdbtrack feature is enabled or not. |
1536 | When non-nil, pdbtrack is enabled in all comint-based buffers, |
1537 | @@ -330,6 +352,20 @@ |
1538 | :type '(repeat string) |
1539 | :group 'python) |
1540 | |
1541 | +(defcustom py-current-defun-show t |
1542 | + "If `py-current-defun' should jump to the definition, highlight it while waiting PY-WHICH-FUNC-DELAY seconds, before returning to previous position. |
1543 | + |
1544 | +Default is `t'." |
1545 | + |
1546 | +:type 'boolean |
1547 | +:group 'python) |
1548 | + |
1549 | +(defcustom py-current-defun-delay 2 |
1550 | + "When called interactively, `py-current-defun' should wait PY-WHICH-FUNC-DELAY seconds at the definition name found, before returning to previous position. " |
1551 | + |
1552 | +:type 'number |
1553 | +:group 'python) |
1554 | + |
1555 | ;; Not customizable |
1556 | (defvar py-master-file nil |
1557 | "If non-nil, execute the named file instead of the buffer's file. |
1558 | @@ -397,6 +433,10 @@ |
1559 | :type 'boolean |
1560 | :group 'python) |
1561 | |
1562 | +(defcustom py-mark-decorators nil |
1563 | + "If py-mark-def-or-class functions should mark decorators too. Default is `nil'. " |
1564 | + :type 'boolean |
1565 | + :group 'python) |
1566 | |
1567 | |
1568 | |
1569 | ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
1570 | @@ -425,11 +465,35 @@ |
1571 | ((nth 4 ppss) 'comment) |
1572 | (t nil)))) |
1573 | |
1574 | +(defvar empty-line-p-chars "^[ \t\r\f]*$" |
1575 | + "Empty-line-p-chars.") |
1576 | + |
1577 | +;;;###autoload |
1578 | +(defun empty-line-p (&optional iact) |
1579 | + "Returns t if cursor is at an empty line, nil otherwise." |
1580 | + (interactive "p") |
1581 | + (save-excursion |
1582 | + (let ((erg (progn |
1583 | + (beginning-of-line) |
1584 | + (looking-at empty-line-p-chars)))) |
1585 | + (when iact |
1586 | + (message "%s" erg)) |
1587 | + erg))) |
1588 | + |
1589 | +(defalias 'py-in-list-p 'py-list-beginning-position) |
1590 | +(defun py-list-beginning-position (&optional start) |
1591 | + "Return lists beginning position, nil if not inside. |
1592 | +Optional ARG indicates a start-position for `parse-partial-sexp'." |
1593 | + (interactive) |
1594 | + (let* ((ppstart (or start (point-min))) |
1595 | + (erg (nth 1 (parse-partial-sexp ppstart (point))))) |
1596 | + (when (interactive-p) (message "%s" erg)) |
1597 | + erg)) |
1598 | |
1599 | ;; 2009-09-10 a.roehler@web.de changed section start |
1600 | ;; from python.el, version "22.1" |
1601 | |
1602 | -(defconst python-font-lock-syntactic-keywords |
1603 | +(defconst py-font-lock-syntactic-keywords |
1604 | '(("[^\\]\\\\\\(?:\\\\\\\\\\)*\\(\\s\"\\)\\1\\(\\1\\)" |
1605 | (2 |
1606 | (7))) |
1607 | @@ -510,11 +574,51 @@ |
1608 | (modify-syntax-entry ?\_ "w" table) |
1609 | table)) |
1610 | |
1611 | -(defsubst python-in-string/comment () |
1612 | - "Return non-nil if point is in a Python literal (a comment or string)." |
1613 | - ;; We don't need to save the match data. |
1614 | +(defun py-in-comment-p () |
1615 | + "Return the beginning of current line's comment, if inside. " |
1616 | + (save-restriction |
1617 | + (widen) |
1618 | + (let* ((pps (parse-partial-sexp (line-beginning-position) (point))) |
1619 | + (erg (when (nth 4 pps) (nth 8 pps)))) |
1620 | + (unless erg |
1621 | + (when (looking-at (concat "^[ \t]*" comment-start-skip)) |
1622 | + (setq erg (point)))) |
1623 | + erg))) |
1624 | + |
1625 | +(defun py-in-string-p () |
1626 | + "Returns character address of start of comment or string, nil if not inside. " |
1627 | + (interactive) |
1628 | + (let* ((pps (parse-partial-sexp (point-min) (point))) |
1629 | + (erg (when (nth 3 pps) (nth 8 pps)))) |
1630 | + (save-excursion |
1631 | + (unless erg (setq erg |
1632 | + (progn |
1633 | + (when (looking-at "\"\\|'") |
1634 | + (forward-char 1) |
1635 | + (setq pps (parse-partial-sexp (point-min) (point))) |
1636 | + (when (nth 3 pps) (nth 8 pps))))))) |
1637 | + (when (interactive-p) (message "%s" erg)) |
1638 | + erg)) |
1639 | + |
1640 | +(defsubst py-in-string-or-comment-p () |
1641 | + "Return beginning position if point is in a Python literal (a comment or string)." |
1642 | (nth 8 (parse-partial-sexp (point-min) (point)))) |
1643 | |
1644 | +(defun py-in-triplequoted-string-p () |
1645 | + "Returns character address of start tqs-string, nil if not inside. " |
1646 | + (interactive) |
1647 | + (let* ((pps (parse-partial-sexp (point-min) (point))) |
1648 | + (erg (when (and (nth 3 pps) (nth 8 pps))(nth 2 pps)))) |
1649 | + (save-excursion |
1650 | + (unless erg (setq erg |
1651 | + (progn |
1652 | + (when (looking-at "\"\"\"\\|''''") |
1653 | + (goto-char (match-end 0)) |
1654 | + (setq pps (parse-partial-sexp (point-min) (point))) |
1655 | + (when (and (nth 3 pps) (nth 8 pps)) (nth 2 pps))))))) |
1656 | + (when (interactive-p) (message "%s" erg)) |
1657 | + erg)) |
1658 | + |
1659 | (defconst python-space-backslash-table |
1660 | (let ((table (copy-syntax-table py-mode-syntax-table))) |
1661 | (modify-syntax-entry ?\\ " " table) |
1662 | @@ -523,61 +627,41 @@ |
1663 | |
1664 | ;; 2009-09-10 a.roehler@web.de changed section end |
1665 | |
1666 | -(defconst py-emacs-features |
1667 | - (let (features) |
1668 | - features) |
1669 | - "A list of features extant in the Emacs you are using. |
1670 | -There are many flavors of Emacs out there, with different levels of |
1671 | -support for features needed by `python-mode'.") |
1672 | - |
1673 | -;; Face for None, True, False, self, and Ellipsis |
1674 | -(defvar py-pseudo-keyword-face 'py-pseudo-keyword-face |
1675 | - "Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.") |
1676 | -(make-face 'py-pseudo-keyword-face) |
1677 | +;; ;; Face for None, True, False, self, and Ellipsis |
1678 | +(defface py-pseudo-keyword-face |
1679 | + '((t (:inherit font-lock-keyword-face))) |
1680 | + "Face for pseudo keywords in Python mode, like self, True, False, Ellipsis." |
1681 | + :group 'python) |
1682 | +(defvar py-pseudo-keyword-face 'py-pseudo-keyword-face) |
1683 | |
1684 | ;; PEP 318 decorators |
1685 | -(defvar py-decorators-face 'py-decorators-face |
1686 | - "Face method decorators.") |
1687 | -(make-face 'py-decorators-face) |
1688 | +(defface py-decorators-face |
1689 | + '((t (:inherit font-lock-keyword-face))) |
1690 | + "Face method decorators." |
1691 | + :group 'python) |
1692 | +(defvar py-decorators-face 'py-decorators-face) |
1693 | |
1694 | ;; Face for builtins |
1695 | -(defvar py-builtins-face 'py-builtins-face |
1696 | - "Face for builtins like TypeError, object, open, and exec.") |
1697 | -(make-face 'py-builtins-face) |
1698 | +(defface py-builtins-face |
1699 | + '((t (:inherit font-lock-builtin-face))) |
1700 | + "Face for builtins like TypeError, object, open, and exec." |
1701 | + :group 'python) |
1702 | +(defvar py-builtins-face 'py-builtins-face) |
1703 | + |
1704 | +(defface py-class-name-face |
1705 | + '((t (:inherit font-lock-keyword-face))) |
1706 | + "Face for builtins like TypeError, object, open, and exec." |
1707 | + :group 'python) |
1708 | +(defvar py-class-name-face 'py-class-name-face) |
1709 | |
1710 | ;; XXX, TODO, and FIXME comments and such |
1711 | -(defvar py-XXX-tag-face 'py-XXX-tag-face |
1712 | - "Face for XXX, TODO, and FIXME tags") |
1713 | -(make-face 'py-XXX-tag-face) |
1714 | - |
1715 | -;; Face for class names |
1716 | -(defvar py-class-name-face 'py-class-name-face |
1717 | - "Face for Python class names.") |
1718 | -(make-face 'py-class-name-face) |
1719 | - |
1720 | -;; Face for exception names |
1721 | -(defvar py-exception-name-face 'py-exception-name-face |
1722 | - "Face for exception names like TypeError.") |
1723 | -(make-face 'py-exception-name-face) |
1724 | - |
1725 | -(defun py-font-lock-mode-hook () |
1726 | - (or (face-differs-from-default-p 'py-pseudo-keyword-face) |
1727 | - (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face)) |
1728 | - (or (face-differs-from-default-p 'py-builtins-face) |
1729 | - (copy-face 'font-lock-keyword-face 'py-builtins-face)) |
1730 | - (or (face-differs-from-default-p 'py-decorators-face) |
1731 | - (copy-face 'py-pseudo-keyword-face 'py-decorators-face)) |
1732 | - (or (face-differs-from-default-p 'py-XXX-tag-face) |
1733 | - (copy-face 'font-lock-comment-face 'py-XXX-tag-face)) |
1734 | - (or (face-differs-from-default-p 'py-class-name-face) |
1735 | - (copy-face 'font-lock-type-face 'py-class-name-face)) |
1736 | - (or (face-differs-from-default-p 'py-exception-name-face) |
1737 | - (copy-face 'font-lock-builtin-face 'py-exception-name-face)) |
1738 | - ) |
1739 | - |
1740 | -(add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook) |
1741 | - |
1742 | -(defvar python-font-lock-keywords |
1743 | +(defface py-exception-name-face |
1744 | + '((t (:inherit font-lock-builtin-face))) |
1745 | + "." |
1746 | + :group 'python) |
1747 | +(defvar py-exception-name-face 'py-exception-name-face) |
1748 | + |
1749 | +(defvar py-font-lock-keywords |
1750 | (let ((kw1 (mapconcat 'identity |
1751 | '("and" "assert" "break" "class" |
1752 | "continue" "def" "del" "elif" |
1753 | @@ -636,7 +720,7 @@ |
1754 | ) |
1755 | (list |
1756 | ;; decorators |
1757 | - '("^[ \t]*\\(@[a-zA-Z_][a-zA-Z_0-9]+\\)\\((.+)\\)?" 1 'py-decorators-face) |
1758 | + '("^[ \t]*\\(@[a-zA-Z_][a-zA-Z_0-9.]+\\)\\((.+)\\)?" 1 'py-decorators-face) |
1759 | ;; keywords |
1760 | (cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1) |
1761 | ;; builtins when they don't appear as object attributes |
1762 | @@ -657,7 +741,7 @@ |
1763 | '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" |
1764 | 1 font-lock-function-name-face) |
1765 | ;; pseudo-keywords |
1766 | - '("\\<\\(self\\|Ellipsis\\|True\\|False\\|None\\)\\>" |
1767 | + '("\\<\\(self\\|cls\\|Ellipsis\\|True\\|False\\|None\\)\\>" |
1768 | 1 py-pseudo-keyword-face) |
1769 | ;; XXX, TODO, and FIXME tags |
1770 | '("XXX\\|TODO\\|FIXME" 0 py-XXX-tag-face t) |
1771 | @@ -685,6 +769,7 @@ |
1772 | )) |
1773 | "Additional expressions to highlight in Python mode.") |
1774 | |
1775 | + |
1776 | ;; have to bind py-file-queue before installing the kill-emacs-hook |
1777 | (defvar py-file-queue nil |
1778 | "Queue of Python temp files awaiting execution. |
1779 | @@ -694,9 +779,43 @@ |
1780 | |
1781 | (defvar py-pychecker-history nil) |
1782 | |
1783 | - |
1784 | |
1785 | |
1786 | ;; Constants |
1787 | +(defconst py-assignement-re "\\<\\w+\\>[ \t]*\\(=\\|+=\\|*=\\|%=\\|&=\\|^=\\|<<=\\|-=\\|/=\\|**=\\||=\\|>>=\\|//=\\)" |
1788 | + "If looking at the beginning of an assignement. ") |
1789 | + |
1790 | +(defconst py-block-re "[ \t]*\\<\\(class\\|def\\|for\\|if\\|try\\|while\\|with\\)\\>" |
1791 | + "Matches the beginning of a class, method or compound statement. ") |
1792 | + |
1793 | +(defconst py-return-re |
1794 | + "[ \t]*\\<\\(return\\)\\>" |
1795 | + "Regular expression matching keyword which typically closes a function. ") |
1796 | + |
1797 | +(defconst py-class-re "[ \t]*\\<\\(class\\)\\>" |
1798 | + "Matches the beginning of a class definition. ") |
1799 | + |
1800 | +(defconst py-def-or-class-re "[ \t]*\\<\\(def\\|class\\)\\>" |
1801 | + "Matches the beginning of a class- or functions definition. ") |
1802 | + |
1803 | +(defconst py-def-re "[ \t]*\\<\\(def\\)\\>" |
1804 | + "Matches the beginning of a functions definition. ") |
1805 | + |
1806 | +(defconst py-if-clause-re "[ \t]*\\<\\elif\\>" |
1807 | + "Matches the beginning of a compound statement's clause. ") |
1808 | + |
1809 | +(defconst py-try-clause-re |
1810 | + (concat "\\(" (mapconcat 'identity |
1811 | + '("except\\(\\s +.*\\)?:" |
1812 | + "finally:") |
1813 | + "\\|") |
1814 | + "\\)") |
1815 | + "Matches the beginning of a try-statement's clause. ") |
1816 | + |
1817 | +(defconst py-if-block-re "[ \t]*\\<if\\>" |
1818 | + "Matches the beginning of a compound statement saying `if'. ") |
1819 | + |
1820 | +(defconst py-try-block-re "[ \t]*\\<try\\>" |
1821 | + "Matches the beginning of a compound statement saying `try'. " ) |
1822 | |
1823 | (defconst py-stringlit-re |
1824 | (concat |
1825 | @@ -729,15 +848,11 @@ |
1826 | (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)" |
1827 | "Regular expression matching a blank or comment line.") |
1828 | |
1829 | -(defconst py-outdent-re |
1830 | - (concat "\\(" (mapconcat 'identity |
1831 | - '("else:" |
1832 | - "except\\(\\s +.*\\)?:" |
1833 | - "finally:" |
1834 | - "elif\\s +.*:") |
1835 | - "\\|") |
1836 | - "\\)") |
1837 | - "Regular expression matching statements to be dedented one level.") |
1838 | +(defconst py-block-or-clause-re "[ \t]*\\<\\(if\\|else\\|elif\\|while\\|for\\|def\\|class\\|try\\|except\\|finally\\|with\\)\\>" |
1839 | + "Matches the beginning of a compound statement or it's clause. ") |
1840 | + |
1841 | +(defconst py-clause-re "[ \t]*\\<\\(else\\|except\\|finally\\|elif\\)\\>" |
1842 | + "Matches the beginning of a compound statement's clause. ") |
1843 | |
1844 | (defconst py-block-closing-keywords-re |
1845 | "\\(return\\|raise\\|break\\|continue\\|pass\\)" |
1846 | @@ -759,7 +874,7 @@ |
1847 | "\\)") |
1848 | "Regular expression matching lines not to dedent after.") |
1849 | |
1850 | -(defvar py-traceback-line-re |
1851 | +(defconst py-traceback-line-re |
1852 | "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)" |
1853 | "Regular expression that describes tracebacks.") |
1854 | |
1855 | @@ -775,7 +890,6 @@ |
1856 | (defconst py-pdbtrack-track-range 10000 |
1857 | "Max number of characters from end of buffer to search for stack entry.") |
1858 | |
1859 | - |
1860 | |
1861 | |
1862 | ;; Major mode boilerplate |
1863 | |
1864 | @@ -784,8 +898,19 @@ |
1865 | "Abbrev table in use in `python-mode' buffers.") |
1866 | (define-abbrev-table 'python-mode-abbrev-table nil) |
1867 | |
1868 | -(defvar python-mode-hook nil |
1869 | - "*Hook called by `python-mode'.") |
1870 | +(defcustom python-mode-hook nil |
1871 | + "Hook run when entering Python mode." |
1872 | + :group 'python |
1873 | + :type 'hook) |
1874 | + |
1875 | +(custom-add-option 'python-mode-hook 'imenu-add-menubar-index) |
1876 | +(custom-add-option 'python-mode-hook |
1877 | + (lambda () |
1878 | + "Turn off Indent Tabs mode." |
1879 | + (setq indent-tabs-mode nil))) |
1880 | +(custom-add-option 'python-mode-hook 'turn-on-eldoc-mode) |
1881 | +(custom-add-option 'python-mode-hook 'abbrev-mode) |
1882 | +;; (custom-add-option 'python-mode-hook 'python-setup-brm) |
1883 | |
1884 | (make-obsolete-variable 'jpython-mode-hook 'jython-mode-hook nil) |
1885 | (defvar jython-mode-hook nil |
1886 | @@ -800,85 +925,118 @@ |
1887 | (and (fboundp 'make-obsolete-variable) |
1888 | (make-obsolete-variable 'py-mode-hook 'python-mode-hook nil)) |
1889 | |
1890 | -(defvar py-mode-map () |
1891 | - "Keymap used in `python-mode' buffers.") |
1892 | -(if py-mode-map |
1893 | - nil |
1894 | - (setq py-mode-map (make-sparse-keymap)) |
1895 | - ;; electric keys |
1896 | - (define-key py-mode-map ":" 'py-electric-colon) |
1897 | - ;; indentation level modifiers |
1898 | - (define-key py-mode-map "\C-c\C-l" 'py-shift-region-left) |
1899 | - (define-key py-mode-map "\C-c\C-r" 'py-shift-region-right) |
1900 | - (define-key py-mode-map "\C-c<" 'py-shift-region-left) |
1901 | - (define-key py-mode-map "\C-c>" 'py-shift-region-right) |
1902 | - ;; subprocess commands |
1903 | - (define-key py-mode-map "\C-c\C-c" 'py-execute-buffer) |
1904 | - (define-key py-mode-map "\C-c\C-m" 'py-execute-import-or-reload) |
1905 | - (define-key py-mode-map "\C-c\C-s" 'py-execute-string) |
1906 | - (define-key py-mode-map "\C-c|" 'py-execute-region) |
1907 | - (define-key py-mode-map "\e\C-x" 'py-execute-def-or-class) |
1908 | - (define-key py-mode-map "\C-c!" 'py-shell) |
1909 | - (define-key py-mode-map "\C-c\C-t" 'py-toggle-shells) |
1910 | - ;; Caution! Enter here at your own risk. We are trying to support |
1911 | - ;; several behaviors and it gets disgusting. :-( This logic ripped |
1912 | - ;; largely from CC Mode. |
1913 | - ;; |
1914 | - ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind |
1915 | - ;; backwards deletion behavior to DEL, which both Delete and |
1916 | - ;; Backspace get translated to. There's no way to separate this |
1917 | - ;; behavior in a clean way, so deal with it! Besides, it's been |
1918 | - ;; this way since the dawn of time. |
1919 | - (if (not (boundp 'delete-key-deletes-forward)) |
1920 | - (define-key py-mode-map "\177" 'py-electric-backspace) |
1921 | - ;; However, XEmacs 20 actually achieved enlightenment. It is |
1922 | - ;; possible to sanely define both backward and forward deletion |
1923 | - ;; behavior under X separately (TTYs are forever beyond hope, but |
1924 | - ;; who cares? XEmacs 20 does the right thing with these too). |
1925 | - (define-key py-mode-map [delete] 'py-electric-delete) |
1926 | - (define-key py-mode-map [backspace] 'py-electric-backspace)) |
1927 | - ;; Separate M-BS from C-M-h. The former should remain |
1928 | - ;; backward-kill-word. |
1929 | - (define-key py-mode-map [(control meta h)] 'py-mark-def-or-class) |
1930 | - (define-key py-mode-map "\C-c\C-k" 'py-mark-block) |
1931 | - ;; Miscellaneous |
1932 | - (define-key py-mode-map "\C-c:" 'py-guess-indent-offset) |
1933 | - (define-key py-mode-map "\C-c\t" 'py-indent-region) |
1934 | - (define-key py-mode-map "\C-c\C-d" 'py-pdbtrack-toggle-stack-tracking) |
1935 | - (define-key py-mode-map "\C-c\C-f" 'py-sort-imports) |
1936 | - (define-key py-mode-map "\C-c\C-n" 'py-next-statement) |
1937 | - (define-key py-mode-map "\C-c\C-p" 'py-previous-statement) |
1938 | - (define-key py-mode-map "\C-c\C-u" 'py-goto-block-up) |
1939 | - (define-key py-mode-map "\C-c#" 'py-comment-region) |
1940 | - (define-key py-mode-map "\C-c?" 'py-describe-mode) |
1941 | - (define-key py-mode-map "\C-c\C-e" 'py-help-at-point) |
1942 | - (define-key py-mode-map "\e\C-a" 'py-beginning-of-def-or-class) |
1943 | - (define-key py-mode-map "\e\C-e" 'py-end-of-def-or-class) |
1944 | - (define-key py-mode-map "\C-c-" 'py-up-exception) |
1945 | - (define-key py-mode-map "\C-c=" 'py-down-exception) |
1946 | - ;; stuff that is `standard' but doesn't interface well with |
1947 | - ;; python-mode, which forces us to rebind to special commands |
1948 | - (define-key py-mode-map "\C-xnd" 'py-narrow-to-defun) |
1949 | - ;; information |
1950 | - (define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report) |
1951 | - (define-key py-mode-map "\C-c\C-v" 'py-version) |
1952 | - (define-key py-mode-map "\C-c\C-w" 'py-pychecker-run) |
1953 | - ;; shadow global bindings for newline-and-indent w/ the py- version. |
1954 | - ;; BAW - this is extremely bad form, but I'm not going to change it |
1955 | - ;; for now. |
1956 | - (mapc #'(lambda (key) |
1957 | - (define-key py-mode-map key 'py-newline-and-indent)) |
1958 | - (where-is-internal 'newline-and-indent)) |
1959 | - ;; Force RET to be py-newline-and-indent even if it didn't get |
1960 | - ;; mapped by the above code. motivation: Emacs' default binding for |
1961 | - ;; RET is `newline' and C-j is `newline-and-indent'. Most Pythoneers |
1962 | - ;; expect RET to do a `py-newline-and-indent' and any Emacsers who |
1963 | - ;; dislike this are probably knowledgeable enough to do a rebind. |
1964 | - ;; However, we do *not* change C-j since many Emacsers have already |
1965 | - ;; swapped RET and C-j and they don't want C-j bound to `newline' to |
1966 | - ;; change. |
1967 | - (define-key py-mode-map "\C-m" 'py-newline-and-indent) |
1968 | - ) |
1969 | +(defvar py-mode-map |
1970 | + (let ((map (make-sparse-keymap))) |
1971 | + ;; electric keys |
1972 | + (define-key map ":" 'py-electric-colon) |
1973 | + ;; indentation level modifiers |
1974 | + (define-key map "\C-c\C-l" 'py-shift-region-left) |
1975 | + (define-key map "\C-c\C-r" 'py-shift-region-right) |
1976 | + (define-key map "\C-c<" 'py-shift-region-left) |
1977 | + (define-key map "\C-c>" 'py-shift-region-right) |
1978 | + ;; subprocess commands |
1979 | + (define-key map "\C-c\C-c" 'py-execute-buffer) |
1980 | + (define-key map "\C-c\C-m" 'py-execute-import-or-reload) |
1981 | + (define-key map "\C-c\C-s" 'py-execute-string) |
1982 | + (define-key map "\C-c|" 'py-execute-region) |
1983 | + (define-key map "\e\C-x" 'py-execute-def-or-class) |
1984 | + (define-key map "\C-c!" 'py-shell) |
1985 | + (define-key map "\C-c\C-t" 'py-toggle-shells) |
1986 | + (define-key map [?\C-c ?\d] 'py-hungry-delete-backwards) |
1987 | + (define-key map [?\C-c ?\C-\d] 'py-hungry-delete-backwards) |
1988 | + (define-key map [?\C-c deletechar] 'py-hungry-delete-forward) |
1989 | + (if (not (boundp 'delete-key-deletes-forward)) |
1990 | + (define-key map "\177" 'py-electric-backspace) |
1991 | + (define-key map [delete] 'py-electric-delete) |
1992 | + (define-key map [backspace] 'py-electric-backspace)) |
1993 | + (define-key map [(control meta h)] 'py-mark-def-or-class) |
1994 | + (define-key map "\C-c\C-k" 'py-mark-block-or-clause) |
1995 | + ;; Miscellaneous |
1996 | + (define-key map "\C-c:" 'py-guess-indent-offset) |
1997 | + (define-key map "\C-c\t" 'py-indent-region) |
1998 | + (define-key map "\C-c\C-d" 'py-pdbtrack-toggle-stack-tracking) |
1999 | + (define-key map "\C-c\C-f" 'py-sort-imports) |
2000 | + (define-key map "\C-c\C-n" 'py-end-of-statement) |
2001 | + (define-key map "\C-c\C-a" 'py-mark-statement) |
2002 | + (define-key map "\C-c\C-p" 'py-beginning-of-statement) |
2003 | + (define-key map "\C-c\C-u" 'py-beginning-of-block) |
2004 | + (define-key map "\C-c\C-q" 'py-end-of-block) |
2005 | + (define-key map "\C-c#" 'py-comment-region) |
2006 | + (define-key map "\C-c?" 'py-describe-mode) |
2007 | + (define-key map "\C-c\C-e" 'py-help-at-point) |
2008 | + (define-key map "\e\C-a" 'py-beginning-of-def-or-class) |
2009 | + (define-key map "\e\C-e" 'py-end-of-def-or-class) |
2010 | + (define-key map "\C-c-" 'py-up-exception) |
2011 | + (define-key map "\C-c=" 'py-down-exception) |
2012 | + ;; stuff that is `standard' but doesn't interface well with |
2013 | + ;; python-mode, which forces us to rebind to special commands |
2014 | + (define-key map "\C-xnd" 'py-narrow-to-defun) |
2015 | + ;; information |
2016 | + (define-key map "\C-c\C-b" 'py-submit-bug-report) |
2017 | + (define-key map "\C-c\C-b" 'py-submit-bug-report) |
2018 | + (define-key map "\C-c\C-v" 'py-version) |
2019 | + (define-key map "\C-c\C-w" 'py-pychecker-run) |
2020 | + ;; shadow global bindings for newline-and-indent w/ the py- version. |
2021 | + (mapc #'(lambda (key) |
2022 | + (define-key map key 'py-newline-and-indent)) |
2023 | + (where-is-internal 'newline-and-indent)) |
2024 | + ;; Most Pythoneers expect RET to do a `py-newline-and-indent' |
2025 | + (define-key map "\C-m" 'py-newline-and-indent) |
2026 | + (define-key map [(control return)] 'py-newline-and-dedent) |
2027 | + (easy-menu-define py-menu map "Python Mode menu" |
2028 | + `("Python" |
2029 | + :help "Python-specific Features" |
2030 | + ["Shift region left" py-shift-left :active mark-active |
2031 | + :help "Shift by a single indentation step"] |
2032 | + ["Shift region right" py-shift-right :active mark-active |
2033 | + :help "Shift by a single indentation step"] |
2034 | + "-" |
2035 | + ["Mark block" py-mark-block |
2036 | + :help "Mark innermost block around point"] |
2037 | + ["Mark def/class" mark-defun |
2038 | + :help "Mark innermost definition around point"] |
2039 | + "-" |
2040 | + ["Start of block" py-beginning-of-block |
2041 | + :help "Go to start of innermost definition around point"] |
2042 | + ["End of block" py-end-of-block |
2043 | + :help "Go to end of innermost definition around point"] |
2044 | + ["Start of def/class" beginning-of-defun |
2045 | + :help "Go to start of innermost definition around point"] |
2046 | + ["End of def/class" end-of-defun |
2047 | + :help "Go to end of innermost definition around point"] |
2048 | + "-" |
2049 | + ("Templates..." |
2050 | + :help "Expand templates for compound statements" |
2051 | + :filter (lambda (&rest junk) |
2052 | + (abbrev-table-menu python-mode-abbrev-table))) |
2053 | + "-" |
2054 | + ["Start interpreter" py-shell |
2055 | + :help "Run `inferior' Python in separate buffer"] |
2056 | + ["Import/reload file" py-load-file |
2057 | + :help "Load into inferior Python session"] |
2058 | + ["Eval buffer" py-execute-buffer |
2059 | + :help "Evaluate buffer en bloc in inferior Python session"] |
2060 | + ["Eval region" py-execute-region :active mark-active |
2061 | + :help "Evaluate region en bloc in inferior Python session"] |
2062 | + ["Eval def/class" py-execute-defun |
2063 | + :help "Evaluate current definition in inferior Python session"] |
2064 | + ["Switch to interpreter" py-switch-to-python |
2065 | + :help "Switch to inferior Python buffer"] |
2066 | + ["Set default process" py-set-proc |
2067 | + :help "Make buffer's inferior process the default" |
2068 | + :active (buffer-live-p py-buffer)] |
2069 | + ["Check file" py-check :help "Run pychecker"] |
2070 | + ["Debugger" pdb :help "Run pdb under GUD"] |
2071 | + "-" |
2072 | + ["Help on symbol" py-describe-symbol |
2073 | + :help "Use pydoc on symbol at point"] |
2074 | + ["Complete symbol" completion-at-point |
2075 | + :help "Complete (qualified) symbol before point"] |
2076 | + ["Find function" py-find-function |
2077 | + :help "Try to find source definition of function at point"] |
2078 | + ["Update imports" py-find-imports |
2079 | + :help "Update list of top-level imports for completion"])) |
2080 | + map)) |
2081 | |
2082 | (defvar py-mode-output-map nil |
2083 | "Keymap used in *Python Output* buffers.") |
2084 | @@ -957,7 +1115,6 @@ |
2085 | (modify-syntax-entry ?_ "_" py-dotted-expression-syntax-table) |
2086 | (modify-syntax-entry ?. "_" py-dotted-expression-syntax-table)) |
2087 | |
2088 | - |
2089 | |
2090 | |
2091 | ;; Utilities |
2092 | (defsubst py-keep-region-active () |
2093 | @@ -999,272 +1156,94 @@ |
2094 | (point) |
2095 | (goto-char here)))) |
2096 | |
2097 | -(defsubst py-highlight-line (from to file line) |
2098 | - (cond |
2099 | - ((fboundp 'make-extent) |
2100 | - ;; XEmacs |
2101 | - (let ((e (make-extent from to))) |
2102 | - (set-extent-property e 'mouse-face 'highlight) |
2103 | - (set-extent-property e 'py-exc-info (cons file line)) |
2104 | - (set-extent-property e 'keymap py-mode-output-map))) |
2105 | - (t |
2106 | - ;; Emacs -- Please port this! |
2107 | - ) |
2108 | - )) |
2109 | - |
2110 | -(defun py-in-literal (&optional lim) |
2111 | - "Return non-nil if point is in a Python literal (a comment or string). |
2112 | -Optional argument LIM indicates the beginning of the containing form, |
2113 | -i.e. the limit on how far back to scan." |
2114 | - ;; This is the version used for non-XEmacs, which has a nicer |
2115 | - ;; interface. |
2116 | - ;; |
2117 | - ;; WARNING: Watch out for infinite recursion. |
2118 | - (let* ((lim (or lim (py-point 'bod))) |
2119 | - (state (parse-partial-sexp lim (point)))) |
2120 | +(when (featurep 'xemacs) |
2121 | + (defsubst py-highlight-line (from to file line) |
2122 | (cond |
2123 | - ((nth 3 state) 'string) |
2124 | - ((nth 4 state) 'comment) |
2125 | - (t nil)))) |
2126 | - |
2127 | -;; XEmacs has a built-in function that should make this much quicker. |
2128 | -;; In this case, lim is ignored |
2129 | -(defun py-fast-in-literal (&optional lim) |
2130 | - "Fast version of `py-in-literal', used only by XEmacs. |
2131 | -Optional LIM is ignored." |
2132 | - ;; don't have to worry about context == 'block-comment |
2133 | - (buffer-syntactic-context)) |
2134 | - |
2135 | -(if (fboundp 'buffer-syntactic-context) |
2136 | - (defalias 'py-in-literal 'py-fast-in-literal)) |
2137 | - |
2138 | - |
2139 | - |
2140 | |
2141 | -;; Menu definitions, only relevent if you have the easymenu.el package |
2142 | -;; (standard in the latest Emacs 19 and XEmacs 19 distributions). |
2143 | -(defvar py-menu nil |
2144 | - "Menu for Python Mode. |
2145 | -This menu will get created automatically if you have the `easymenu' |
2146 | -package. Note that the latest X/Emacs releases contain this package.") |
2147 | - |
2148 | -(and (ignore-errors (require 'easymenu) t) |
2149 | - (easy-menu-define |
2150 | - py-menu py-mode-map "Python Mode menu" |
2151 | - '("Python" |
2152 | - ["Comment Out Region" py-comment-region (mark)] |
2153 | - ["Uncomment Region" (py-comment-region (point) (mark) '(4)) (mark)] |
2154 | - "-" |
2155 | - ["Mark current block" py-mark-block t] |
2156 | - ["Mark current def" py-mark-def-or-class t] |
2157 | - ["Mark current class" (py-mark-def-or-class t) t] |
2158 | - "-" |
2159 | - ["Shift region left" py-shift-region-left (mark)] |
2160 | - ["Shift region right" py-shift-region-right (mark)] |
2161 | - "-" |
2162 | - ["Import/reload file" py-execute-import-or-reload t] |
2163 | - ["Execute buffer" py-execute-buffer t] |
2164 | - ["Execute region" py-execute-region (mark)] |
2165 | - ["Execute def or class" py-execute-def-or-class (mark)] |
2166 | - ["Execute string" py-execute-string t] |
2167 | - ["Start interpreter..." py-shell t] |
2168 | - "-" |
2169 | - ["Go to start of block" py-goto-block-up t] |
2170 | - ["Go to start of class" (py-beginning-of-def-or-class t) t] |
2171 | - ["Move to end of class" (py-end-of-def-or-class t) t] |
2172 | - ["Move to start of def" py-beginning-of-def-or-class t] |
2173 | - ["Move to end of def" py-end-of-def-or-class t] |
2174 | - "-" |
2175 | - ["Describe mode" py-describe-mode t] |
2176 | - ))) |
2177 | - |
2178 | - |
2179 | - |
2180 | |
2181 | -;; Imenu definitions |
2182 | -(defvar py-imenu-class-regexp |
2183 | - (concat ; <<classes>> |
2184 | - "\\(" ; |
2185 | - "^[ \t]*" ; newline and maybe whitespace |
2186 | - "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; class name |
2187 | - ; possibly multiple superclasses |
2188 | - "\\([ \t]*\\((\\([a-zA-Z0-9_,. \t\n]\\)*)\\)?\\)" |
2189 | - "[ \t]*:" ; and the final : |
2190 | - "\\)" ; >>classes<< |
2191 | - ) |
2192 | - "Regexp for Python classes for use with the Imenu package." |
2193 | - ) |
2194 | - |
2195 | -(defvar py-imenu-method-regexp |
2196 | - (concat ; <<methods and functions>> |
2197 | - "\\(" ; |
2198 | - "^[ \t]*" ; new line and maybe whitespace |
2199 | - "\\(def[ \t]+" ; function definitions start with def |
2200 | - "\\([a-zA-Z0-9_]+\\)" ; name is here |
2201 | - ; function arguments... |
2202 | -;; "[ \t]*(\\([-+/a-zA-Z0-9_=,\* \t\n.()\"'#]*\\))" |
2203 | - "[ \t]*(\\([^:#]*\\))" |
2204 | - "\\)" ; end of def |
2205 | - "[ \t]*:" ; and then the : |
2206 | - "\\)" ; >>methods and functions<< |
2207 | - ) |
2208 | - "Regexp for Python methods/functions for use with the Imenu package." |
2209 | - ) |
2210 | - |
2211 | -(defvar py-imenu-method-no-arg-parens '(2 8) |
2212 | - "Indices into groups of the Python regexp for use with Imenu. |
2213 | - |
2214 | -Using these values will result in smaller Imenu lists, as arguments to |
2215 | -functions are not listed. |
2216 | - |
2217 | -See the variable `py-imenu-show-method-args-p' for more |
2218 | -information.") |
2219 | - |
2220 | -(defvar py-imenu-method-arg-parens '(2 7) |
2221 | - "Indices into groups of the Python regexp for use with imenu. |
2222 | -Using these values will result in large Imenu lists, as arguments to |
2223 | -functions are listed. |
2224 | - |
2225 | -See the variable `py-imenu-show-method-args-p' for more |
2226 | -information.") |
2227 | - |
2228 | -;; Note that in this format, this variable can still be used with the |
2229 | -;; imenu--generic-function. Otherwise, there is no real reason to have |
2230 | -;; it. |
2231 | -(defvar py-imenu-generic-expression |
2232 | - (cons |
2233 | - (concat |
2234 | - py-imenu-class-regexp |
2235 | - "\\|" ; or... |
2236 | - py-imenu-method-regexp |
2237 | + ((fboundp 'make-extent) |
2238 | + ;; XEmacs |
2239 | + (let ((e (make-extent from to))) |
2240 | + (set-extent-property e 'mouse-face 'highlight) |
2241 | + (set-extent-property e 'py-exc-info (cons file line)) |
2242 | + (set-extent-property e 'keymap py-mode-output-map))) |
2243 | + (t |
2244 | + ;; Emacs -- Please port this! |
2245 | + ) |
2246 | + ))) |
2247 | + |
2248 | + |
2249 | |
2250 | +;;;; Imenu. |
2251 | + |
2252 | +;; For possibily speeding this up, here's the top of the ELP profile |
2253 | +;; for rescanning pydoc.py (2.2k lines, 90kb): |
2254 | +;; Function Name Call Count Elapsed Time Average Time |
2255 | +;; ==================================== ========== ============= ============ |
2256 | +;; python-imenu-create-index 156 2.430906 0.0155827307 |
2257 | +;; python-end-of-defun 155 1.2718260000 0.0082053290 |
2258 | +;; python-end-of-block 155 1.1898689999 0.0076765741 |
2259 | +;; python-next-statement 2970 1.024717 0.0003450225 |
2260 | +;; python-end-of-statement 2970 0.4332190000 0.0001458649 |
2261 | +;; python-beginning-of-defun 265 0.0918479999 0.0003465962 |
2262 | +;; python-skip-comments/blanks 3125 0.0753319999 2.410...e-05 |
2263 | + |
2264 | +(defvar python-recursing) |
2265 | +;; (defun python-imenu-create-index () |
2266 | +(defun py-imenu-create-index () |
2267 | + "`imenu-create-index-function' for Python. |
2268 | + |
2269 | +Makes nested Imenu menus from nested `class' and `def' statements. |
2270 | +The nested menus are headed by an item referencing the outer |
2271 | +definition; it has a space prepended to the name so that it sorts |
2272 | +first with `imenu--sort-by-name' (though, unfortunately, sub-menus |
2273 | +precede it)." |
2274 | + (unless (boundp 'python-recursing) ; dynamically bound below |
2275 | + ;; Normal call from Imenu. |
2276 | + (goto-char (point-min)) |
2277 | + ;; Without this, we can get an infloop if the buffer isn't all |
2278 | + ;; fontified. I guess this is really a bug in syntax.el. OTOH, |
2279 | + ;; _with_ this, imenu doesn't immediately work; I can't figure out |
2280 | + ;; what's going on, but it must be something to do with timers in |
2281 | + ;; font-lock. |
2282 | + ;; This can't be right, especially not when jit-lock is not used. --Stef |
2283 | + ;; (unless (get-text-property (1- (point-max)) 'fontified) |
2284 | + ;; (font-lock-fontify-region (point-min) (point-max))) |
2285 | ) |
2286 | - py-imenu-method-no-arg-parens) |
2287 | - "Generic Python expression which may be used directly with Imenu. |
2288 | -Used by setting the variable `imenu-generic-expression' to this value. |
2289 | -Also, see the function \\[py-imenu-create-index] for a better |
2290 | -alternative for finding the index.") |
2291 | - |
2292 | -;; These next two variables are used when searching for the Python |
2293 | -;; class/definitions. Just saving some time in accessing the |
2294 | -;; generic-python-expression, really. |
2295 | -(defvar py-imenu-generic-regexp nil) |
2296 | -(defvar py-imenu-generic-parens nil) |
2297 | - |
2298 | - |
2299 | -(defun py-imenu-create-index-function () |
2300 | - "Python interface function for the Imenu package. |
2301 | -Finds all Python classes and functions/methods. Calls function |
2302 | -\\[py-imenu-create-index-engine]. See that function for the details |
2303 | -of how this works." |
2304 | - (setq py-imenu-generic-regexp (car py-imenu-generic-expression) |
2305 | - py-imenu-generic-parens (if py-imenu-show-method-args-p |
2306 | - py-imenu-method-arg-parens |
2307 | - py-imenu-method-no-arg-parens)) |
2308 | - (goto-char (point-min)) |
2309 | - ;; Warning: When the buffer has no classes or functions, this will |
2310 | - ;; return nil, which seems proper according to the Imenu API, but |
2311 | - ;; causes an error in the XEmacs port of Imenu. Sigh. |
2312 | - (py-imenu-create-index-engine nil)) |
2313 | - |
2314 | -(defun py-imenu-create-index-engine (&optional start-indent) |
2315 | - "Function for finding Imenu definitions in Python. |
2316 | - |
2317 | -Finds all definitions (classes, methods, or functions) in a Python |
2318 | -file for the Imenu package. |
2319 | - |
2320 | -Returns a possibly nested alist of the form |
2321 | - |
2322 | - (INDEX-NAME . INDEX-POSITION) |
2323 | - |
2324 | -The second element of the alist may be an alist, producing a nested |
2325 | -list as in |
2326 | - |
2327 | - (INDEX-NAME . INDEX-ALIST) |
2328 | - |
2329 | -This function should not be called directly, as it calls itself |
2330 | -recursively and requires some setup. Rather this is the engine for |
2331 | -the function \\[py-imenu-create-index-function]. |
2332 | - |
2333 | -It works recursively by looking for all definitions at the current |
2334 | -indention level. When it finds one, it adds it to the alist. If it |
2335 | -finds a definition at a greater indentation level, it removes the |
2336 | -previous definition from the alist. In its place it adds all |
2337 | -definitions found at the next indentation level. When it finds a |
2338 | -definition that is less indented then the current level, it returns |
2339 | -the alist it has created thus far. |
2340 | - |
2341 | -The optional argument START-INDENT indicates the starting indentation |
2342 | -at which to continue looking for Python classes, methods, or |
2343 | -functions. If this is not supplied, the function uses the indentation |
2344 | -of the first definition found." |
2345 | - (let (index-alist |
2346 | - sub-method-alist |
2347 | - looking-p |
2348 | - def-name prev-name |
2349 | - cur-indent def-pos |
2350 | - (class-paren (first py-imenu-generic-parens)) |
2351 | - (def-paren (second py-imenu-generic-parens))) |
2352 | - (setq looking-p |
2353 | - (re-search-forward py-imenu-generic-regexp (point-max) t)) |
2354 | - (while looking-p |
2355 | - (save-excursion |
2356 | - ;; used to set def-name to this value but generic-extract-name |
2357 | - ;; is new to imenu-1.14. this way it still works with |
2358 | - ;; imenu-1.11 |
2359 | - ;;(imenu--generic-extract-name py-imenu-generic-parens)) |
2360 | - (let ((cur-paren (if (match-beginning class-paren) |
2361 | - class-paren def-paren))) |
2362 | - (setq def-name |
2363 | - (buffer-substring-no-properties (match-beginning cur-paren) |
2364 | - (match-end cur-paren)))) |
2365 | - (save-match-data |
2366 | - (py-beginning-of-def-or-class 'either)) |
2367 | - (beginning-of-line) |
2368 | - (setq cur-indent (current-indentation))) |
2369 | - ;; HACK: want to go to the next correct definition location. We |
2370 | - ;; explicitly list them here but it would be better to have them |
2371 | - ;; in a list. |
2372 | - (setq def-pos |
2373 | - (or (match-beginning class-paren) |
2374 | - (match-beginning def-paren))) |
2375 | - ;; if we don't have a starting indent level, take this one |
2376 | - (or start-indent |
2377 | - (setq start-indent cur-indent)) |
2378 | - ;; if we don't have class name yet, take this one |
2379 | - (or prev-name |
2380 | - (setq prev-name def-name)) |
2381 | - ;; what level is the next definition on? must be same, deeper |
2382 | - ;; or shallower indentation |
2383 | - (cond |
2384 | - ;; Skip code in comments and strings |
2385 | - ((py-in-literal)) |
2386 | - ;; at the same indent level, add it to the list... |
2387 | - ((= start-indent cur-indent) |
2388 | - (push (cons def-name def-pos) index-alist)) |
2389 | - ;; deeper indented expression, recurse |
2390 | - ((< start-indent cur-indent) |
2391 | - ;; the point is currently on the expression we're supposed to |
2392 | - ;; start on, so go back to the last expression. The recursive |
2393 | - ;; call will find this place again and add it to the correct |
2394 | - ;; list |
2395 | - (re-search-backward py-imenu-generic-regexp (point-min) 'move) |
2396 | - (setq sub-method-alist (py-imenu-create-index-engine cur-indent)) |
2397 | - (if sub-method-alist |
2398 | - ;; we put the last element on the index-alist on the start |
2399 | - ;; of the submethod alist so the user can still get to it. |
2400 | - (let ((save-elmt (pop index-alist))) |
2401 | - (push (cons prev-name |
2402 | - (cons save-elmt sub-method-alist)) |
2403 | - index-alist)))) |
2404 | - ;; found less indented expression, we're done. |
2405 | - (t |
2406 | - (setq looking-p nil) |
2407 | - (re-search-backward py-imenu-generic-regexp (point-min) t))) |
2408 | - ;; end-cond |
2409 | - (setq prev-name def-name) |
2410 | - (and looking-p |
2411 | - (setq looking-p |
2412 | - (re-search-forward py-imenu-generic-regexp |
2413 | - (point-max) 'move)))) |
2414 | - (nreverse index-alist))) |
2415 | + (let (index-alist) ; accumulated value to return |
2416 | + (while (re-search-forward |
2417 | + (rx line-start (0+ space) ; leading space |
2418 | + (or (group "def") (group "class")) ; type |
2419 | + (1+ space) (group (1+ (or word ?_)))) ; name |
2420 | + nil t) |
2421 | + (unless (py-in-string-or-comment-p) |
2422 | + (let ((pos (match-beginning 0)) |
2423 | + (name (match-string-no-properties 3))) |
2424 | + (if (match-beginning 2) ; def or class? |
2425 | + (setq name (concat "class " name))) |
2426 | + (save-restriction |
2427 | + (narrow-to-defun) |
2428 | + (let* ((python-recursing t) |
2429 | +;; (sublist (python-imenu-create-index))) |
2430 | + (sublist (py-imenu-create-index))) |
2431 | + (if sublist |
2432 | + (progn (push (cons (concat " " name) pos) sublist) |
2433 | + (push (cons name sublist) index-alist)) |
2434 | + (push (cons name pos) index-alist))))))) |
2435 | + (unless (boundp 'python-recursing) |
2436 | + ;; Look for module variables. |
2437 | + (let (vars) |
2438 | + (goto-char (point-min)) |
2439 | + (while (re-search-forward |
2440 | + (rx line-start (group (1+ (or word ?_))) (0+ space) "=") |
2441 | + nil t) |
2442 | + (unless (py-in-string-or-comment-p) |
2443 | + (push (cons (match-string 1) (match-beginning 1)) |
2444 | + vars))) |
2445 | + (setq index-alist (nreverse index-alist)) |
2446 | + (if vars |
2447 | + (push (cons "Module variables" |
2448 | + (nreverse vars)) |
2449 | + index-alist)))) |
2450 | + index-alist)) |
2451 | + |
2452 | |
2453 | |
2454 | |
2455 | |
2456 | |
2457 | @@ -1290,7 +1269,6 @@ |
2458 | py-shell-alist)) |
2459 | (and elt (caddr elt)))) |
2460 | |
2461 | - |
2462 | |
2463 | |
2464 | (defun py-choose-shell-by-import () |
2465 | "Choose CPython or Jython mode based imports. |
2466 | @@ -1326,7 +1304,7 @@ |
2467 | |
2468 | |
2469 | (defvar py-which-shell nil) |
2470 | ;;;###autoload |
2471 | -(defun python-mode () |
2472 | +(define-derived-mode python-mode fundamental-mode "Python" |
2473 | "Major mode for editing Python files. |
2474 | To submit a problem report, enter `\\[py-submit-bug-report]' from a |
2475 | `python-mode' buffer. Do `\\[py-describe-mode]' for detailed |
2476 | @@ -1345,105 +1323,57 @@ |
2477 | py-python-command\t\tshell command to invoke Python interpreter |
2478 | py-temp-directory\t\tdirectory used for temp files (if needed) |
2479 | py-beep-if-tab-change\t\tring the bell if `tab-width' is changed" |
2480 | - (interactive) |
2481 | - ;; set up local variables |
2482 | - (kill-all-local-variables) |
2483 | - (make-local-variable 'paragraph-separate) |
2484 | - (make-local-variable 'paragraph-start) |
2485 | - (make-local-variable 'require-final-newline) |
2486 | - (make-local-variable 'comment-start) |
2487 | - (make-local-variable 'comment-end) |
2488 | - (make-local-variable 'comment-start-skip) |
2489 | - (make-local-variable 'comment-column) |
2490 | - (make-local-variable 'comment-indent-function) |
2491 | - (make-local-variable 'indent-region-function) |
2492 | - (make-local-variable 'indent-line-function) |
2493 | - (make-local-variable 'add-log-current-defun-function) |
2494 | - (make-local-variable 'fill-paragraph-function) |
2495 | - ;; |
2496 | + (set (make-local-variable 'font-lock-defaults) |
2497 | + '(py-font-lock-keywords nil nil nil nil |
2498 | + (font-lock-syntactic-keywords |
2499 | + . py-font-lock-syntactic-keywords))) |
2500 | + (set (make-local-variable 'paragraph-separate) "^[ \t]*$") |
2501 | + (set (make-local-variable 'paragraph-start) "^[ \t]*$" ) |
2502 | + (set (make-local-variable 'require-final-newline) t) |
2503 | + (set (make-local-variable 'comment-start) "#") |
2504 | + (set (make-local-variable 'comment-end) "") |
2505 | + (set (make-local-variable 'comment-start-skip) "# *") |
2506 | + (set (make-local-variable 'comment-column) 40) |
2507 | + (set (make-local-variable 'comment-indent-function) 'py-comment-indent-function) |
2508 | + (set (make-local-variable 'indent-region-function) 'py-indent-region) |
2509 | + (set (make-local-variable 'indent-line-function) 'py-indent-line) |
2510 | + (set (make-local-variable 'add-log-current-defun-function) 'py-current-defun) |
2511 | + (set (make-local-variable 'fill-paragraph-function) 'py-fill-paragraph) |
2512 | (set-syntax-table py-mode-syntax-table) |
2513 | - ;; 2009-09-10 a.roehler@web.de changed section start |
2514 | - ;; from python.el, version "22.1" |
2515 | - (set (make-local-variable 'font-lock-defaults) |
2516 | - '(python-font-lock-keywords nil nil nil nil |
2517 | - (font-lock-syntactic-keywords |
2518 | - . python-font-lock-syntactic-keywords))) |
2519 | - ;; 2009-09-10 a.roehler@web.de changed section end |
2520 | - (setq major-mode 'python-mode |
2521 | - mode-name "Python" |
2522 | - local-abbrev-table python-mode-abbrev-table |
2523 | - paragraph-separate "^[ \t]*$" |
2524 | - paragraph-start "^[ \t]*$" |
2525 | - require-final-newline t |
2526 | - comment-start "# " |
2527 | - comment-end "" |
2528 | - comment-start-skip "# *" |
2529 | - comment-column 40 |
2530 | - comment-indent-function 'py-comment-indent-function |
2531 | - indent-region-function 'py-indent-region |
2532 | - indent-line-function 'py-indent-line |
2533 | - ;; tell add-log.el how to find the current function/method/variable |
2534 | - add-log-current-defun-function 'py-current-defun |
2535 | - |
2536 | - fill-paragraph-function 'py-fill-paragraph |
2537 | - ) |
2538 | (use-local-map py-mode-map) |
2539 | - ;; add the menu |
2540 | - (if py-menu |
2541 | - (easy-menu-add py-menu)) |
2542 | ;; Emacs 19 requires this |
2543 | (if (boundp 'comment-multi-line) |
2544 | (setq comment-multi-line nil)) |
2545 | - ;; Install Imenu if available |
2546 | - (when (ignore-errors (require 'imenu)) |
2547 | - (setq imenu-create-index-function #'py-imenu-create-index-function) |
2548 | - (setq imenu-generic-expression py-imenu-generic-expression) |
2549 | - (if (fboundp 'imenu-add-to-menubar) |
2550 | - (imenu-add-to-menubar (format "%s-%s" "IM" mode-name))) |
2551 | - ) |
2552 | - |
2553 | + (set (make-local-variable 'skeleton-further-elements) |
2554 | + '((< '(backward-delete-char-untabify (min py-indent-offset |
2555 | + (current-column)))) |
2556 | + (^ '(- (1+ (current-indentation)))))) |
2557 | ;; Add support for HideShow |
2558 | - (add-to-list 'hs-special-modes-alist |
2559 | - (list |
2560 | - 'python-mode |
2561 | - ;; start regex |
2562 | - (concat (if py-hide-show-hide-docstrings |
2563 | - "^\\s-*\"\"\"\\|" "") |
2564 | - (mapconcat 'identity |
2565 | - (mapcar #'(lambda (x) (concat "^\\s-*" x "\\>")) |
2566 | - py-hide-show-keywords) |
2567 | - "\\|")) |
2568 | - ;; end regex |
2569 | - nil |
2570 | - ;; comment-start regex |
2571 | - "#" |
2572 | - ;; forward-sexp function |
2573 | - (lambda (arg) |
2574 | - (py-goto-beyond-block) |
2575 | - (skip-chars-backward " \t\n")) |
2576 | - nil)) |
2577 | - |
2578 | - ;; Run the mode hook. Note that py-mode-hook is deprecated. |
2579 | - (if python-mode-hook |
2580 | - (run-hooks 'python-mode-hook) |
2581 | - (run-hooks 'py-mode-hook)) |
2582 | - ;; Now do the automagical guessing |
2583 | + (add-to-list 'hs-special-modes-alist (list |
2584 | + 'python-mode (concat (if py-hide-show-hide-docstrings "^\\s-*\"\"\"\\|" "") (mapconcat 'identity (mapcar #'(lambda (x) (concat "^\\s-*" x "\\>")) py-hide-show-keywords) "\\|")) nil "#" |
2585 | + (lambda (arg) |
2586 | + (py-goto-beyond-block) |
2587 | + (skip-chars-backward " \v\f\t\n")) |
2588 | + nil)) |
2589 | + ;; Now do the automagical guessing |
2590 | (if py-smart-indentation |
2591 | - (let ((offset py-indent-offset)) |
2592 | - ;; It's okay if this fails to guess a good value |
2593 | - (if (and (ignore-errors (py-guess-indent-offset)) |
2594 | - (<= py-indent-offset 8) |
2595 | - (>= py-indent-offset 2)) |
2596 | - (setq offset py-indent-offset)) |
2597 | - (setq py-indent-offset offset) |
2598 | - ;; Only turn indent-tabs-mode off if tab-width != |
2599 | - ;; py-indent-offset. Never turn it on, because the user must |
2600 | - ;; have explicitly turned it off. |
2601 | - (if (/= tab-width py-indent-offset) |
2602 | - (setq indent-tabs-mode nil)))) |
2603 | + (let ((offset py-indent-offset)) |
2604 | + ;; It's okay if this fails to guess a good value |
2605 | + (if (and (ignore-errors (py-guess-indent-offset)) |
2606 | + (<= py-indent-offset 8) |
2607 | + (>= py-indent-offset 2)) |
2608 | + (setq offset py-indent-offset)) |
2609 | + (setq py-indent-offset offset) |
2610 | + ;; Only turn indent-tabs-mode off if tab-width != |
2611 | + ;; py-indent-offset. Never turn it on, because the user must |
2612 | + ;; have explicitly turned it off. |
2613 | + (if (/= tab-width py-indent-offset) |
2614 | + (setq indent-tabs-mode nil)))) |
2615 | ;; Set the default shell if not already set |
2616 | - (when (null py-which-shell) |
2617 | - (py-toggle-shells (py-choose-shell)))) |
2618 | + (unless py-which-shell |
2619 | + (py-toggle-shells (py-choose-shell))) |
2620 | + (when (interactive-p) (message "python-mode loaded from: %s" "python-mode.el")) |
2621 | + ) |
2622 | |
2623 | (make-obsolete 'jpython-mode 'jython-mode nil) |
2624 | (defun jython-mode () |
2625 | @@ -1458,7 +1388,6 @@ |
2626 | (when jython-mode-hook |
2627 | (run-hooks 'jython-mode-hook))) |
2628 | |
2629 | - |
2630 | ;; It's handy to add recognition of Python files to the |
2631 | ;; interpreter-mode-alist and to auto-mode-alist. With the former, we |
2632 | ;; can specify different `derived-modes' based on the #! line, but |
2633 | @@ -1478,21 +1407,19 @@ |
2634 | (rassq 'jython-mode auto-mode-alist))) |
2635 | (push '("\\.py$" . python-mode) auto-mode-alist)) |
2636 | |
2637 | - |
2638 | |
2639 | |
2640 | ;; electric characters |
2641 | (defun py-outdent-p () |
2642 | "Returns non-nil if the current line should dedent one level." |
2643 | (save-excursion |
2644 | (and (progn (back-to-indentation) |
2645 | - (looking-at py-outdent-re)) |
2646 | + (looking-at py-clause-re)) |
2647 | ;; short circuit infloop on illegal construct |
2648 | (not (bobp)) |
2649 | (progn (forward-line -1) |
2650 | (py-goto-initial-line) |
2651 | (back-to-indentation) |
2652 | - (while (or (looking-at py-blank-or-comment-re) |
2653 | - (bobp)) |
2654 | + (when (looking-at py-blank-or-comment-re) |
2655 | (backward-to-indentation 1)) |
2656 | (not (looking-at py-no-outdent-re))) |
2657 | ))) |
2658 | @@ -1637,7 +1564,8 @@ |
2659 | (setq target_buffer (cadr target)) |
2660 | (setq target_fname (buffer-file-name target_buffer)) |
2661 | (switch-to-buffer-other-window target_buffer) |
2662 | - (goto-line target_lineno) |
2663 | + (goto-char (point-min)) |
2664 | + (forward-line target_lineno) |
2665 | (message "pdbtrack: line %s, file %s" target_lineno target_fname) |
2666 | (py-pdbtrack-overlay-arrow t) |
2667 | (pop-to-buffer origbuf t) |
2668 | @@ -1726,20 +1654,17 @@ |
2669 | (setq file (match-string 1) |
2670 | line (string-to-number (match-string 2)) |
2671 | bol (py-point 'bol)) |
2672 | - (py-highlight-line bol (py-point 'eol) file line))) |
2673 | + ;; XEmacs function |
2674 | + ;; (py-highlight-line bol (py-point 'eol) file line) |
2675 | + )) |
2676 | (when (and py-jump-on-exception line) |
2677 | (beep) |
2678 | (py-jump-to-exception file line) |
2679 | (setq err-p t)) |
2680 | err-p)) |
2681 | |
2682 | - |
2683 | |
2684 | |
2685 | ;;; Subprocess commands |
2686 | - |
2687 | -;; only used when (memq 'broken-temp-names py-emacs-features) |
2688 | -(defvar py-serial-number 0) |
2689 | -(defvar py-exception-buffer nil) |
2690 | (defvar py-output-buffer "*Python Output*") |
2691 | (make-variable-buffer-local 'py-output-buffer) |
2692 | |
2693 | @@ -1762,7 +1687,7 @@ |
2694 | `jython', equivalent to positive arg and negative arg respectively." |
2695 | (interactive "P") |
2696 | ;; default is to toggle |
2697 | - (if (null arg) |
2698 | + (unless arg |
2699 | (setq arg 0)) |
2700 | ;; preprocess arg |
2701 | (cond |
2702 | @@ -1901,16 +1826,12 @@ |
2703 | is inserted at the end. See also the command `py-clear-queue'." |
2704 | (interactive "r\nP") |
2705 | ;; Skip ahead to the first non-blank line |
2706 | - (let* ((proc (get-process py-which-bufname)) |
2707 | - (temp (if (memq 'broken-temp-names py-emacs-features) |
2708 | - (let |
2709 | - ((sn py-serial-number) |
2710 | - (pid (and (fboundp 'emacs-pid) (emacs-pid)))) |
2711 | - (setq py-serial-number (1+ py-serial-number)) |
2712 | - (if pid |
2713 | - (format "python-%d-%d" sn pid) |
2714 | - (format "python-%d" sn))) |
2715 | - (make-temp-name "python-"))) |
2716 | + (let* ((proc (or |
2717 | + (get-process py-which-bufname) |
2718 | + (save-excursion (py-shell) |
2719 | + (get-process py-which-bufname)))) |
2720 | + (procbuf (process-buffer proc)) |
2721 | + (temp (make-temp-name "python-")) |
2722 | (file (concat (expand-file-name temp py-temp-directory) ".py")) |
2723 | (cur (current-buffer)) |
2724 | (buf (get-buffer-create file)) |
2725 | @@ -1929,6 +1850,7 @@ |
2726 | (let ((needs-if (/= (py-point 'bol) (py-point 'boi)))) |
2727 | (set-buffer buf) |
2728 | (python-mode) |
2729 | + (insert "#-*- coding: utf-8 -*-\n") |
2730 | (when needs-if |
2731 | (insert "if 1:\n") |
2732 | (setq py-line-number-offset (- py-line-number-offset 1))) |
2733 | @@ -1961,16 +1883,16 @@ |
2734 | (save-excursion |
2735 | (set-buffer buf) |
2736 | (write-region (point-min) (point-max) file nil 'nomsg)) |
2737 | - (if (not py-file-queue) |
2738 | - (py-execute-file proc file) |
2739 | - (message "File %s queued for execution" file)) |
2740 | - (setq py-file-queue (append py-file-queue (list file))) |
2741 | - (setq py-exception-buffer (cons file (current-buffer)))) |
2742 | + (py-execute-file proc file) |
2743 | + (setq py-exception-buffer (cons file (current-buffer))) |
2744 | + (switch-to-buffer procbuf)) |
2745 | (t |
2746 | ;; TBD: a horrible hack, but why create new Custom variables? |
2747 | - (let ((cmd (concat py-which-shell (if (string-equal py-which-bufname |
2748 | - "Jython") |
2749 | - " -" "")))) |
2750 | + (let ((cmd |
2751 | + ;; (concat py-which-shell (if (string-equal py-which-bufname |
2752 | + (concat shell (if (string-equal py-which-bufname |
2753 | + "Jython") |
2754 | + " -" "")))) |
2755 | ;; otherwise either run it synchronously in a subprocess |
2756 | (save-excursion |
2757 | (set-buffer buf) |
2758 | @@ -1984,9 +1906,7 @@ |
2759 | (let ((err-p (py-postprocess-output-buffer py-output-buffer))) |
2760 | (pop-to-buffer py-output-buffer) |
2761 | (if err-p |
2762 | - (pop-to-buffer py-exception-buffer))) |
2763 | - )) |
2764 | - )) |
2765 | + (pop-to-buffer py-exception-buffer))))))) |
2766 | ;; Clean up after ourselves. |
2767 | (kill-buffer buf))) |
2768 | |
2769 | @@ -2061,7 +1981,6 @@ |
2770 | ;; else |
2771 | (py-execute-buffer async)))) |
2772 | |
2773 | - |
2774 | (defun py-execute-def-or-class (&optional async) |
2775 | "Send the current function or class definition to a Python interpreter. |
2776 | |
2777 | @@ -2075,7 +1994,6 @@ |
2778 | ;; mark is before point |
2779 | (py-execute-region (mark) (point) async))) |
2780 | |
2781 | - |
2782 | (defun py-execute-string (string &optional async) |
2783 | "Send the argument STRING to a Python interpreter. |
2784 | |
2785 | @@ -2090,7 +2008,6 @@ |
2786 | (insert string) |
2787 | (py-execute-region (point-min) (point-max) async))) |
2788 | |
2789 | - |
2790 | |
2791 | |
2792 | (defun py-jump-to-exception (file line) |
2793 | "Jump to the Python code in FILE at LINE." |
2794 | @@ -2112,28 +2029,29 @@ |
2795 | |
2796 | (pop-to-buffer buffer) |
2797 | ;; Force Python mode |
2798 | - (if (not (eq major-mode 'python-mode)) |
2799 | + (unless(eq major-mode 'python-mode) |
2800 | (python-mode)) |
2801 | - (goto-line line) |
2802 | + (goto-char (point-min)) |
2803 | + (forward-line line) |
2804 | (message "Jumping to exception in file %s on line %d" file line))) |
2805 | |
2806 | -(defun py-mouseto-exception (event) |
2807 | - "Jump to the code which caused the Python exception at EVENT. |
2808 | +(when (featurep 'xemacs) |
2809 | + (defun py-mouseto-exception (event) |
2810 | + "Jump to the code which caused the Python exception at EVENT. |
2811 | EVENT is usually a mouse click." |
2812 | - (interactive "e") |
2813 | - (cond |
2814 | - ((fboundp 'event-point) |
2815 | - ;; XEmacs |
2816 | - (let* ((point (event-point event)) |
2817 | - (buffer (event-buffer event)) |
2818 | - (e (and point buffer (extent-at point buffer 'py-exc-info))) |
2819 | - (info (and e (extent-property e 'py-exc-info)))) |
2820 | - (message "Event point: %d, info: %s" point info) |
2821 | - (and info |
2822 | - (py-jump-to-exception (car info) (cdr info))) |
2823 | - )) |
2824 | - ;; Emacs -- Please port this! |
2825 | - )) |
2826 | + (interactive "e") |
2827 | + (cond |
2828 | + ((fboundp 'event-point) |
2829 | + ;; XEmacs |
2830 | + (let* ((point (event-point event)) |
2831 | + (buffer (event-buffer event)) |
2832 | + (e (and point buffer (extent-at point buffer 'py-exc-info))) |
2833 | + (info (and e (extent-property e 'py-exc-info)))) |
2834 | + (message "Event point: %d, info: %s" point info) |
2835 | + (and info |
2836 | + (py-jump-to-exception (car info) (cdr info))))) |
2837 | + ;; Emacs -- Please port this! |
2838 | + ))) |
2839 | |
2840 | (defun py-goto-exception () |
2841 | "Go to the line indicated by the traceback." |
2842 | @@ -2191,83 +2109,32 @@ |
2843 | |
2844 | |
2845 | |
2846 | ;; Electric deletion |
2847 | -(defun py-electric-backspace (arg) |
2848 | - "Delete preceding character or levels of indentation. |
2849 | -Deletion is performed by calling the function in `py-backspace-function' |
2850 | -with a single argument (the number of characters to delete). |
2851 | - |
2852 | -If point is at the leftmost column, delete the preceding newline. |
2853 | - |
2854 | -Otherwise, if point is at the leftmost non-whitespace character of a |
2855 | -line that is neither a continuation line nor a non-indenting comment |
2856 | -line, or if point is at the end of a blank line, this command reduces |
2857 | -the indentation to match that of the line that opened the current |
2858 | -block of code. The line that opened the block is displayed in the |
2859 | -echo area to help you keep track of where you are. With |
2860 | -\\[universal-argument] dedents that many blocks (but not past column |
2861 | -zero). |
2862 | - |
2863 | -Otherwise the preceding character is deleted, converting a tab to |
2864 | -spaces if needed so that only a single column position is deleted. |
2865 | -\\[universal-argument] specifies how many characters to delete; |
2866 | -default is 1. |
2867 | - |
2868 | -When used programmatically, argument ARG specifies the number of |
2869 | -blocks to dedent, or the number of characters to delete, as indicated |
2870 | -above." |
2871 | +(defun py-electric-backspace (&optional arg) |
2872 | + "Delete preceding character or level of indentation. |
2873 | +With ARG do that ARG times. " |
2874 | (interactive "*p") |
2875 | - (if (or (/= (current-indentation) (current-column)) |
2876 | - (bolp) |
2877 | - (py-continuation-line-p) |
2878 | -; (not py-honor-comment-indentation) |
2879 | -; (looking-at "#[^ \t\n]") ; non-indenting # |
2880 | - ) |
2881 | - (funcall py-backspace-function arg) |
2882 | - ;; else indent the same as the colon line that opened the block |
2883 | - ;; force non-blank so py-goto-block-up doesn't ignore it |
2884 | - (insert-char ?* 1) |
2885 | - (backward-char) |
2886 | - (let ((base-indent 0) ; indentation of base line |
2887 | - (base-text "") ; and text of base line |
2888 | - (base-found-p nil)) |
2889 | - (save-excursion |
2890 | - (while (< 0 arg) |
2891 | - (condition-case nil ; in case no enclosing block |
2892 | - (progn |
2893 | - (py-goto-block-up 'no-mark) |
2894 | - (setq base-indent (current-indentation) |
2895 | - base-text (py-suck-up-leading-text) |
2896 | - base-found-p t)) |
2897 | - (error nil)) |
2898 | - (setq arg (1- arg)))) |
2899 | - (delete-char 1) ; toss the dummy character |
2900 | - (delete-horizontal-space) |
2901 | - (indent-to base-indent) |
2902 | - (if base-found-p |
2903 | - (message "Closes block: %s" base-text))))) |
2904 | - |
2905 | - |
2906 | -(defun py-electric-delete (arg) |
2907 | + (let ((arg (or arg 1))) |
2908 | + (dotimes (i arg) |
2909 | + (if (looking-back "^[ \t]+") |
2910 | + (let* ((remains (% (current-column) py-indent-offset))) |
2911 | + (if (< 0 remains) |
2912 | + (delete-char (- remains)) |
2913 | + (indent-line-to (- (current-indentation) py-indent-offset)))) |
2914 | + (delete-char (- 1)))))) |
2915 | + |
2916 | +(defun py-electric-delete (&optional arg) |
2917 | "Delete preceding or following character or levels of whitespace. |
2918 | |
2919 | -The behavior of this function depends on the variable |
2920 | -`delete-key-deletes-forward'. If this variable is nil (or does not |
2921 | -exist, as in older Emacsen and non-XEmacs versions), then this |
2922 | -function behaves identically to \\[c-electric-backspace]. |
2923 | - |
2924 | -If `delete-key-deletes-forward' is non-nil and is supported in your |
2925 | -Emacs, then deletion occurs in the forward direction, by calling the |
2926 | -function in `py-delete-function'. |
2927 | - |
2928 | -\\[universal-argument] (programmatically, argument ARG) specifies the |
2929 | -number of characters to delete (default is 1)." |
2930 | +With ARG do that ARG times. " |
2931 | (interactive "*p") |
2932 | - (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21 |
2933 | - (delete-forward-p)) |
2934 | - (and (boundp 'delete-key-deletes-forward) ;XEmacs 20 |
2935 | - delete-key-deletes-forward)) |
2936 | - (funcall py-delete-function arg) |
2937 | - (py-electric-backspace arg))) |
2938 | + (let ((arg (or arg 1))) |
2939 | + (dotimes (i arg) |
2940 | + (if (and (or (bolp)(looking-back "^[ \t]+")) (looking-at "[ \t]+")) |
2941 | + (let* ((remains (% (+ (current-column) (- (match-end 0)(match-beginning 0))) py-indent-offset))) |
2942 | + (if (< 0 remains) |
2943 | + (delete-char remains) |
2944 | + (delete-char py-indent-offset))) |
2945 | + (delete-char 1))))) |
2946 | |
2947 | ;; required for pending-del and delsel modes |
2948 | (put 'py-electric-colon 'delete-selection t) ;delsel |
2949 | @@ -2277,42 +2144,18 @@ |
2950 | (put 'py-electric-delete 'delete-selection 'supersede) ;delsel |
2951 | (put 'py-electric-delete 'pending-delete 'supersede) ;pending-del |
2952 | |
2953 | - |
2954 | +33333 |
2955 | |
2956 | |
2957 | -(defun py-indent-line (&optional arg) |
2958 | +(defun py-indent-line () |
2959 | "Fix the indentation of the current line according to Python rules. |
2960 | -With \\[universal-argument] (programmatically, the optional argument |
2961 | -ARG non-nil), ignore dedenting rules for block closing statements |
2962 | -\(e.g. return, raise, break, continue, pass) |
2963 | |
2964 | This function is normally bound to `indent-line-function' so |
2965 | \\[indent-for-tab-command] will call it." |
2966 | - (interactive "P") |
2967 | - (let* ((ci (current-indentation)) |
2968 | - (move-to-indentation-p (<= (current-column) ci)) |
2969 | - (need (py-compute-indentation (not arg))) |
2970 | - (cc (current-column))) |
2971 | - ;; dedent out a level if previous command was the same unless we're in |
2972 | - ;; column 1 |
2973 | - (if (and (equal last-command this-command) |
2974 | - (/= cc 0)) |
2975 | - (progn |
2976 | - (beginning-of-line) |
2977 | - (delete-horizontal-space) |
2978 | - (indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset))) |
2979 | - (progn |
2980 | - ;; see if we need to dedent |
2981 | - (if (py-outdent-p) |
2982 | - (setq need (- need py-indent-offset))) |
2983 | - (if (or py-tab-always-indent |
2984 | - move-to-indentation-p) |
2985 | - (progn (if (/= ci need) |
2986 | - (save-excursion |
2987 | - (beginning-of-line) |
2988 | - (delete-horizontal-space) |
2989 | - (indent-to need))) |
2990 | - (if move-to-indentation-p (back-to-indentation))) |
2991 | - (insert-tab)))))) |
2992 | + (interactive) |
2993 | + (let* ((need (py-compute-indentation (point)))) |
2994 | + (beginning-of-line) |
2995 | + (delete-horizontal-space) |
2996 | + (indent-to need))) |
2997 | |
2998 | (defun py-newline-and-indent () |
2999 | "Strives to act like the Emacs `newline-and-indent'. |
3000 | @@ -2329,239 +2172,133 @@ |
3001 | (insert-char ?\n 1) |
3002 | (move-to-column ci)))) |
3003 | |
3004 | -(defun py-compute-indentation (honor-block-close-p) |
3005 | +(defalias 'py-newline-and-close-block 'py-newline-and-dedent) |
3006 | +(defun py-newline-and-dedent () |
3007 | + "Add a newline and indent to one level below current. " |
3008 | + (interactive "*") |
3009 | + (let ((cui (current-indentation)) |
3010 | + goal) |
3011 | + (newline) |
3012 | + (when (< 0 cui) |
3013 | + (setq goal (py-compute-indentation)) |
3014 | + (indent-to-column (- goal py-indent-offset))))) |
3015 | + |
3016 | +(defun py-compute-indentation (&optional orig origline) |
3017 | "Compute Python indentation. |
3018 | -When HONOR-BLOCK-CLOSE-P is non-nil, statements such as `return', |
3019 | -`raise', `break', `continue', and `pass' force one level of |
3020 | -dedenting." |
3021 | + When HONOR-BLOCK-CLOSE-P is non-nil, statements such as `return', |
3022 | +`raise', `break', `continue', and `pass' force one level of dedenting." |
3023 | + (interactive "P") |
3024 | (save-excursion |
3025 | - (beginning-of-line) |
3026 | - (let* ((bod (py-point 'bod)) |
3027 | - (pps (parse-partial-sexp bod (point))) |
3028 | - (boipps (parse-partial-sexp bod (py-point 'boi))) |
3029 | - placeholder) |
3030 | - (cond |
3031 | - ;; are we inside a multi-line string or comment? |
3032 | - ((or (and (nth 3 pps) (nth 3 boipps)) |
3033 | - (and (nth 4 pps) (nth 4 boipps))) |
3034 | - (save-excursion |
3035 | - (if (not py-align-multiline-strings-p) 0 |
3036 | - ;; skip back over blank & non-indenting comment lines |
3037 | - ;; note: will skip a blank or non-indenting comment line |
3038 | - ;; that happens to be a continuation line too |
3039 | - (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move) |
3040 | - (back-to-indentation) |
3041 | - (current-column)))) |
3042 | - ;; are we on a continuation line? |
3043 | - ((py-continuation-line-p) |
3044 | - (let ((startpos (point)) |
3045 | - (open-bracket-pos (py-nesting-level)) |
3046 | - endpos searching found state cind cline) |
3047 | - (if open-bracket-pos |
3048 | - (progn |
3049 | - (setq endpos (py-point 'bol)) |
3050 | - (py-goto-initial-line) |
3051 | - (setq cind (current-indentation)) |
3052 | - (setq cline cind) |
3053 | - (dolist (bp |
3054 | - (nth 9 (save-excursion |
3055 | - (parse-partial-sexp (point) endpos))) |
3056 | - cind) |
3057 | - (if (search-forward "\n" bp t) (setq cline cind)) |
3058 | - (goto-char (1+ bp)) |
3059 | - (skip-chars-forward " \t") |
3060 | - (setq cind (if (memq (following-char) '(?\n ?# ?\\)) |
3061 | - (+ cline py-indent-offset) |
3062 | - (current-column))))) |
3063 | - ;; else on backslash continuation line |
3064 | - (forward-line -1) |
3065 | - (if (py-continuation-line-p) ; on at least 3rd line in block |
3066 | - (current-indentation) ; so just continue the pattern |
3067 | - ;; else started on 2nd line in block, so indent more. |
3068 | - ;; if base line is an assignment with a start on a RHS, |
3069 | - ;; indent to 2 beyond the leftmost "="; else skip first |
3070 | - ;; chunk of non-whitespace characters on base line, + 1 more |
3071 | - ;; column |
3072 | - (end-of-line) |
3073 | - (setq endpos (point) |
3074 | - searching t) |
3075 | - (back-to-indentation) |
3076 | - (setq startpos (point)) |
3077 | - ;; look at all "=" from left to right, stopping at first |
3078 | - ;; one not nested in a list or string |
3079 | - (while searching |
3080 | - (skip-chars-forward "^=" endpos) |
3081 | - (if (= (point) endpos) |
3082 | - (setq searching nil) |
3083 | - (forward-char 1) |
3084 | - (setq state (parse-partial-sexp startpos (point))) |
3085 | - (if (and (zerop (car state)) ; not in a bracket |
3086 | - (null (nth 3 state))) ; & not in a string |
3087 | - (progn |
3088 | - (setq searching nil) ; done searching in any case |
3089 | - (setq found |
3090 | - (not (or |
3091 | - (eq (following-char) ?=) |
3092 | - (memq (char-after (- (point) 2)) |
3093 | - '(?< ?> ?!))))))))) |
3094 | - (if (or (not found) ; not an assignment |
3095 | - (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash> |
3096 | - (progn |
3097 | - (goto-char startpos) |
3098 | - (skip-chars-forward "^ \t\n"))) |
3099 | - ;; if this is a continuation for a block opening |
3100 | - ;; statement, add some extra offset. |
3101 | - (+ (current-column) (if (py-statement-opens-block-p) |
3102 | - py-continuation-offset 0) |
3103 | - 1) |
3104 | - )))) |
3105 | - |
3106 | - ;; not on a continuation line |
3107 | - ((bobp) (current-indentation)) |
3108 | - |
3109 | - ;; Dfn: "Indenting comment line". A line containing only a |
3110 | - ;; comment, but which is treated like a statement for |
3111 | - ;; indentation calculation purposes. Such lines are only |
3112 | - ;; treated specially by the mode; they are not treated |
3113 | - ;; specially by the Python interpreter. |
3114 | - |
3115 | - ;; The rules for indenting comment lines are a line where: |
3116 | - ;; - the first non-whitespace character is `#', and |
3117 | - ;; - the character following the `#' is whitespace, and |
3118 | - ;; - the line is dedented with respect to (i.e. to the left |
3119 | - ;; of) the indentation of the preceding non-blank line. |
3120 | - |
3121 | - ;; The first non-blank line following an indenting comment |
3122 | - ;; line is given the same amount of indentation as the |
3123 | - ;; indenting comment line. |
3124 | - |
3125 | - ;; All other comment-only lines are ignored for indentation |
3126 | - ;; purposes. |
3127 | - |
3128 | - ;; Are we looking at a comment-only line which is *not* an |
3129 | - ;; indenting comment line? If so, we assume that it's been |
3130 | - ;; placed at the desired indentation, so leave it alone. |
3131 | - ;; Indenting comment lines are aligned as statements down |
3132 | - ;; below. |
3133 | - ((and (looking-at "[ \t]*#[^ \t\n]") |
3134 | - ;; NOTE: this test will not be performed in older Emacsen |
3135 | - (fboundp 'forward-comment) |
3136 | - (<= (current-indentation) |
3137 | - (save-excursion |
3138 | - (forward-comment (- (point-max))) |
3139 | - (current-indentation)))) |
3140 | - (current-indentation)) |
3141 | - |
3142 | - ;; else indentation based on that of the statement that |
3143 | - ;; precedes us; use the first line of that statement to |
3144 | - ;; establish the base, in case the user forced a non-std |
3145 | - ;; indentation for the continuation lines (if any) |
3146 | - (t |
3147 | - ;; skip back over blank & non-indenting comment lines note: |
3148 | - ;; will skip a blank or non-indenting comment line that |
3149 | - ;; happens to be a continuation line too. use fast Emacs 19 |
3150 | - ;; function if it's there. |
3151 | - (if (and (eq py-honor-comment-indentation nil) |
3152 | - (fboundp 'forward-comment)) |
3153 | - (forward-comment (- (point-max))) |
3154 | - (let ((prefix-re (concat py-block-comment-prefix "[ \t]*")) |
3155 | - done) |
3156 | - (while (not done) |
3157 | - (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#\\)" nil 'move) |
3158 | - (setq done (or (bobp) |
3159 | - (and (eq py-honor-comment-indentation t) |
3160 | - (save-excursion |
3161 | - (back-to-indentation) |
3162 | - (not (looking-at prefix-re)) |
3163 | - )) |
3164 | - (and (not (eq py-honor-comment-indentation t)) |
3165 | - (save-excursion |
3166 | - (back-to-indentation) |
3167 | - (and (not (looking-at prefix-re)) |
3168 | - (or (looking-at "[^#]") |
3169 | - (not (zerop (current-column))) |
3170 | - )) |
3171 | - )) |
3172 | - )) |
3173 | - ))) |
3174 | - ;; if we landed inside a string, go to the beginning of that |
3175 | - ;; string. this handles triple quoted, multi-line spanning |
3176 | - ;; strings. |
3177 | - (py-goto-beginning-of-tqs (nth 3 (parse-partial-sexp bod (point)))) |
3178 | - ;; now skip backward over continued lines |
3179 | - (setq placeholder (point)) |
3180 | - (py-goto-initial-line) |
3181 | - ;; we may *now* have landed in a TQS, so find the beginning of |
3182 | - ;; this string. |
3183 | - (py-goto-beginning-of-tqs |
3184 | - (save-excursion (nth 3 (parse-partial-sexp |
3185 | - placeholder (point))))) |
3186 | - (+ (current-indentation) |
3187 | - (if (py-statement-opens-block-p) |
3188 | - py-indent-offset |
3189 | - (if (and honor-block-close-p (py-statement-closes-block-p)) |
3190 | - (- py-indent-offset) |
3191 | - 0))) |
3192 | - ))))) |
3193 | + (save-restriction |
3194 | + (widen) |
3195 | + (let* ((orig (or orig (point))) |
3196 | + (origline (or origline (py-count-lines))) |
3197 | + (pps (parse-partial-sexp (point-min) (point))) |
3198 | + erg indent) |
3199 | + ;; (back-to-indentation) |
3200 | + (setq indent |
3201 | + (cond |
3202 | + ;; (py-in-triplequoted-string-p) |
3203 | + ((and (nth 3 pps)(nth 8 pps)(save-excursion (ignore-errors (goto-char (nth 2 pps))) (not (eq origline (py-count-lines))))) |
3204 | + (goto-char (nth 2 pps)) |
3205 | + (current-column)) |
3206 | + ;; beginning of statement from before got beginning |
3207 | + ((looking-at "\"\"\"\\|'''") |
3208 | + (py-beginning-of-statement) |
3209 | + (py-compute-indentation orig origline)) |
3210 | + ;; comments and strings |
3211 | + ((nth 8 pps) |
3212 | + (goto-char (nth 8 pps)) |
3213 | + (skip-chars-backward " \t\r\n\f") |
3214 | + (py-compute-indentation orig origline)) |
3215 | + ;; lists |
3216 | + ((and (nth 1 pps) py-indent-honors-multiline-listing) |
3217 | + (progn (goto-char (+ py-lhs-inbound-indent (nth 1 pps))) |
3218 | + (when (looking-at "[ \t]+") |
3219 | + (goto-char (match-end 0))) |
3220 | + (current-column))) |
3221 | + ((nth 1 pps) |
3222 | + (save-excursion |
3223 | + (py-beginning-of-statement) |
3224 | + (+ (current-column) (* (nth 0 pps) py-indent-offset)))) |
3225 | + ((py-backslashed-continuation-line-p) |
3226 | + (progn (py-beginning-of-statement) |
3227 | + (+ (current-indentation) py-continuation-offset))) |
3228 | + ((not (py-beginning-of-statement-p)) |
3229 | + (py-beginning-of-statement) |
3230 | + (py-compute-indentation orig origline)) |
3231 | + ((looking-at py-if-clause-re) |
3232 | + (py-beginning-of-if-block) |
3233 | + (current-indentation)) |
3234 | + ((looking-at py-try-clause-re) |
3235 | + (py-beginning-of-try-block) |
3236 | + (current-indentation)) |
3237 | + ((looking-at py-clause-re) |
3238 | + (py-beginning-of-block) |
3239 | + (current-indentation)) |
3240 | + ((looking-at py-block-closing-keywords-re) |
3241 | + (save-excursion |
3242 | + (py-beginning-of-block) |
3243 | + (current-indentation))) |
3244 | + ((looking-at py-assignement-re) |
3245 | + (current-indentation)) |
3246 | + ((and (eq origline (py-count-lines)) |
3247 | + (setq erg (py-go-to-keyword py-block-or-clause-re -1))) |
3248 | + (+ (car erg) py-indent-offset)) |
3249 | + ((looking-at py-block-or-clause-re) |
3250 | + (+ (current-indentation) py-indent-offset)) |
3251 | + ((py-statement-opens-block-p) |
3252 | + (+ py-indent-offset (current-indentation))) |
3253 | + ((bobp) |
3254 | + (current-indentation)) |
3255 | + (t (current-indentation)))) |
3256 | + (when (interactive-p) (message "%s" indent)) |
3257 | + indent)))) |
3258 | |
3259 | (defun py-guess-indent-offset (&optional global) |
3260 | - "Guess a good value for, and change, `py-indent-offset'. |
3261 | + "Guess a value for, and change, `py-indent-offset'. |
3262 | |
3263 | By default, make a buffer-local copy of `py-indent-offset' with the |
3264 | -new value, so that other Python buffers are not affected. With |
3265 | -\\[universal-argument] (programmatically, optional argument GLOBAL), |
3266 | -change the global value of `py-indent-offset'. This affects all |
3267 | -Python buffers (that don't have their own buffer-local copy), both |
3268 | -those currently existing and those created later in the Emacs session. |
3269 | - |
3270 | -Some people use a different value for `py-indent-offset' than you use. |
3271 | -There's no excuse for such foolishness, but sometimes you have to deal |
3272 | -with their ugly code anyway. This function examines the file and sets |
3273 | -`py-indent-offset' to what it thinks it was when they created the |
3274 | -mess. |
3275 | - |
3276 | -Specifically, it searches forward from the statement containing point, |
3277 | -looking for a line that opens a block of code. `py-indent-offset' is |
3278 | -set to the difference in indentation between that line and the Python |
3279 | -statement following it. If the search doesn't succeed going forward, |
3280 | -it's tried again going backward." |
3281 | - (interactive "P") ; raw prefix arg |
3282 | - (let (new-value |
3283 | - (start (point)) |
3284 | - (restart (point)) |
3285 | - (found nil) |
3286 | - colon-indent) |
3287 | - (py-goto-initial-line) |
3288 | - (while (not (or found (eobp))) |
3289 | - (when (and (re-search-forward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
3290 | - (not (py-in-literal restart))) |
3291 | - (setq restart (point)) |
3292 | - (py-goto-initial-line) |
3293 | - (if (py-statement-opens-block-p) |
3294 | - (setq found t) |
3295 | - (goto-char restart)))) |
3296 | - (unless found |
3297 | - (goto-char start) |
3298 | - (py-goto-initial-line) |
3299 | - (while (not (or found (bobp))) |
3300 | - (setq found (and |
3301 | - (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
3302 | - (or (py-goto-initial-line) t) ; always true -- side effect |
3303 | - (py-statement-opens-block-p))))) |
3304 | - (setq colon-indent (current-indentation) |
3305 | - found (and found (zerop (py-next-statement 1))) |
3306 | - new-value (- (current-indentation) colon-indent)) |
3307 | - (goto-char start) |
3308 | - (if (not found) |
3309 | - (error "Sorry, couldn't guess a value for py-indent-offset") |
3310 | - (funcall (if global 'kill-local-variable 'make-local-variable) |
3311 | - 'py-indent-offset) |
3312 | - (setq py-indent-offset new-value) |
3313 | - (or noninteractive |
3314 | - (message "%s value of py-indent-offset set to %d" |
3315 | +new value. |
3316 | +With optional argument GLOBAL, |
3317 | +change the global value of `py-indent-offset'. " |
3318 | + (interactive "P") |
3319 | + (save-excursion |
3320 | + (save-restriction |
3321 | + (widen) |
3322 | + (lexical-let ((old-value py-indent-offset) |
3323 | + (orig (point)) |
3324 | + done indent first) |
3325 | + (while (and (not done) (not (bobp))) |
3326 | + (setq first (progn (unless done (py-beginning-of-statement)(current-indentation)))) |
3327 | + (save-excursion |
3328 | + (py-beginning-of-statement) |
3329 | + (setq indent (abs (- first (current-indentation)))) |
3330 | + (if (and indent (>= indent 2) (<= indent 8)) ; sanity check |
3331 | + (setq done t)))) |
3332 | + (unless done |
3333 | + ;; search downward |
3334 | + (goto-char orig) |
3335 | + (while (and (not done) (not (eobp))) |
3336 | + (setq first (progn (unless done (py-end-of-statement)(current-indentation)))) |
3337 | + (py-end-of-statement) |
3338 | + (save-excursion |
3339 | + (py-beginning-of-statement) |
3340 | + (setq indent (abs (- (current-indentation) first))) |
3341 | + (if (and indent (>= indent 2) (<= indent 8)) ; sanity check |
3342 | + (setq done t))))) |
3343 | + (when done |
3344 | + (when (/= indent (default-value 'py-indent-offset)) |
3345 | + (funcall (if global 'kill-local-variable 'make-local-variable) |
3346 | + 'py-indent-offset) |
3347 | + (setq py-indent-offset indent) |
3348 | + (unless (= tab-width py-indent-offset) |
3349 | + (setq indent-tabs-mode nil))) |
3350 | + (unless (and (eq old-value py-indent-offset) (eq py-indent-offset (default-value 'py-indent-offset))) |
3351 | + (message "%s value of py-indent-offset: %d" |
3352 | (if global "Global" "Local") |
3353 | py-indent-offset))) |
3354 | - )) |
3355 | + py-indent-offset)))) |
3356 | |
3357 | (defun py-comment-indent-function () |
3358 | "Python version of `comment-indent-function'." |
3359 | @@ -2779,391 +2516,396 @@ |
3360 | (insert ")") |
3361 | ))) |
3362 | |
3363 | - |
3364 | |
3365 | |
3366 | ;; Functions for moving point |
3367 | -(defun py-previous-statement (count) |
3368 | - "Go to the start of the COUNTth preceding Python statement. |
3369 | -By default, goes to the previous statement. If there is no such |
3370 | -statement, goes to the first statement. Return count of statements |
3371 | -left to move. `Statements' do not include blank, comment, or |
3372 | -continuation lines." |
3373 | - (interactive "p") ; numeric prefix arg |
3374 | - (if (< count 0) (py-next-statement (- count)) |
3375 | - (py-goto-initial-line) |
3376 | - (let (start) |
3377 | - (while (and |
3378 | - (setq start (point)) ; always true -- side effect |
3379 | - (> count 0) |
3380 | - (zerop (forward-line -1)) |
3381 | - (py-goto-statement-at-or-above)) |
3382 | - (setq count (1- count))) |
3383 | - (if (> count 0) (goto-char start))) |
3384 | - count)) |
3385 | - |
3386 | -(defun py-next-statement (count) |
3387 | - "Go to the start of next Python statement. |
3388 | -If the statement at point is the i'th Python statement, goes to the |
3389 | -start of statement i+COUNT. If there is no such statement, goes to the |
3390 | -last statement. Returns count of statements left to move. `Statements' |
3391 | -do not include blank, comment, or continuation lines." |
3392 | - (interactive "p") ; numeric prefix arg |
3393 | - (if (< count 0) (py-previous-statement (- count)) |
3394 | - (beginning-of-line) |
3395 | - (let (start) |
3396 | - (while (and |
3397 | - (setq start (point)) ; always true -- side effect |
3398 | - (> count 0) |
3399 | - (py-goto-statement-below)) |
3400 | - (setq count (1- count))) |
3401 | - (if (> count 0) (goto-char start))) |
3402 | - count)) |
3403 | - |
3404 | +(defalias 'py-hungry-delete-forward 'c-hungry-delete-forward) |
3405 | +(defalias 'py-hungry-delete-backwards 'c-hungry-delete-backwards) |
3406 | + |
3407 | +;; Statement |
3408 | +(defalias 'py-backward-statement 'py-beginning-of-statement) |
3409 | +(defalias 'py-previous-statement 'py-beginning-of-statement) |
3410 | +(defalias 'py-statement-backward 'py-beginning-of-statement) |
3411 | +(defalias 'py-goto-statement-at-or-above 'py-beginning-of-statement) |
3412 | +(defun py-beginning-of-statement (&optional orig origline) |
3413 | + "Go to the initial line of a simple statement. |
3414 | + |
3415 | +For beginning of compound statement use py-beginning-of-block. |
3416 | +For beginning of clause py-beginning-of-clause. |
3417 | + |
3418 | +Referring python program structures see for example: |
3419 | +http://docs.python.org/reference/compound_stmts.html |
3420 | +" |
3421 | + (interactive) |
3422 | + (save-restriction |
3423 | + (widen) |
3424 | + (if (and (bobp) orig) |
3425 | + (point) |
3426 | + (unless (bobp) |
3427 | + (let ((orig (or orig (point))) |
3428 | + (cui (current-indentation)) |
3429 | + (origline (or origline (py-count-lines))) |
3430 | + (pps (parse-partial-sexp (point-min) (point))) |
3431 | + erg) |
3432 | + (unless (< (point) orig)(skip-chars-backward " \t\r\n\f")) |
3433 | + |
3434 | + (setq erg |
3435 | + (cond |
3436 | + ((empty-line-p) |
3437 | + (forward-line -1) |
3438 | + (while (and (not (bobp))(empty-line-p)) |
3439 | + (forward-line -1)) |
3440 | + (end-of-line) |
3441 | + (py-beginning-of-statement orig origline)) |
3442 | + ;; if in string |
3443 | + ((and (nth 3 pps)(nth 8 pps) |
3444 | + (save-excursion |
3445 | + (ignore-errors |
3446 | + (goto-char (nth 2 pps))) |
3447 | + ;; (not (eq origline (py-count-lines))) |
3448 | + )) |
3449 | + (goto-char (nth 2 pps)) |
3450 | + (py-beginning-of-statement orig origline)) |
3451 | + ;; comments left, as strings are done |
3452 | + ((nth 8 pps) |
3453 | + (goto-char (1- (nth 8 pps))) |
3454 | + (py-beginning-of-statement orig origline)) |
3455 | + ((looking-at "[ \t]*#") |
3456 | + (forward-line -1) (end-of-line) |
3457 | + (py-beginning-of-statement orig origline)) |
3458 | + ((py-backslashed-continuation-line-p) |
3459 | + (forward-line -1) |
3460 | + (py-beginning-of-statement orig origline)) |
3461 | + ;; character address of start of innermost containing list; nil if none. |
3462 | + ((nth 1 pps) |
3463 | + (goto-char (nth 1 pps)) |
3464 | + (forward-char -1) |
3465 | + (py-beginning-of-statement orig origline)) |
3466 | + ((and (eq (current-indentation) (current-column)) |
3467 | + (eq (point) orig) (not (bolp))) |
3468 | + (beginning-of-line) |
3469 | + (py-beginning-of-statement orig origline)) |
3470 | + ((and |
3471 | + (not (string= "" (make-string (- orig (point)) ? ))) |
3472 | + (looking-at (make-string (- orig (point)) ? ))) |
3473 | + (forward-line -1) |
3474 | + (py-beginning-of-statement orig origline)) |
3475 | + ((not (eq (current-column) (current-indentation))) |
3476 | + (back-to-indentation) |
3477 | + (py-beginning-of-statement orig origline)) |
3478 | + ((and (eq (point) orig)(or (bolp) (<= (current-column)(current-indentation)))) |
3479 | + (forward-line -1) |
3480 | + (end-of-line) |
3481 | + (skip-chars-backward " \t") |
3482 | + (py-beginning-of-statement orig origline)) |
3483 | + (t (point)))) |
3484 | + (when (interactive-p) (message "%s" erg)) |
3485 | + erg))))) |
3486 | + |
3487 | +(defalias 'py-statement-forward 'py-end-of-statement) |
3488 | +(defalias 'py-next-statement 'py-end-of-statement) |
3489 | +(defalias 'py-forward-statement 'py-end-of-statement) |
3490 | +(defun py-end-of-statement (&optional orig origline done) |
3491 | + "Go to the point just beyond the final line of the current statement. " |
3492 | + (interactive) |
3493 | + (save-restriction |
3494 | + (widen) |
3495 | + (unless (eobp) |
3496 | + (let* ((orig (or orig (point))) |
3497 | + (origline (or origline (py-count-lines))) |
3498 | + (pps (parse-partial-sexp (point-min) (point)))) |
3499 | + (cond |
3500 | + ((and (empty-line-p)(not done)(not (eobp))) |
3501 | + (while |
3502 | + (and (empty-line-p)(not done)(not (eobp))) |
3503 | + (forward-line 1) |
3504 | + (py-end-of-statement (point) origline done))) |
3505 | + ;; start of comment or string; nil if not in one |
3506 | + ((nth 8 pps) |
3507 | + (when (looking-at "\"\"\"\\|'''\\|\"\\|'") |
3508 | + (goto-char (match-end 0))) |
3509 | + (re-search-forward "[^\\]\"\"\"\\|[^\\]'''\\|[^\\]\"\\|[^\\]'" nil (quote move) 1) |
3510 | + (end-of-line) |
3511 | + (skip-chars-backward " \t\r\n\f") |
3512 | + (py-end-of-statement orig origline done)) |
3513 | + ((looking-at "[ \t]*#") |
3514 | + (while (looking-at "[ \t]*#") |
3515 | + (forward-line 1) |
3516 | + (beginning-of-line)) |
3517 | + (end-of-line) |
3518 | + (skip-chars-backward " \t\r\n\f") |
3519 | + (py-end-of-statement orig origline done)) |
3520 | + ((py-backslashed-continuation-line-p) |
3521 | + (py-forward-line) |
3522 | + (py-end-of-statement orig origline done)) |
3523 | + ;; start of innermost containing list; nil if none. |
3524 | + ((nth 1 pps) |
3525 | + (goto-char (nth 1 pps)) |
3526 | + (forward-list) |
3527 | + (setq done t) |
3528 | + (py-end-of-statement orig origline done)) |
3529 | + ((and (eq (point) orig)(not (looking-at "[ \t]*$"))) |
3530 | + (end-of-line) (skip-chars-backward " \t") |
3531 | + (py-beginning-of-comment) |
3532 | + (skip-chars-backward " \t") |
3533 | + (if (< orig (point)) |
3534 | + (py-end-of-statement orig origline done) |
3535 | + (py-forward-line) |
3536 | + (py-end-of-statement orig origline done))) |
3537 | + ((and (eq orig (point))(looking-at "[ \t]*$")(not (eobp))) |
3538 | + (py-forward-line) |
3539 | + (py-end-of-statement orig origline done)) |
3540 | + ((and (eq orig (point))(not (eobp))) |
3541 | + (py-forward-line) |
3542 | + (py-end-of-statement orig origline done)))) |
3543 | + (when (interactive-p) (message "%s" (point))) |
3544 | + (point)))) |
3545 | + |
3546 | +(defun py-goto-statement-below () |
3547 | + "Goto beginning of next statement. " |
3548 | + (interactive) |
3549 | + (lexical-let ((orig (point)) |
3550 | + (erg (py-end-of-statement))) |
3551 | + (py-beginning-of-statement) |
3552 | + (when (< (point) orig) |
3553 | + (goto-char erg) |
3554 | + (py-end-of-statement) |
3555 | + (py-beginning-of-statement)))) |
3556 | + |
3557 | +;; Block |
3558 | +(defalias 'py-previous-block 'py-beginning-of-block) |
3559 | (defalias 'py-goto-block-up 'py-beginning-of-block) |
3560 | -(defun py-beginning-of-block (&optional nomark) |
3561 | - "Move to start of current block. |
3562 | -Go to the statement that starts the smallest enclosing block; roughly |
3563 | -speaking, this will be the closest preceding statement that ends with a |
3564 | -colon and is indented less than the statement you started on. If |
3565 | -successful, also sets the mark to the starting point. |
3566 | - |
3567 | -`\\[py-mark-block]' can be used afterward to mark the whole code |
3568 | -block, if desired. |
3569 | - |
3570 | -If called from a program, the mark will not be set if optional argument |
3571 | -NOMARK is not nil." |
3572 | - (interactive) |
3573 | - (let ((start (point)) |
3574 | - (found nil) |
3575 | - initial-indent) |
3576 | - (py-goto-initial-line) |
3577 | - ;; if on blank or non-indenting comment line, use the preceding stmt |
3578 | - (if (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") |
3579 | - (progn |
3580 | - (py-goto-statement-at-or-above) |
3581 | - (setq found (py-statement-opens-block-p)))) |
3582 | - ;; search back for colon line indented less |
3583 | - (setq initial-indent (current-indentation)) |
3584 | - (if (zerop initial-indent) |
3585 | - ;; force fast exit |
3586 | - (goto-char (point-min))) |
3587 | - (while (not (or found (bobp))) |
3588 | - (setq found |
3589 | - (and |
3590 | - (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
3591 | - (or (py-goto-initial-line) t) ; always true -- side effect |
3592 | - (< (current-indentation) initial-indent) |
3593 | - (py-statement-opens-block-p)))) |
3594 | - (if found |
3595 | - (progn |
3596 | - (or nomark (push-mark start)) |
3597 | - (back-to-indentation)) |
3598 | - (goto-char start) |
3599 | - (error "Enclosing block not found")))) |
3600 | - |
3601 | -(defun py-beginning-of-def-or-class (&optional class count) |
3602 | - "Move point to start of `def' or `class'. |
3603 | - |
3604 | -Searches back for the closest preceding `def'. If you supply a prefix |
3605 | -arg, looks for a `class' instead. The docs below assume the `def' |
3606 | -case; just substitute `class' for `def' for the other case. |
3607 | -Programmatically, if CLASS is `either', then moves to either `class' |
3608 | -or `def'. |
3609 | - |
3610 | -When second optional argument is given programmatically, move to the |
3611 | -COUNTth start of `def'. |
3612 | - |
3613 | -If point is in a `def' statement already, and after the `d', simply |
3614 | -moves point to the start of the statement. |
3615 | - |
3616 | -Otherwise (i.e. when point is not in a `def' statement, or at or |
3617 | -before the `d' of a `def' statement), searches for the closest |
3618 | -preceding `def' statement, and leaves point at its start. If no such |
3619 | -statement can be found, leaves point at the start of the buffer. |
3620 | - |
3621 | -Returns t iff a `def' statement is found by these rules. |
3622 | - |
3623 | -Note that doing this command repeatedly will take you closer to the |
3624 | -start of the buffer each time. |
3625 | - |
3626 | -To mark the current `def', see `\\[py-mark-def-or-class]'." |
3627 | - (interactive "P") ; raw prefix arg |
3628 | - (lexical-let* ((count (or count 1)) |
3629 | - (step (if (< 0 count) -1 1)) |
3630 | - (start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>") |
3631 | - (class "^[ \t]*class\\>") |
3632 | - (t "^[ \t]*def\\>")))) |
3633 | - (while (/= 0 count) |
3634 | - (if (< 0 count) |
3635 | - (unless (looking-at start-re) (end-of-line)) |
3636 | - (end-of-line)) |
3637 | - (if |
3638 | - (re-search-backward start-re nil 'move (- step)) |
3639 | - (unless |
3640 | - ;; if inside a string |
3641 | - (nth 3 (parse-partial-sexp (point-min) (point))) |
3642 | - (goto-char (match-beginning 0)) |
3643 | - (setq count (+ count step))) |
3644 | - (setq count 0))))) |
3645 | - |
3646 | -;; Backwards compatibility |
3647 | -(defalias 'beginning-of-python-def-or-class 'py-beginning-of-def-or-class) |
3648 | - |
3649 | -(defun py-end-of-def-or-class (&optional class count) |
3650 | - "Move point beyond end of `def' or `class' body. |
3651 | - |
3652 | -By default, looks for an appropriate `def'. If you supply a prefix |
3653 | -arg, looks for a `class' instead. The docs below assume the `def' |
3654 | -case; just substitute `class' for `def' for the other case. |
3655 | -Programmatically, if CLASS is `either', then moves to either `class' |
3656 | -or `def'. |
3657 | - |
3658 | -When second optional argument is given programmatically, move to the |
3659 | -COUNTth end of `def'. |
3660 | - |
3661 | -If point is in a `def' statement already, this is the `def' we use. |
3662 | - |
3663 | -Else, if the `def' found by `\\[py-beginning-of-def-or-class]' |
3664 | -contains the statement you started on, that's the `def' we use. |
3665 | - |
3666 | -Otherwise, we search forward for the closest following `def', and use that. |
3667 | - |
3668 | -If a `def' can be found by these rules, point is moved to the start of |
3669 | -the line immediately following the `def' block, and the position of the |
3670 | -start of the `def' is returned. |
3671 | - |
3672 | -Else point is moved to the end of the buffer, and nil is returned. |
3673 | - |
3674 | -Note that doing this command repeatedly will take you closer to the |
3675 | -end of the buffer each time. |
3676 | - |
3677 | -To mark the current `def', see `\\[py-mark-def-or-class]'." |
3678 | - (interactive "P") ; raw prefix arg |
3679 | - (if (and count (/= count 1)) |
3680 | - (py-beginning-of-def-or-class (- 1 count))) |
3681 | - (let ((start (progn (py-goto-initial-line) (point))) |
3682 | - (which (cond ((eq class 'either) "\\(class\\|def\\)") |
3683 | - (class "class") |
3684 | - (t "def"))) |
3685 | - (state 'not-found)) |
3686 | - ;; move point to start of appropriate def/class |
3687 | - (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one |
3688 | - (setq state 'at-beginning) |
3689 | - ;; else see if py-beginning-of-def-or-class hits container |
3690 | - (if (and (py-beginning-of-def-or-class class) |
3691 | - (progn (py-goto-beyond-block) |
3692 | - (> (point) start))) |
3693 | - (setq state 'at-end) |
3694 | - ;; else search forward |
3695 | - (goto-char start) |
3696 | - (if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move) |
3697 | - (progn (setq state 'at-beginning) |
3698 | - (beginning-of-line))))) |
3699 | - (cond |
3700 | - ((eq state 'at-beginning) (py-goto-beyond-block) t) |
3701 | - ((eq state 'at-end) t) |
3702 | - ((eq state 'not-found) nil) |
3703 | - (t (error "Internal error in `py-end-of-def-or-class'"))))) |
3704 | - |
3705 | -;; Backwards compabitility |
3706 | -(defalias 'end-of-python-def-or-class 'py-end-of-def-or-class) |
3707 | - |
3708 | - |
3709 | |
3710 | -;; Functions for marking regions |
3711 | -(defun py-mark-block (&optional extend just-move) |
3712 | - "Mark following block of lines. With prefix arg, mark structure. |
3713 | -Easier to use than explain. It sets the region to an `interesting' |
3714 | -block of succeeding lines. If point is on a blank line, it goes down to |
3715 | -the next non-blank line. That will be the start of the region. The end |
3716 | -of the region depends on the kind of line at the start: |
3717 | - |
3718 | - - If a comment, the region will include all succeeding comment lines up |
3719 | - to (but not including) the next non-comment line (if any). |
3720 | - |
3721 | - - Else if a prefix arg is given, and the line begins one of these |
3722 | - structures: |
3723 | - |
3724 | - if elif else try except finally for while def class |
3725 | - |
3726 | - the region will be set to the body of the structure, including |
3727 | - following blocks that `belong' to it, but excluding trailing blank |
3728 | - and comment lines. E.g., if on a `try' statement, the `try' block |
3729 | - and all (if any) of the following `except' and `finally' blocks |
3730 | - that belong to the `try' structure will be in the region. Ditto |
3731 | - for if/elif/else, for/else and while/else structures, and (a bit |
3732 | - degenerate, since they're always one-block structures) def and |
3733 | - class blocks. |
3734 | - |
3735 | - - Else if no prefix argument is given, and the line begins a Python |
3736 | - block (see list above), and the block is not a `one-liner' (i.e., |
3737 | - the statement ends with a colon, not with code), the region will |
3738 | - include all succeeding lines up to (but not including) the next |
3739 | - code statement (if any) that's indented no more than the starting |
3740 | - line, except that trailing blank and comment lines are excluded. |
3741 | - E.g., if the starting line begins a multi-statement `def' |
3742 | - structure, the region will be set to the full function definition, |
3743 | - but without any trailing `noise' lines. |
3744 | - |
3745 | - - Else the region will include all succeeding lines up to (but not |
3746 | - including) the next blank line, or code or indenting-comment line |
3747 | - indented strictly less than the starting line. Trailing indenting |
3748 | - comment lines are included in this case, but not trailing blank |
3749 | - lines. |
3750 | - |
3751 | -A msg identifying the location of the mark is displayed in the echo |
3752 | -area; or do `\\[exchange-point-and-mark]' to flip down to the end. |
3753 | - |
3754 | -If called from a program, optional argument EXTEND plays the role of |
3755 | -the prefix arg, and if optional argument JUST-MOVE is not nil, just |
3756 | -moves to the end of the block (& does not set mark or display a msg)." |
3757 | - (interactive "P") ; raw prefix arg |
3758 | - (py-goto-initial-line) |
3759 | - ;; skip over blank lines |
3760 | - (while (and |
3761 | - (looking-at "[ \t]*$") ; while blank line |
3762 | - (not (eobp))) ; & somewhere to go |
3763 | - (forward-line 1)) |
3764 | - (if (eobp) |
3765 | - (error "Hit end of buffer without finding a non-blank stmt")) |
3766 | - (let ((initial-pos (point)) |
3767 | - (initial-indent (current-indentation)) |
3768 | - last-pos ; position of last stmt in region |
3769 | - (followers |
3770 | - '((if elif else) (elif elif else) (else) |
3771 | - (try except finally) (except except) (finally) |
3772 | - (for else) (while else) |
3773 | - (def) (class) ) ) |
3774 | - first-symbol next-symbol) |
3775 | - |
3776 | - (cond |
3777 | - ;; if comment line, suck up the following comment lines |
3778 | - ((looking-at "[ \t]*#") |
3779 | - (re-search-forward "^[ \t]*[^ \t#]" nil 'move) ; look for non-comment |
3780 | - (re-search-backward "^[ \t]*#") ; and back to last comment in block |
3781 | - (setq last-pos (point))) |
3782 | - |
3783 | - ;; else if line is a block line and EXTEND given, suck up |
3784 | - ;; the whole structure |
3785 | - ((and extend |
3786 | - (setq first-symbol (py-suck-up-first-keyword) ) |
3787 | - (assq first-symbol followers)) |
3788 | - (while (and |
3789 | - (or (py-goto-beyond-block) t) ; side effect |
3790 | - (forward-line -1) ; side effect |
3791 | - (setq last-pos (point)) ; side effect |
3792 | - (py-goto-statement-below) |
3793 | - (= (current-indentation) initial-indent) |
3794 | - (setq next-symbol (py-suck-up-first-keyword)) |
3795 | - (memq next-symbol (cdr (assq first-symbol followers)))) |
3796 | - (setq first-symbol next-symbol))) |
3797 | - |
3798 | - ;; else if line *opens* a block, search for next stmt indented <= |
3799 | - ((py-statement-opens-block-p) |
3800 | - (while (and |
3801 | - (setq last-pos (point)) ; always true -- side effect |
3802 | - (py-goto-statement-below) |
3803 | - (> (current-indentation) initial-indent) |
3804 | - ))) |
3805 | - |
3806 | - ;; else plain code line; stop at next blank line, or stmt or |
3807 | - ;; indenting comment line indented < |
3808 | - (t |
3809 | - (while (and |
3810 | - (setq last-pos (point)) ; always true -- side effect |
3811 | - (or (py-goto-beyond-final-line) t) |
3812 | - (not (looking-at "[ \t]*$")) ; stop at blank line |
3813 | - (or |
3814 | - (>= (current-indentation) initial-indent) |
3815 | - (looking-at "[ \t]*#[^ \t\n]"))) ; ignore non-indenting # |
3816 | - nil))) |
3817 | - |
3818 | - ;; skip to end of last stmt |
3819 | - (goto-char last-pos) |
3820 | - (py-goto-beyond-final-line) |
3821 | - |
3822 | - ;; set mark & display |
3823 | - (if just-move |
3824 | - () ; just return |
3825 | - (push-mark (point) 'no-msg) |
3826 | - (forward-line -1) |
3827 | - (message "Mark set after: %s" (py-suck-up-leading-text)) |
3828 | - (goto-char initial-pos) |
3829 | - (exchange-point-and-mark) |
3830 | - (py-keep-region-active) |
3831 | - ))) |
3832 | - |
3833 | -(defun py-mark-def-or-class (&optional class) |
3834 | - "Set region to body of def (or class, with prefix arg) enclosing point. |
3835 | -Pushes the current mark, then point, on the mark ring (all language |
3836 | -modes do this, but although it's handy it's never documented ...). |
3837 | - |
3838 | -In most Emacs language modes, this function bears at least a |
3839 | -hallucinogenic resemblance to `\\[py-end-of-def-or-class]' and |
3840 | -`\\[py-beginning-of-def-or-class]'. |
3841 | - |
3842 | -And in earlier versions of Python mode, all 3 were tightly connected. |
3843 | -Turned out that was more confusing than useful: the `goto start' and |
3844 | -`goto end' commands are usually used to search through a file, and |
3845 | -people expect them to act a lot like `search backward' and `search |
3846 | -forward' string-search commands. But because Python `def' and `class' |
3847 | -can nest to arbitrary levels, finding the smallest def containing |
3848 | -point cannot be done via a simple backward search: the def containing |
3849 | -point may not be the closest preceding def, or even the closest |
3850 | -preceding def that's indented less. The fancy algorithm required is |
3851 | -appropriate for the usual uses of this `mark' command, but not for the |
3852 | -`goto' variations. |
3853 | - |
3854 | -So the def marked by this command may not be the one either of the |
3855 | -`goto' commands find: If point is on a blank or non-indenting comment |
3856 | -line, moves back to start of the closest preceding code statement or |
3857 | -indenting comment line. If this is a `def' statement, that's the def |
3858 | -we use. Else searches for the smallest enclosing `def' block and uses |
3859 | -that. Else signals an error. |
3860 | - |
3861 | -When an enclosing def is found: The mark is left immediately beyond |
3862 | -the last line of the def block. Point is left at the start of the |
3863 | -def, except that: if the def is preceded by a number of comment lines |
3864 | -followed by (at most) one optional blank line, point is left at the |
3865 | -start of the comments; else if the def is preceded by a blank line, |
3866 | -point is left at its start. |
3867 | - |
3868 | -The intent is to mark the containing def/class and its associated |
3869 | -documentation, to make moving and duplicating functions and classes |
3870 | -pleasant." |
3871 | - (interactive "P") ; raw prefix arg |
3872 | - (let ((start (point)) |
3873 | - (which (cond ((eq class 'either) "\\(class\\|def\\)") |
3874 | - (class "class") |
3875 | - (t "def")))) |
3876 | - (push-mark start) |
3877 | - (if (not (py-go-up-tree-to-keyword which)) |
3878 | - (progn (goto-char start) |
3879 | - (error "Enclosing %s not found" |
3880 | - (if (eq class 'either) |
3881 | - "def or class" |
3882 | - which))) |
3883 | - ;; else enclosing def/class found |
3884 | - (setq start (point)) |
3885 | - (py-goto-beyond-block) |
3886 | - (push-mark (point)) |
3887 | - (goto-char start) |
3888 | - (if (zerop (forward-line -1)) ; if there is a preceding line |
3889 | +(defalias 'py-backward-block 'py-beginning-of-block) |
3890 | +(defun py-beginning-of-block (&optional count) |
3891 | + "Looks up for nearest opening block, i.e. compound statement |
3892 | + |
3893 | +Returns position reached, if any, nil otherwise. |
3894 | + |
3895 | +Referring python program structures see for example: |
3896 | +http://docs.python.org/reference/compound_stmts.html" |
3897 | + (interactive "p") |
3898 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-block-re -1))))) |
3899 | + (when (interactive-p) (message "%s" erg)) |
3900 | + erg)) |
3901 | + |
3902 | +(defun py-beginning-of-if-block (&optional count) |
3903 | + "Looks up for nearest opening if-block, i.e. compound statement |
3904 | + |
3905 | +Returns position reached, if any, nil otherwise. |
3906 | + |
3907 | +Referring python program structures see for example: |
3908 | +http://docs.python.org/reference/compound_stmts.html" |
3909 | + (interactive "p") |
3910 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-if-block-re -1))))) |
3911 | + (when (interactive-p) (message "%s" erg)) |
3912 | + erg)) |
3913 | + |
3914 | +(defun py-beginning-of-try-block (&optional count) |
3915 | + "Looks up for nearest opening try-block, i.e. compound statement |
3916 | + |
3917 | +Returns position reached, if any, nil otherwise. |
3918 | + |
3919 | +Referring python program structures see for example: |
3920 | +http://docs.python.org/reference/compound_stmts.html" |
3921 | + (interactive "p") |
3922 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-try-block-re -1))))) |
3923 | + (when (interactive-p) (message "%s" erg)) |
3924 | + erg)) |
3925 | + |
3926 | +(defalias 'py-forward-block 'py-end-of-block) |
3927 | +(defun py-end-of-block (&optional count) |
3928 | + "Move point beyond compound statement. " |
3929 | + (interactive "p") |
3930 | + (py-end-of-block-or-clause)) |
3931 | + |
3932 | +;; Block or clause |
3933 | +(defalias 'py-goto-initial-line 'py-beginning-of-block-or-clause) |
3934 | +(defalias 'py-previous-block-or-clause 'py-beginning-of-block-or-clause) |
3935 | +(defalias 'py-goto-block-or-clause-up 'py-beginning-of-block-or-clause) |
3936 | +(defalias 'py-backward-block-or-clause 'py-beginning-of-block-or-clause) |
3937 | + |
3938 | +(defun py-beginning-of-block-or-clause (&optional arg) |
3939 | + "Looks up for nearest opening clause or block. |
3940 | +With universal argument looks for next compound statements |
3941 | +i.e. blocks only. |
3942 | + |
3943 | +Returns position reached, if any, nil otherwise. |
3944 | + |
3945 | +Referring python program structures see for example: |
3946 | +http://docs.python.org/reference/compound_stmts.html" |
3947 | + (interactive "P\\np") |
3948 | + (let* ((regexp (if arg |
3949 | + py-block-re |
3950 | + py-block-or-clause-re)) |
3951 | + (erg (ignore-errors (cdr (py-go-to-keyword regexp -1))))) |
3952 | + (when (interactive-p) (message "%s" erg)) |
3953 | + erg)) |
3954 | + |
3955 | +(defalias 'py-forward-block-or-clause 'py-end-of-block-or-clause) |
3956 | +(defalias 'py-goto-beyond-block-or-clause 'py-end-of-block-or-clause) |
3957 | +(defun py-end-of-block-or-clause (&optional arg) |
3958 | + "Without arg, go to the end of a compound statement. |
3959 | +With arg , move point to end of clause at point. |
3960 | + |
3961 | +Returns position reached, if any, nil otherwise. |
3962 | + |
3963 | +Referring python program structures see for example: |
3964 | +http://docs.python.org/reference/compound_stmts.html" |
3965 | + (interactive "P") |
3966 | + (let ((regexp (if arg |
3967 | + py-block-re |
3968 | + py-block-or-clause-re)) |
3969 | + (orig (point))) |
3970 | + (py-end-base regexp orig (interactive-p)))) |
3971 | + |
3972 | +;; Def |
3973 | +(defun py-beginning-of-def (&optional class) |
3974 | + "Move point to start of `def'. |
3975 | +Returns position reached, if any, nil otherwise." |
3976 | + (interactive "P") |
3977 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-def-re -1))))) |
3978 | + (when (interactive-p) (message "%s" erg)) |
3979 | + erg)) |
3980 | + |
3981 | +(defun py-end-of-def (&optional iact) |
3982 | + "Move point beyond next method definition. |
3983 | + |
3984 | +Returns position reached, if any, nil otherwise." |
3985 | + (interactive "p") |
3986 | + (let* ((orig (point)) |
3987 | + (regexp py-def-re)) |
3988 | + (py-end-base regexp orig iact))) |
3989 | + |
3990 | +;; Class |
3991 | +(defalias 'py-backward-class 'py-beginning-of-class) |
3992 | +(defalias 'py-previous-class 'py-beginning-of-class) |
3993 | +(defun py-beginning-of-class () |
3994 | + "Move point to start of next `class'. |
3995 | +See also `py-beginning-of-def-or-class'. |
3996 | +Returns position reached, if any, nil otherwise." |
3997 | + (interactive) |
3998 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-class-re -1))))) |
3999 | + (when (interactive-p) (message "%s" erg)) |
4000 | + erg)) |
4001 | + |
4002 | +(defalias 'py-forward-class 'py-end-of-class) |
4003 | +(defalias 'py-next-class 'py-end-of-class) |
4004 | +(defun py-end-of-class (&optional iact) |
4005 | + "Move point beyond next method definition. |
4006 | + |
4007 | +Returns position reached, if any, nil otherwise." |
4008 | + (interactive "p") |
4009 | + (let ((orig (point)) |
4010 | + (regexp py-class-re)) |
4011 | + (py-end-base regexp orig iact))) |
4012 | + |
4013 | +;; Clause |
4014 | +(defalias 'py-previous-clause 'py-beginning-of-clause) |
4015 | +(defalias 'py-goto-clause-up 'py-beginning-of-clause) |
4016 | +(defalias 'py-backward-clause 'py-beginning-of-clause) |
4017 | +(defun py-beginning-of-clause () |
4018 | + "Looks up for nearest opening clause, i.e. a compound statements |
4019 | +subform. |
4020 | +Returns position reached, if any, nil otherwise. |
4021 | + |
4022 | +Referring python program structures see for example: |
4023 | +http://docs.python.org/reference/compound_stmts.html" |
4024 | + (interactive "p") |
4025 | + (let ((erg (ignore-errors (cdr (py-go-to-keyword py-clause-re -1))))) |
4026 | + (when (interactive-p) (message "%s" erg)) |
4027 | + erg)) |
4028 | + |
4029 | +(defalias 'py-forward-clause 'py-end-of-clause) |
4030 | +(defalias 'py-goto-beyond-clause 'py-end-of-clause) |
4031 | +(defun py-end-of-clause () |
4032 | + "Without arg, go to the end of a compound statement. |
4033 | +With arg , move point to end of clause at point. |
4034 | + |
4035 | +Returns position reached, if any, nil otherwise. |
4036 | + |
4037 | +Referring python program structures see for example: |
4038 | +http://docs.python.org/reference/compound_stmts.html" |
4039 | + (interactive) |
4040 | + (let ((regexp py-block-or-clause-re) |
4041 | + (orig (point))) |
4042 | + (py-end-base regexp orig (interactive-p)))) |
4043 | + |
4044 | +;; Defun or Class |
4045 | +(defalias 'py-backward-def-or-class 'py-beginning-of-def-or-class) |
4046 | +(defalias 'py-previous-def-or-class 'py-beginning-of-def-or-class) |
4047 | +(defun py-beginning-of-def-or-class (&optional class) |
4048 | + "Move point to start of `def' or `class', whatever is next. |
4049 | +With optional CLASS, move to the beginn of class definition. |
4050 | +Returns position reached, if any, nil otherwise. " |
4051 | + (interactive "P") |
4052 | + (let* ((regexp (if class |
4053 | + py-class-re |
4054 | + py-def-or-class-re)) |
4055 | + (erg (ignore-errors (cdr (py-go-to-keyword regexp -1))))) |
4056 | + (when (interactive-p) (message "%s" erg)) |
4057 | + erg)) |
4058 | + |
4059 | +(defalias 'end-of-def-or-class 'py-end-of-def-or-class) |
4060 | +(defalias 'py-forward-def-or-class 'py-end-of-def-or-class) |
4061 | +(defalias 'py-next-def-or-class 'py-end-of-def-or-class) |
4062 | +(defun py-end-of-def-or-class (&optional class) |
4063 | + "Move point beyond next `def' or `class' definition. |
4064 | +With optional CLASS, move to the end of class exclusively. |
4065 | +Returns position reached, if any, nil otherwise." |
4066 | + (interactive "P") |
4067 | + (let* ((orig (point)) |
4068 | + (regexp |
4069 | + (cond (class py-class-re) |
4070 | + (t py-def-or-class-re)))) |
4071 | + (py-end-base regexp orig (interactive-p)))) |
4072 | + |
4073 | +(defun py-travel-current-indent (listing) |
4074 | + "Moves down until clause is closed, i.e. current indentation is reached. |
4075 | + |
4076 | +Takes a list, INDENT and START position. " |
4077 | + (let ((start (ignore-errors (cdr listing))) |
4078 | + (indent (ignore-errors (car listing))) |
4079 | + last) |
4080 | + (if start |
4081 | + (progn |
4082 | + (goto-char start) |
4083 | + (while (and (not (eobp))(setq last (point))(py-end-of-statement) |
4084 | + (ignore-errors (<= indent (current-indentation))))) |
4085 | + (when last (goto-char last)) |
4086 | + last)))) |
4087 | + |
4088 | +(defun py-go-to-keyword (regexp arg) |
4089 | + "Returns a list, whose car is indentation, cdr position. " |
4090 | + (lexical-let ((orig (point)) |
4091 | + (stop (if (< 0 arg)'(eobp)'(bobp))) |
4092 | + (function (if (< 0 arg) 'py-end-of-statement 'py-beginning-of-statement)) |
4093 | + erg) |
4094 | + (setq erg (funcall function)) |
4095 | + (while (and (not (eval stop))(not (setq erg (py-statement-opens-block-p regexp)))) |
4096 | + (funcall function)) |
4097 | + (when erg (setq erg (cons (current-indentation) erg))) |
4098 | + erg)) |
4099 | + |
4100 | +(defun py-end-base (regexp orig iact) |
4101 | + "Used internal by functions going to the end forms. " |
4102 | + (let (erg) |
4103 | + (unless (py-statement-opens-block-p regexp) |
4104 | + (py-go-to-keyword regexp -1)) |
4105 | + (when (py-statement-opens-block-p regexp) |
4106 | + (setq erg (point)) |
4107 | + (forward-line 1) |
4108 | + (setq erg (py-travel-current-indent (cons (current-indentation) (point)))) |
4109 | + (if (eq orig (point)) |
4110 | (progn |
4111 | - (if (looking-at "[ \t]*$") ; it's blank |
4112 | - (setq start (point)) ; so reset start point |
4113 | - (goto-char start)) ; else try again |
4114 | - (if (zerop (forward-line -1)) |
4115 | - (if (looking-at "[ \t]*#") ; a comment |
4116 | - ;; look back for non-comment line |
4117 | - ;; tricky: note that the regexp matches a blank |
4118 | - ;; line, cuz \n is in the 2nd character class |
4119 | - (and |
4120 | - (re-search-backward "^[ \t]*[^ \t#]" nil 'move) |
4121 | - (forward-line 1)) |
4122 | - ;; no comment, so go back |
4123 | - (goto-char start))))))) |
4124 | - (exchange-point-and-mark) |
4125 | - (py-keep-region-active)) |
4126 | + (while (not (or |
4127 | + (eobp) |
4128 | + (and (setq erg (re-search-forward regexp nil (quote move) 1)) |
4129 | + (not (py-in-string-or-comment-p)) |
4130 | + (not (py-in-list-p)))))) |
4131 | + (unless (eobp)(py-end-base regexp orig iact))) |
4132 | + (when (and (< orig (point))(not (eobp))) |
4133 | + (setq erg (point)))) |
4134 | + (when iact (message "%s" erg)) |
4135 | + erg))) |
4136 | |
4137 | ;; ripped from cc-mode |
4138 | (defun py-forward-into-nomenclature (&optional arg) |
4139 | @@ -3196,6 +2938,319 @@ |
4140 | (py-forward-into-nomenclature (- arg)) |
4141 | (py-keep-region-active)) |
4142 | |
4143 | +(defun py-in-statement-p () |
4144 | + "Returns list of beginning and end-position if inside. |
4145 | +Result is useful for booleans too: (when (py-in-statement-p)...) |
4146 | +will work. |
4147 | +" |
4148 | + (interactive) |
4149 | + (let ((orig (point)) |
4150 | + beg end erg) |
4151 | + (save-excursion |
4152 | + (setq end (py-end-of-statement)) |
4153 | + (setq beg (py-beginning-of-statement)) |
4154 | + (when (and (<= beg orig)(<= orig end)) |
4155 | + (setq erg (cons beg end)) |
4156 | + (when (interactive-p) (message "%s" erg)) |
4157 | + erg)))) |
4158 | + |
4159 | +(defun py-beginning-of-statement-p () |
4160 | + (interactive) |
4161 | + "Returns position, if cursor is at the beginning of a statement, nil otherwise. " |
4162 | + (let ((orig (point))) |
4163 | + (save-excursion |
4164 | + (py-end-of-statement) |
4165 | + (py-beginning-of-statement) |
4166 | + (when (or (eq orig (point)) (and (looking-back "^[ \t]+") (<= (line-beginning-position) orig)(<= orig (point)))) |
4167 | + (when (interactive-p) |
4168 | + (message "%s" orig)) |
4169 | + orig)))) |
4170 | + |
4171 | +(defalias 'py-beginning-of-block-p 'py-statement-opens-block-p) |
4172 | +(defun py-statement-opens-block-p (&optional regexp) |
4173 | + (interactive) |
4174 | + "Return position if the current statement opens a block |
4175 | +in stricter or wider sense. |
4176 | +For stricter sense specify regexp. " |
4177 | + (let* ((regexp (or regexp py-block-re)) |
4178 | + (erg (py-statement-opens-base regexp))) |
4179 | + (when (interactive-p) (message "%s" erg)) |
4180 | + erg)) |
4181 | + |
4182 | +(defalias 'py-beginning-of-clause-p 'py-statement-opens-clause-p) |
4183 | +(defun py-statement-opens-clause-p () |
4184 | + "Return position if the current statement opens block or clause. " |
4185 | + (interactive) |
4186 | + (py-statement-opens-base py-clause-re)) |
4187 | + |
4188 | +(defun py-statement-opens-base (regexp) |
4189 | + (let ((orig (point)) |
4190 | + erg) |
4191 | + (save-excursion |
4192 | + (back-to-indentation) |
4193 | + (py-end-of-statement) |
4194 | + (py-beginning-of-statement) |
4195 | + (when (and |
4196 | + (looking-back "^[ \t]*") (<= (line-beginning-position)(point))(looking-at regexp)) |
4197 | + (setq erg (point)))) |
4198 | + (when (interactive-p) (message "%s" erg)) |
4199 | + erg)) |
4200 | + |
4201 | +(defalias 'py-beginning-of-block-or-clause-p 'py-statement-opens-block-or-clause-p) |
4202 | +(defun py-statement-opens-block-or-clause-p () |
4203 | + "Return position if the current statement opens block or clause. " |
4204 | + (interactive) |
4205 | + (py-statement-opens-base py-block-or-clause-re)) |
4206 | + |
4207 | + |
4208 | +(defalias 'py-beginning-of-class-p 'py-statement-opens-class-p) |
4209 | +(defun py-statement-opens-class-p () |
4210 | + "Return `t' if the statement opens a functions or class definition, nil otherwise. " |
4211 | + (interactive) |
4212 | + (py-statement-opens-base py-class-re)) |
4213 | + |
4214 | +(defalias 'py-beginning-of-def-p 'py-statement-opens-def-p) |
4215 | +(defun py-statement-opens-def-p () |
4216 | + "Return `t' if the statement opens a functions or class definition, nil otherwise. " |
4217 | + (interactive) |
4218 | + (py-statement-opens-base py-def-re)) |
4219 | + |
4220 | +(defalias 'py-beginning-of-def-or-class-p 'py-statement-opens-def-or-class-p) |
4221 | +(defun py-statement-opens-def-or-class-p () |
4222 | + "Return `t' if the statement opens a functions or class definition, nil otherwise. " |
4223 | + (interactive) |
4224 | + (py-statement-opens-base py-def-or-class-re)) |
4225 | + |
4226 | +;; Mark forms |
4227 | +(defun py-mark-expression () |
4228 | + "Mark expression around point. |
4229 | + Returns beginning and end positions of marked area, a cons. " |
4230 | + (interactive) |
4231 | + (py-mark-base "expression") |
4232 | + (exchange-point-and-mark)) |
4233 | + |
4234 | +(defun py-mark-partial-expression () |
4235 | + "Mark partial-expression around point. |
4236 | + Returns beginning and end positions of marked area, a cons. " |
4237 | + (interactive) |
4238 | + (py-mark-base "partial-expression") |
4239 | + (exchange-point-and-mark)) |
4240 | + |
4241 | +(defun py-mark-statement () |
4242 | + "Mark statement around point. |
4243 | + Returns beginning and end positions of marked area, a cons. " |
4244 | + (interactive) |
4245 | + (py-mark-base "statement") |
4246 | + (exchange-point-and-mark)) |
4247 | + |
4248 | +(defun py-mark-block () |
4249 | + "Mark block around point. |
4250 | + Returns beginning and end positions of marked area, a cons. " |
4251 | + (interactive) |
4252 | + (py-mark-base "block") |
4253 | + (exchange-point-and-mark)) |
4254 | + |
4255 | +(defun py-mark-block-or-clause () |
4256 | + "Mark block-or-clause around point. |
4257 | + Returns beginning and end positions of marked area, a cons. " |
4258 | + (interactive) |
4259 | + (py-mark-base "block-or-clause") |
4260 | + (exchange-point-and-mark)) |
4261 | + |
4262 | +(defun py-mark-def (&optional arg) |
4263 | + "Mark def around point. |
4264 | + |
4265 | +With universal argument or `py-mark-decorators' set to `t' decorators are marked too. |
4266 | +Returns beginning and end positions of marked area, a cons." |
4267 | + |
4268 | + (interactive "P") |
4269 | + (let ((py-mark-decorators (or arg py-mark-decorators))) |
4270 | + (py-mark-base "def" py-mark-decorators) |
4271 | + (exchange-point-and-mark))) |
4272 | + |
4273 | +(defun py-mark-def-or-class (&optional arg) |
4274 | + "Mark def-or-class around point. |
4275 | + |
4276 | +With universal argument or `py-mark-decorators' set to `t' decorators are marked too. |
4277 | +Returns beginning and end positions of marked area, a cons." |
4278 | + (interactive "P") |
4279 | + (let ((py-mark-decorators (or arg py-mark-decorators))) |
4280 | + (py-mark-base "def-or-class" py-mark-decorators) |
4281 | + (exchange-point-and-mark))) |
4282 | + |
4283 | +(defun py-mark-class (&optional arg) |
4284 | + "Mark class around point. |
4285 | + |
4286 | +With universal argument or `py-mark-decorators' set to `t' decorators are marked too. |
4287 | +Returns beginning and end positions of marked area, a cons." |
4288 | + |
4289 | + (interactive "P") |
4290 | + (let ((py-mark-decorators (or arg py-mark-decorators))) |
4291 | + (py-mark-base "class" py-mark-decorators) |
4292 | + (exchange-point-and-mark))) |
4293 | + |
4294 | +(defun py-mark-clause () |
4295 | + "Mark clause around point. |
4296 | + Returns beginning and end positions of marked area, a cons. " |
4297 | + (interactive) |
4298 | + (py-mark-base "clause") |
4299 | + (exchange-point-and-mark)) |
4300 | + |
4301 | +(defun py-mark-base (form &optional py-mark-decorators) |
4302 | + (let* ((begform (intern-soft (concat "py-beginning-of-" form))) |
4303 | + (endform (intern-soft (concat "py-end-of-" form))) |
4304 | + (begcheckform (intern-soft (concat "py-beginning-of-" form "-p"))) |
4305 | + (orig (point)) |
4306 | + beg end) |
4307 | + (setq beg (if |
4308 | + (setq beg (funcall begcheckform)) |
4309 | + beg |
4310 | + (funcall begform))) |
4311 | + (when py-mark-decorators |
4312 | + (save-excursion |
4313 | + (forward-line -1) |
4314 | + (back-to-indentation) |
4315 | + (when (looking-at "@\\w+") |
4316 | + (setq beg (match-beginning 0))))) |
4317 | + (setq end (funcall endform)) |
4318 | + (progn |
4319 | + (push-mark beg t t) |
4320 | + (goto-char end)) |
4321 | + (when (interactive-p) (message "%s %s" beg end)) |
4322 | + (cons beg end))) |
4323 | + |
4324 | +;; Copying |
4325 | +(defun py-copy-expression () |
4326 | + "Mark expression around point. |
4327 | + Returns beginning and end positions of marked area, a cons. " |
4328 | + (interactive) |
4329 | + (let ((erg (py-mark-base "expression"))) |
4330 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4331 | + |
4332 | +(defun py-copy-partial-expression () |
4333 | + "Mark partial-expression around point. |
4334 | + Returns beginning and end positions of marked area, a cons. " |
4335 | + (interactive) |
4336 | + (let ((erg (py-mark-base "partial-expression"))) |
4337 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4338 | + |
4339 | +(defun py-copy-statement () |
4340 | + "Mark statement around point. |
4341 | + Returns beginning and end positions of marked area, a cons. " |
4342 | + (interactive) |
4343 | + (let ((erg (py-mark-base "statement"))) |
4344 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4345 | + |
4346 | +(defun py-copy-block () |
4347 | + "Mark block around point. |
4348 | + Returns beginning and end positions of marked area, a cons. " |
4349 | + (interactive) |
4350 | + (let ((erg (py-mark-base "block"))) |
4351 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4352 | + |
4353 | +(defun py-copy-block-or-clause () |
4354 | + "Mark block-or-clause around point. |
4355 | + Returns beginning and end positions of marked area, a cons. " |
4356 | + (interactive) |
4357 | + (let ((erg (py-mark-base "block-or-clause"))) |
4358 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4359 | + |
4360 | +(defun py-copy-def (&optional arg) |
4361 | + "Mark def around point. |
4362 | + |
4363 | +With universal argument or `py-mark-decorators' set to `t' decorators are copied too. |
4364 | +Returns beginning and end positions of marked area, a cons." |
4365 | + |
4366 | + (interactive "P") |
4367 | + (let ((py-mark-decorators (or arg py-mark-decorators)) |
4368 | + (erg (py-mark-base "def" py-mark-decorators))) |
4369 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4370 | + |
4371 | +(defun py-copy-def-or-class (&optional arg) |
4372 | + "Mark def-or-class around point. |
4373 | + |
4374 | +With universal argument or `py-mark-decorators' set to `t' decorators are copied too. |
4375 | +Returns beginning and end positions of marked area, a cons." |
4376 | + (interactive "P") |
4377 | + (let ((py-mark-decorators (or arg py-mark-decorators)) |
4378 | + (erg (py-mark-base "def-or-class" py-mark-decorators))) |
4379 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4380 | + |
4381 | +(defun py-copy-class (&optional arg) |
4382 | + "Mark class around point. |
4383 | + |
4384 | +With universal argument or `py-mark-decorators' set to `t' decorators are copied too. |
4385 | +Returns beginning and end positions of marked area, a cons." |
4386 | + |
4387 | + (interactive "P") |
4388 | + (let ((py-mark-decorators (or arg py-mark-decorators)) |
4389 | + (erg (py-mark-base "class" py-mark-decorators))) |
4390 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4391 | + |
4392 | +(defun py-copy-clause () |
4393 | + "Mark clause around point. |
4394 | + Returns beginning and end positions of marked area, a cons. " |
4395 | + (interactive) |
4396 | + (let ((erg (py-mark-base "clause"))) |
4397 | + (kill-new (buffer-substring-no-properties (car erg) (cdr erg))))) |
4398 | + |
4399 | + |
4400 | +;; Deleting |
4401 | +(defun py-kill-expression () |
4402 | + "Delete expression around point. |
4403 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4404 | + (interactive) |
4405 | + (let ((erg (py-mark-base "expression"))) |
4406 | + (kill-region (car erg) (cdr erg)))) |
4407 | + |
4408 | +(defun py-kill-partial-expression () |
4409 | + "Delete partial-expression around point. |
4410 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4411 | + (interactive) |
4412 | + (let ((erg (py-mark-base "partial-expression"))) |
4413 | + (kill-region (car erg) (cdr erg)))) |
4414 | + |
4415 | +(defun py-kill-statement () |
4416 | + "Delete statement around point. |
4417 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4418 | + (interactive) |
4419 | + (let ((erg (py-mark-base "statement"))) |
4420 | + (kill-region (car erg) (cdr erg)))) |
4421 | + |
4422 | +(defun py-kill-block () |
4423 | + "Delete block around point. |
4424 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4425 | + (interactive) |
4426 | + (let ((erg (py-mark-base "block"))) |
4427 | + (kill-region (car erg) (cdr erg)))) |
4428 | + |
4429 | +(defun py-kill-block-or-clause () |
4430 | + "Delete block-or-clause around point. |
4431 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4432 | + (interactive) |
4433 | + (let ((erg (py-mark-base "block-or-clause"))) |
4434 | + (kill-region (region-beginning) (region-end)))) |
4435 | + |
4436 | +(defun py-kill-def-or-class () |
4437 | + "Delete def-or-class around point. |
4438 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4439 | + (interactive) |
4440 | + (let ((erg (py-mark-base "def-or-class"))) |
4441 | + (kill-region (car erg) (cdr erg)))) |
4442 | + |
4443 | +(defun py-kill-class () |
4444 | + "Delete class around point. |
4445 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4446 | + (interactive) |
4447 | + (let ((erg (py-mark-base "class"))) |
4448 | + (kill-region (car erg) (cdr erg)))) |
4449 | + |
4450 | +(defun py-kill-clause () |
4451 | + "Delete clause around point. |
4452 | + Stores data in kill ring. Might be yanked back using `C-y'. " |
4453 | + (interactive) |
4454 | + (let ((erg (py-mark-base "clause"))) |
4455 | + (kill-region (car erg) (cdr erg)))) |
4456 | |
4457 | |
4458 | |
4459 | ;; pdbtrack functions |
4460 | @@ -3219,7 +3274,6 @@ |
4461 | (interactive) |
4462 | (py-pdbtrack-toggle-stack-tracking 0)) |
4463 | |
4464 | - |
4465 | |
4466 | |
4467 | ;; Pychecker |
4468 | |
4469 | @@ -3262,36 +3316,12 @@ |
4470 | (compile-internal command "No more errors")))) |
4471 | |
4472 | |
4473 | |
4474 | -;; pydoc commands. The guts of this function is stolen from XEmacs's |
4475 | -;; symbol-near-point, but without the useless regexp-quote call on the |
4476 | -;; results, nor the interactive bit. Also, we've added the temporary |
4477 | -;; syntax table setting, which Skip originally had broken out into a |
4478 | -;; separate function. Note that Emacs doesn't have the original |
4479 | -;; function. |
4480 | -(defun py-symbol-near-point () |
4481 | - "Return the first textual item to the nearest point." |
4482 | - ;; alg stolen from etag.el |
4483 | - (save-excursion |
4484 | - (with-syntax-table py-dotted-expression-syntax-table |
4485 | - (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_)))) |
4486 | - (while (not (looking-at "\\sw\\|\\s_\\|\\'")) |
4487 | - (forward-char 1))) |
4488 | - (while (looking-at "\\sw\\|\\s_") |
4489 | - (forward-char 1)) |
4490 | - (if (re-search-backward "\\sw\\|\\s_" nil t) |
4491 | - (progn (forward-char 1) |
4492 | - (buffer-substring (point) |
4493 | - (progn (forward-sexp -1) |
4494 | - (while (looking-at "\\s'") |
4495 | - (forward-char 1)) |
4496 | - (point)))) |
4497 | - nil)))) |
4498 | - |
4499 | +(defalias 'py-describe-symbol 'py-help-at-point) |
4500 | (defun py-help-at-point () |
4501 | "Get help from Python based on the symbol nearest point." |
4502 | (interactive) |
4503 | - (let* ((sym (py-symbol-near-point)) |
4504 | - (base (substring sym 0 (or (search "." sym :from-end t) 0))) |
4505 | + (let* ((sym (prin1-to-string (symbol-at-point))) |
4506 | + (base (substring sym 0 (or (string-match "\\." sym) 0))) |
4507 | cmd) |
4508 | (if (not (equal base "")) |
4509 | (setq cmd (concat "import " base "\n"))) |
4510 | @@ -3305,7 +3335,6 @@ |
4511 | ;; BAW: Should we really be leaving the output buffer in help-mode? |
4512 | (help-mode))) |
4513 | |
4514 | - |
4515 | |
4516 | |
4517 | ;; Documentation functions |
4518 | |
4519 | @@ -3353,7 +3382,7 @@ |
4520 | (terpri) |
4521 | (setq start end)) |
4522 | (princ (substitute-command-keys (substring str start)))) |
4523 | - (print-help-return-message))) |
4524 | + (help-print-return-message))) |
4525 | |
4526 | (defun py-describe-mode () |
4527 | "Dump long form of Python-mode docs." |
4528 | @@ -3445,7 +3474,6 @@ |
4529 | statement containing point, even if point happens to be in the middle |
4530 | of some continuation line. |
4531 | |
4532 | - |
4533 | @INDENTATION |
4534 | |
4535 | Primarily for entering new code: |
4536 | @@ -3521,11 +3549,9 @@ |
4537 | %c:py-newline-and-indent |
4538 | %c:py-electric-backspace |
4539 | |
4540 | - |
4541 | The next function may be handy when editing code you didn't write: |
4542 | %c:py-guess-indent-offset |
4543 | |
4544 | - |
4545 | The remaining `indent' functions apply to a region of Python code. They |
4546 | assume the block structure (equals indentation, in Python) of the region |
4547 | is correct, and alter the indentation in various ways while preserving |
4548 | @@ -3620,6 +3646,72 @@ |
4549 | |
4550 | |
4551 | |
4552 | ;; Helper functions |
4553 | +(when (featurep 'xemacs) |
4554 | + (unless (functionp 'looking-back) |
4555 | + ;; from GNU Emacs subr.el |
4556 | + (defun looking-back (regexp &optional limit greedy) |
4557 | + "Return non-nil if text before point matches regular expression REGEXP. |
4558 | + Like `looking-at' except matches before point, and is slower. |
4559 | + LIMIT if non-nil speeds up the search by specifying a minimum |
4560 | + starting position, to avoid checking matches that would start |
4561 | + before LIMIT. |
4562 | + If GREEDY is non-nil, extend the match backwards as far as possible, |
4563 | + stopping when a single additional previous character cannot be part |
4564 | + of a match for REGEXP." |
4565 | + (let ((start (point)) |
4566 | + (pos |
4567 | + (save-excursion |
4568 | + (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t) |
4569 | + (point))))) |
4570 | + (if (and greedy pos) |
4571 | + (save-restriction |
4572 | + (narrow-to-region (point-min) start) |
4573 | + (while (and (> pos (point-min)) |
4574 | + (save-excursion |
4575 | + (goto-char pos) |
4576 | + (backward-char 1) |
4577 | + (looking-at (concat "\\(?:" regexp "\\)\\'")))) |
4578 | + (setq pos (1- pos))) |
4579 | + (save-excursion |
4580 | + (goto-char pos) |
4581 | + (looking-at (concat "\\(?:" regexp "\\)\\'"))))) |
4582 | + (not (null pos)))))) |
4583 | + |
4584 | +(defun py-count-lines (&optional start end) |
4585 | + "Count lines in accessible part of buffer. |
4586 | + |
4587 | +If no optional position arguments are given but region is active, |
4588 | +use the region. |
4589 | +Else count from point-min until curser position - (point) |
4590 | + |
4591 | +See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7115" |
4592 | + (interactive) |
4593 | + (lexical-let ((beg (cond (start) |
4594 | + ((region-active-p) |
4595 | + (region-beginning)) |
4596 | + (t (point-min)))) |
4597 | + (end (cond (end) |
4598 | + ((region-active-p) |
4599 | + (copy-marker (region-end))) |
4600 | + (t (point)))) |
4601 | + erg) |
4602 | + (if (featurep 'xemacs) |
4603 | + (setq erg (count-lines beg end)) |
4604 | + (setq erg (1+ (count-matches "[\n\C-m]" beg end)))) |
4605 | + (when (interactive-p) (message "%s" erg)) |
4606 | + erg)) |
4607 | + |
4608 | +(defun py-forward-line (&optional arg) |
4609 | + "Goes to end of line after forward move. |
4610 | +Travels right-margin comments. " |
4611 | + (interactive "p") |
4612 | + (let ((arg (or arg 1))) |
4613 | + (forward-line arg) |
4614 | + (end-of-line) |
4615 | + (skip-chars-backward " \t") |
4616 | + (py-beginning-of-comment) |
4617 | + (skip-chars-backward " \t"))) |
4618 | + |
4619 | (defvar py-parse-state-re |
4620 | (concat |
4621 | "^[ \t]*\\(elif\\|else\\|while\\|def\\|class\\)\\>" |
4622 | @@ -3684,132 +3776,15 @@ |
4623 | (or (py-backslash-continuation-preceding-line-p) |
4624 | (py-nesting-level)))) |
4625 | |
4626 | -(defun py-goto-beginning-of-tqs (delim) |
4627 | - "Go to the beginning of a triple quoted string at point. |
4628 | -DELIM is the result of \"(nth 3 (parse-partial-sexp...\", i.e. the |
4629 | - character that will terminate the string, or `t' if the string |
4630 | - is terminated by a generic string delimiter. |
4631 | -If syntax-table is set correctly, the latter should be the case. " |
4632 | - (if (numberp delim) |
4633 | - (let ((skip (and delim (make-string 1 delim))) |
4634 | - (continue t)) |
4635 | - (when skip |
4636 | - (save-excursion |
4637 | - (while continue |
4638 | - (ignore-errors (search-backward skip)) |
4639 | - (setq continue (and (not (bobp)) |
4640 | - (= (char-before) ?\\)))) |
4641 | - (if (and (= (char-before) delim) |
4642 | - (= (char-before (1- (point))) delim)) |
4643 | - (setq skip (make-string 3 delim)))) |
4644 | - ;; we're looking at a triple-quoted string |
4645 | - (ignore-errors (search-backward skip)))) |
4646 | - (when |
4647 | - (skip-syntax-backward "^|") |
4648 | - (forward-char 1)))) |
4649 | - |
4650 | -(defun py-goto-initial-line () |
4651 | - "Go to the initial line of a simple or compound statement. |
4652 | -If inside a compound statement, go to the line that introduces |
4653 | -the suite, i.e. the clause header. |
4654 | - |
4655 | -The Python language reference: |
4656 | - |
4657 | - \"Compound statements consist of one or more ‘clauses.’ A clause consists |
4658 | - of a header and a ‘suite.’ The clause headers of a particular compound |
4659 | - statement are all at the same indentation level. Each clause header begins |
4660 | - with a uniquely identifying keyword and ends with a colon. A suite is a |
4661 | - group of statements controlled by a clause. A suite can be one or more |
4662 | - semicolon-separated simple statements on the same line as the header, |
4663 | - following the header’s colon, or it can be one or more indented statements |
4664 | - on subsequent lines. [...]\" |
4665 | - |
4666 | -See: http://docs.python.org/reference/compound_stmts.html |
4667 | -" |
4668 | - ;; Tricky: We want to avoid quadratic-time behavior for long |
4669 | - ;; continued blocks, whether of the backslash or open-bracket |
4670 | - ;; varieties, or a mix of the two. The following manages to do that |
4671 | - ;; in the usual cases. |
4672 | - ;; |
4673 | - ;; Also, if we're sitting inside a triple quoted string, this will |
4674 | - ;; drop us at the line that begins the string. |
4675 | - (let (open-bracket-pos pos) |
4676 | - (while (py-continuation-line-p) |
4677 | - (beginning-of-line) |
4678 | - (if (py-backslash-continuation-preceding-line-p) |
4679 | - (while (py-backslash-continuation-preceding-line-p) |
4680 | - (forward-line -1)) |
4681 | - ;; else zip out of nested brackets/braces/parens |
4682 | - (while (setq open-bracket-pos (py-nesting-level)) |
4683 | - (goto-char open-bracket-pos)))) |
4684 | - (if (and (setq pos (python-in-string/comment)) |
4685 | - (< pos (point))) |
4686 | - (progn |
4687 | - (goto-char pos) |
4688 | - (py-goto-initial-line)) |
4689 | - (beginning-of-line) |
4690 | - (when |
4691 | - (and (setq pos (python-in-string/comment)) |
4692 | - (< pos (point))) |
4693 | - (goto-char pos) |
4694 | - (py-goto-initial-line))))) |
4695 | - |
4696 | -(defun py-goto-beyond-final-line () |
4697 | - "Go to the point just beyond the final line of the current statement. " |
4698 | - |
4699 | - ;; Tricky: Again we need to be clever to avoid quadratic time |
4700 | - ;; behavior. |
4701 | - ;; |
4702 | - ;; XXX: Not quite the right solution, but deals with multi-line doc |
4703 | - ;; strings |
4704 | - (if (looking-at (concat "[ \t]*\\(" py-stringlit-re "\\)")) |
4705 | - (goto-char (match-end 0))) |
4706 | - ;; |
4707 | - (forward-line 1) |
4708 | - (let (state) |
4709 | - (while (and (py-continuation-line-p) |
4710 | - (not (eobp))) |
4711 | - ;; skip over the backslash flavor |
4712 | - (while (and (py-backslash-continuation-preceding-line-p) |
4713 | - (not (eobp))) |
4714 | - (forward-line 1)) |
4715 | - ;; if in nest, zip to the end of the nest |
4716 | - (setq state (py-parse-state)) |
4717 | - (if (and (not (zerop (car state))) |
4718 | - (not (eobp))) |
4719 | - (progn |
4720 | - (parse-partial-sexp (point) (point-max) 0 nil state) |
4721 | - (forward-line 1)))))) |
4722 | - |
4723 | -(defun py-statement-opens-block-p () |
4724 | - "Return t iff the current statement opens a block. |
4725 | -I.e., iff it ends with a colon that is not in a comment. Point should |
4726 | -be at the start of a statement." |
4727 | +(defun py-backslashed-continuation-line-p () |
4728 | + (interactive) |
4729 | + "Return t if current line is a backslashed continuation line. " |
4730 | (save-excursion |
4731 | - (let ((start (point)) |
4732 | - (finish (progn (py-goto-beyond-final-line) (1- (point)))) |
4733 | - (searching t) |
4734 | - (answer nil) |
4735 | - state) |
4736 | - (goto-char start) |
4737 | - (while searching |
4738 | - ;; look for a colon with nothing after it except whitespace, and |
4739 | - ;; maybe a comment |
4740 | - (if (re-search-forward ":\\([ \t]\\|\\\\\n\\)*\\(#.*\\)?$" |
4741 | - finish t) |
4742 | - (if (eq (point) finish) ; note: no `else' clause; just |
4743 | - ; keep searching if we're not at |
4744 | - ; the end yet |
4745 | - ;; sure looks like it opens a block -- but it might |
4746 | - ;; be in a comment |
4747 | - (progn |
4748 | - (setq searching nil) ; search is done either way |
4749 | - (setq state (parse-partial-sexp start |
4750 | - (match-beginning 0))) |
4751 | - (setq answer (not (nth 4 state))))) |
4752 | - ;; search failed: couldn't find another interesting colon |
4753 | - (setq searching nil))) |
4754 | - answer))) |
4755 | + (beginning-of-line) |
4756 | + (skip-chars-backward " \t\r\n\f") |
4757 | + (let ((erg (eq (char-before (point)) ?\\ ))) |
4758 | + (when (interactive-p) (message "%s" erg)) |
4759 | + erg))) |
4760 | |
4761 | (defun py-statement-closes-block-p () |
4762 | "Return t iff the current statement closes a block. |
4763 | @@ -3823,135 +3798,43 @@ |
4764 | (goto-char here)))) |
4765 | |
4766 | (defun py-goto-beyond-block () |
4767 | - "Go to point just beyond the final line of block begun by the current line. |
4768 | -This is the same as where `py-goto-beyond-final-line' goes unless |
4769 | -we're on colon line, in which case we go to the end of the block. |
4770 | -Assumes point is at the beginning of the line." |
4771 | - (if (py-statement-opens-block-p) |
4772 | - (py-mark-block nil 'just-move) |
4773 | - (py-goto-beyond-final-line))) |
4774 | - |
4775 | -(defun py-goto-statement-at-or-above () |
4776 | - "Go to the start of the first statement at or preceding point. |
4777 | -Return t if there is such a statement, otherwise nil. `Statement' |
4778 | -does not include blank lines, comments, or continuation lines." |
4779 | - (py-goto-initial-line) |
4780 | - (if (looking-at py-blank-or-comment-re) |
4781 | - ;; skip back over blank & comment lines |
4782 | - ;; note: will skip a blank or comment line that happens to be |
4783 | - ;; a continuation line too |
4784 | - (if (re-search-backward "^[ \t]*[^ \t#\n]" nil t) |
4785 | - (progn (py-goto-initial-line) t) |
4786 | - nil) |
4787 | - t)) |
4788 | - |
4789 | -(defun py-goto-statement-below () |
4790 | - "Go to start of the first statement following the statement containing point. |
4791 | -Return t if there is such a statement, otherwise nil. " |
4792 | - (beginning-of-line) |
4793 | - (let ((start (point))) |
4794 | - (py-goto-beyond-final-line) |
4795 | - (while (and |
4796 | - (or (looking-at py-blank-or-comment-re) |
4797 | - (py-in-literal)) |
4798 | - (not (eobp))) |
4799 | - (forward-line 1)) |
4800 | - (if (eobp) |
4801 | - (progn (goto-char start) nil) |
4802 | - t))) |
4803 | - |
4804 | -(defun py-go-up-tree-to-keyword (key) |
4805 | - "Go to begining of statement starting with KEY, at or preceding point. |
4806 | - |
4807 | -KEY is a regular expression describing a Python keyword. Skip blank |
4808 | -lines and non-indenting comments. If the statement found starts with |
4809 | -KEY, then stop, otherwise go back to first enclosing block starting |
4810 | -with KEY. If successful, leave point at the start of the KEY line and |
4811 | -return t. Otherwise, leave point at an undefined place and return nil." |
4812 | - ;; skip blanks and non-indenting # |
4813 | - (py-goto-initial-line) |
4814 | - (while (and |
4815 | - (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") |
4816 | - (zerop (forward-line -1))) ; go back |
4817 | - nil) |
4818 | - (py-goto-initial-line) |
4819 | - (let* ((re (concat "[ \t]*" key "\\>")) |
4820 | - (case-fold-search nil) ; let* so looking-at sees this |
4821 | - (found (looking-at re)) |
4822 | - (dead nil)) |
4823 | - (while (not (or found dead)) |
4824 | - (condition-case nil ; in case no enclosing block |
4825 | - (py-goto-block-up 'no-mark) |
4826 | - (error (setq dead t))) |
4827 | - (or dead (setq found (looking-at re)))) |
4828 | - (beginning-of-line) |
4829 | - found)) |
4830 | - |
4831 | -(defun py-suck-up-leading-text () |
4832 | - "Return string in buffer from start of indentation to end of line. |
4833 | -Prefix with \"...\" if leading whitespace was skipped." |
4834 | - (save-excursion |
4835 | - (back-to-indentation) |
4836 | - (concat |
4837 | - (if (bolp) "" "...") |
4838 | - (buffer-substring (point) (progn (end-of-line) (point)))))) |
4839 | - |
4840 | -(defun py-suck-up-first-keyword () |
4841 | - "Return first keyword on the line as a Lisp symbol. |
4842 | -`Keyword' is defined (essentially) as the regular expression |
4843 | -([a-z]+). Returns nil if none was found." |
4844 | - (let ((case-fold-search nil)) |
4845 | - (if (looking-at "[ \t]*\\([a-z]+\\)\\>") |
4846 | - (intern (buffer-substring (match-beginning 1) (match-end 1))) |
4847 | - nil))) |
4848 | - |
4849 | -(defun py-current-defun () |
4850 | - "Python value for `add-log-current-defun-function'. |
4851 | -This tells add-log.el how to find the current function/method/variable." |
4852 | - (save-excursion |
4853 | - |
4854 | - ;; Move back to start of the current statement. |
4855 | - |
4856 | - (py-goto-initial-line) |
4857 | - (back-to-indentation) |
4858 | - (while (and (or (looking-at py-blank-or-comment-re) |
4859 | - (py-in-literal)) |
4860 | - (not (bobp))) |
4861 | - (backward-to-indentation 1)) |
4862 | - (py-goto-initial-line) |
4863 | - |
4864 | - (let ((scopes "") |
4865 | - (sep "") |
4866 | - dead assignment) |
4867 | - |
4868 | - ;; Check for an assignment. If this assignment exists inside a |
4869 | - ;; def, it will be overwritten inside the while loop. If it |
4870 | - ;; exists at top lever or inside a class, it will be preserved. |
4871 | - |
4872 | - (when (looking-at "[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*=") |
4873 | - (setq scopes (buffer-substring (match-beginning 1) (match-end 1))) |
4874 | - (setq assignment t) |
4875 | - (setq sep ".")) |
4876 | - |
4877 | - ;; Prepend the name of each outer socpe (def or class). |
4878 | - |
4879 | - (while (not dead) |
4880 | - (if (and (py-go-up-tree-to-keyword "\\(class\\|def\\)") |
4881 | - (looking-at |
4882 | - "[ \t]*\\(class\\|def\\)[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*")) |
4883 | - (let ((name (buffer-substring (match-beginning 2) (match-end 2)))) |
4884 | - (if (and assignment (looking-at "[ \t]*def")) |
4885 | - (setq scopes name) |
4886 | - (setq scopes (concat name sep scopes)) |
4887 | - (setq sep ".")))) |
4888 | - (setq assignment nil) |
4889 | - (condition-case nil ; Terminate nicely at top level. |
4890 | - (py-goto-block-up 'no-mark) |
4891 | - (error (setq dead t)))) |
4892 | - (if (string= scopes "") |
4893 | - nil |
4894 | - scopes)))) |
4895 | - |
4896 | + "Go to point just beyond the final line of block begun by the current line. " |
4897 | + (py-forward-block) |
4898 | + (forward-line 1)) |
4899 | + |
4900 | +(defun py-beginning-of-comment (&optional count) |
4901 | + "Go to the beginning of current line's comment, if any. " |
4902 | + (interactive) |
4903 | + (save-restriction |
4904 | + (widen) |
4905 | + (lexical-let ((pps (parse-partial-sexp (line-beginning-position) (point)))) |
4906 | + (when (nth 4 pps) |
4907 | + (goto-char |
4908 | + (nth 8 pps)))))) |
4909 | + |
4910 | +(defun py-current-defun (&optional arg) |
4911 | + "Go to the outermost method or class definition in current scope. |
4912 | + |
4913 | +Python value for `add-log-current-defun-function'. |
4914 | +This tells add-log.el how to find the current function/method/variable. |
4915 | +Returns name of class or methods definition, if found, nil otherwise. |
4916 | + |
4917 | +See customizable variables `py-current-defun-show' and `py-current-defun-delay'." |
4918 | + (interactive "p") |
4919 | + (save-restriction |
4920 | + (widen) |
4921 | + (save-excursion |
4922 | + (while |
4923 | + (or (not (py-beginning-of-def-or-class-p)) (< 0 (current-indentation))) |
4924 | + (py-beginning-of-def-or-class 'either)) |
4925 | + (forward-word 1) |
4926 | + (skip-chars-forward " \t") |
4927 | + (let ((erg (prin1-to-string (symbol-at-point)))) |
4928 | + (when py-current-defun-show (push-mark (point) t t) (skip-chars-forward "^ (") |
4929 | + (exchange-point-and-mark) |
4930 | + (sit-for py-current-defun-delay)) |
4931 | + (when arg (message erg)) |
4932 | + erg)))) |
4933 | |
4934 | |
4935 | |
4936 | (defconst py-help-address "python-mode@python.org" |
4937 | @@ -4017,7 +3900,6 @@ |
4938 | (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string) |
4939 | minor-mode-alist)) |
4940 | |
4941 | - |
4942 | |
4943 | |
4944 | ;;; paragraph and string filling code from Bernhard Herzog |
4945 | ;;; see http://mail.python.org/pipermail/python-list/2002-May/103189.html |
4946 | @@ -4086,7 +3968,6 @@ |
4947 | (fill-paragraph justify)))) |
4948 | t)) |
4949 | |
4950 | - |
4951 | (defun py-fill-string (start &optional justify) |
4952 | "Fill the paragraph around (point) in the string starting at start" |
4953 | ;; basic strategy: narrow to the string and call the default |
4954 | @@ -4098,8 +3979,7 @@ |
4955 | ;; length of the string's delimiter |
4956 | delim-length |
4957 | ;; The string delimiter |
4958 | - delim |
4959 | - ) |
4960 | + delim) |
4961 | |
4962 | (save-excursion |
4963 | (goto-char start) |
4964 | @@ -4148,36 +4028,36 @@ |
4965 | If point is inside a string, narrow to that string and fill. |
4966 | " |
4967 | (interactive "P") |
4968 | - ;; fill-paragraph will narrow incorrectly |
4969 | - (save-restriction |
4970 | - (widen) |
4971 | - (let* ((bod (py-point 'bod)) |
4972 | - (pps (parse-partial-sexp bod (point)))) |
4973 | - (cond |
4974 | - ;; are we inside a comment or on a line with only whitespace before |
4975 | - ;; the comment start? |
4976 | - ((or (nth 4 pps) |
4977 | - (save-excursion (beginning-of-line) (looking-at "[ \t]*#"))) |
4978 | - (py-fill-comment justify)) |
4979 | - ;; are we inside a string? |
4980 | - ((nth 3 pps) |
4981 | - (py-fill-string (nth 8 pps))) |
4982 | - ;; are we at the opening quote of a string, or in the indentation? |
4983 | - ((save-excursion |
4984 | - (forward-word 1) |
4985 | - (eq (py-in-literal) 'string)) |
4986 | - (save-excursion |
4987 | - (py-fill-string (py-point 'boi)))) |
4988 | - ;; are we at or after the closing quote of a string? |
4989 | - ((save-excursion |
4990 | - (backward-word 1) |
4991 | - (eq (py-in-literal) 'string)) |
4992 | - (save-excursion |
4993 | - (py-fill-string (py-point 'boi)))) |
4994 | - ;; otherwise: do not ever fill code |
4995 | - (t nil))))) |
4996 | - |
4997 | - |
4998 | - |
4999 | |
5000 | + (save-excursion |