Skip to content

Commit

Permalink
Handle multiple decorators
Browse files Browse the repository at this point in the history
When `py-mark-decorators' is non-nil, py-backward-... commands should
reach outer decorators, if any.
  • Loading branch information
andreas-roehler committed Sep 17, 2015
1 parent 0bf5789 commit 5c000f6
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 66 deletions.
20 changes: 16 additions & 4 deletions devel/python-mode-utils.el
Expand Up @@ -69,10 +69,7 @@
(list
"block"
"block-or-clause"
"class"
"clause"
"def"
"def-or-class"
"if-block"
"elif-block"
"else-block"
Expand Down Expand Up @@ -359,6 +356,21 @@
"try-block"
))

;; backward class/def treated with shorter forms internally
(setq py-backward-command-names
(list
"block"
"block-or-clause"
"clause"
"elif-block"
"else-block"
"except-block"
"for-block"
"if-block"
"minor-block"
"try-block"
))

(setq py-checker-command-names '("clear-flymake-allowed-file-name-masks" "pylint-flymake-mode" "pyflakes-flymake-mode" "pychecker-flymake-mode" "pep8-flymake-mode" "pyflakespep8-flymake-mode" "py-pylint-doku" "py-pyflakes-run" "py-pyflakespep8-run" "py-pyflakespep8-help"))

(setq py-fast-execute-forms-names
Expand Down Expand Up @@ -2259,7 +2271,7 @@ Returns beginning of " ele " if successful, nil otherwise\n
(t (insert (concat "
(py--backward-prepare indent 'py-" ele "-re 'py-clause-re (called-interactively-p 'any)))\n")))))
;; bol forms
(dolist (ele py-beginning-bol-command-names)
(dolist (ele py-backward-command-names)
(insert (concat "
\(defun py-backward-" ele "-bol (&optional indent)"
"\n \"Go to beginning of " ele ", go to BOL.
Expand Down
60 changes: 0 additions & 60 deletions python-components-backward-forms.el
Expand Up @@ -46,16 +46,6 @@ Returns beginning of block-or-clause if successful, nil otherwise
(interactive)
(py--backward-prepare indent 'py-extended-block-or-clause-re 'py-extended-block-or-clause-re (called-interactively-p 'any)))

(defun py-backward-class (&optional indent)
"Go to beginning of class.
If already at beginning, go one class backward.
Returns beginning of class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-class-re 'py-extended-block-or-clause-re (called-interactively-p 'any)))

(defun py-backward-clause (&optional indent)
"Go to beginning of clause.
Expand All @@ -66,26 +56,6 @@ Returns beginning of clause if successful, nil otherwise
(interactive)
(py--backward-prepare indent 'py-extended-block-or-clause-re 'py-extended-block-or-clause-re (called-interactively-p 'any)))

(defun py-backward-def (&optional indent)
"Go to beginning of def.
If already at beginning, go one def backward.
Returns beginning of def if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-def-re 'py-extended-block-or-clause-re (called-interactively-p 'any)))

(defun py-backward-def-or-class (&optional indent)
"Go to beginning of def-or-class.
If already at beginning, go one def-or-class backward.
Returns beginning of def-or-class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-def-or-class-re 'py-extended-block-or-clause-re (called-interactively-p 'any)))

(defun py-backward-if-block (&optional indent)
"Go to beginning of if-block.
Expand Down Expand Up @@ -176,16 +146,6 @@ Returns beginning of block-or-clause if successful, nil otherwise
(interactive)
(py--backward-prepare indent 'py-extended-block-or-clause-re 'py-extended-block-or-clause-re (called-interactively-p 'any) t))

(defun py-backward-class-bol (&optional indent)
"Go to beginning of class, go to BOL.
If already at beginning, go one class backward.
Returns beginning of class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-class-re 'py-extended-block-or-clause-re (called-interactively-p 'any) t))

(defun py-backward-clause-bol (&optional indent)
"Go to beginning of clause, go to BOL.
Expand All @@ -196,26 +156,6 @@ Returns beginning of clause if successful, nil otherwise
(interactive)
(py--backward-prepare indent 'py-extended-block-or-clause-re 'py-extended-block-or-clause-re (called-interactively-p 'any) t))

(defun py-backward-def-bol (&optional indent)
"Go to beginning of def, go to BOL.
If already at beginning, go one def backward.
Returns beginning of def if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-def-re 'py-extended-block-or-clause-re (called-interactively-p 'any) t))

(defun py-backward-def-or-class-bol (&optional indent)
"Go to beginning of def-or-class, go to BOL.
If already at beginning, go one def-or-class backward.
Returns beginning of def-or-class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(py--backward-prepare indent 'py-def-or-class-re 'py-extended-block-or-clause-re (called-interactively-p 'any) t))

(defun py-backward-elif-block-bol (&optional indent)
"Go to beginning of elif-block, go to BOL.
Expand Down
103 changes: 102 additions & 1 deletion python-components-move.el
Expand Up @@ -219,7 +219,7 @@ computing indents"
(py-backward-statement orig done limit ignore-in-string-p))
((nth 4 pps)
(goto-char (nth 8 pps))
(skip-chars-backward " \t\r\n\f")
(skip-chars-backward " \t\r\n\f")
(py-backward-statement orig done limit ignore-in-string-p))
((nth 1 pps)
(goto-char (1- (nth 1 pps)))
Expand Down Expand Up @@ -706,5 +706,106 @@ Return position if successful"
(when (and (looking-back py-section-end)(< orig (point)))
(point))))

(defun py--backward-def-or-class-decorator-maybe (&optional bol)
"Return position of the decorator.
With BOL, return line-beginning-position"
(let ((orig (point))
erg)
(while (and (not (bobp)) (progn (forward-line -1)(beginning-of-line) (eq (char-after) ?@)))
(setq erg (point)))
;; for bol-forms, set erg to bol
(when (and erg bol
(setq erg (line-beginning-position))))
(or erg (goto-char orig))))

(defun py--backward-def-or-class-intern (regexp &optional indent bol)
(while (and (re-search-backward regexp nil 'move 1)
(nth 8 (parse-partial-sexp (point-min) (point)))))
(let ((erg (when (looking-at regexp)
(if bol (line-beginning-position) (point)))))
;; bol-forms at not at bol yet
(and erg (goto-char erg))
(and erg py-mark-decorators (setq erg (py--backward-def-or-class-decorator-maybe bol)))
erg))

(defun py-backward-class (&optional indent)
"Go to beginning of class.
If already at beginning, go one class backward.
Returns beginning of class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-class-re indent)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(defun py-backward-def (&optional indent)
"Go to beginning of def.
If already at beginning, go one def backward.
Returns beginning of def if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-def-re indent)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(defun py-backward-def-or-class (&optional indent)
"Go to beginning of def-or-class.
If already at beginning, go one def-or-class backward.
Returns beginning of def-or-class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-def-or-class-re indent)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(defun py-backward-class-bol (&optional indent)
"Go to beginning of class, go to BOL.
If already at beginning, go one class backward.
Returns beginning of class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-class-re indent t)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(defun py-backward-def-bol (&optional indent)
"Go to beginning of def, go to BOL.
If already at beginning, go one def backward.
Returns beginning of def if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-def-re indent t)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(defun py-backward-def-or-class-bol (&optional indent)
"Go to beginning of def-or-class, go to BOL.
If already at beginning, go one def-or-class backward.
Returns beginning of def-or-class if successful, nil otherwise
When `py-mark-decorators' is non-nil, decorators are considered too. "
(interactive)
(let ((erg (py--backward-def-or-class-intern py-def-or-class-re indent t)))
(when (and py-verbose-p (called-interactively-p 'any))
(message "%s" erg))
erg))

(provide 'python-components-move)
;;; python-components-move.el ends here
24 changes: 23 additions & 1 deletion test/py-ert-tests-3.el
Expand Up @@ -73,6 +73,28 @@ a = sys.argv"
(search-forward "a = sy")
(py-find-definition)))

(ert-deftest py-ert-multiple-decorators-test-1 ()
(py-test-with-temp-buffer
"@blah
@blub
def foo():
pass
"
(let ((py-mark-decorators t))
(py-beginning-of-def-or-class)
(should (bobp)))))

(ert-deftest py-ert-multiple-decorators-test-2 ()
(py-test-with-temp-buffer
"@blah
@blub
def foo():
pass
"
(let* (py-mark-decorators
(erg (py-beginning-of-def-or-class)))
(should (eq 13 erg)))))

;; (ert-deftest py-ert-find-definition-test-2 ()
;; (py-test-with-temp-buffer
;; "#! /usr/bin/env python
Expand All @@ -85,7 +107,7 @@ a = sys.argv"

;; foo()"
;; (beginning-of-line)
;; (sit-for 0.1)
;; (sit-for 0.1)
;; (should (string= "def foo" (py-find-definition)))))

(provide 'py-ert-tests-3)
Expand Down

0 comments on commit 5c000f6

Please sign in to comment.