Merge lp:~a-roehler/python-mode/myrkwid into lp:python-mode

Proposed by Andreas Roehler
Status: Merged
Merge reported by: Andreas Roehler
Merged at revision: not available
Proposed branch: lp:~a-roehler/python-mode/myrkwid
Merge into: lp:python-mode
Diff against target: 5004 lines (+2516/-1849)
5 files modified
UnicodeEncodeError-lp:550661-test.py (+4/-0)
py-bug-numbered-tests.el (+738/-245)
python-mode-test.el (+202/-0)
python-mode-tests.sh (+88/-0)
python-mode.el (+1484/-1604)
To merge this branch: bzr merge lp:~a-roehler/python-mode/myrkwid
Reviewer Review Type Date Requested Status
python-mode.el developers Pending
Review via email: mp+54478@code.launchpad.net

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-of-statement', `py-end-of-statement'

with `py-travel-current-indent' core stepping downwards.

Also `py-compute-indentation' redone.

To post a comment you must log in.
lp:~a-roehler/python-mode/myrkwid updated
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-continuation-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

  lp:328782-test

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: