diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 164 |
1 files changed, 64 insertions, 100 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 0213a0ec8fb..bbf66f2033f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -46,8 +46,7 @@ | |||
| 46 | ;; causes the current line to be dedented automatically if needed. | 46 | ;; causes the current line to be dedented automatically if needed. |
| 47 | 47 | ||
| 48 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are | 48 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are |
| 49 | ;; properly implemented. A `beginning-of-innermost-defun' is defined | 49 | ;; properly implemented. |
| 50 | ;; to navigate nested defuns. | ||
| 51 | 50 | ||
| 52 | ;; Shell interaction: is provided and allows you easily execute any | 51 | ;; Shell interaction: is provided and allows you easily execute any |
| 53 | ;; block of code of your current buffer in an inferior Python process. | 52 | ;; block of code of your current buffer in an inferior Python process. |
| @@ -224,8 +223,6 @@ | |||
| 224 | "-" | 223 | "-" |
| 225 | ["Start of def/class" beginning-of-defun | 224 | ["Start of def/class" beginning-of-defun |
| 226 | :help "Go to start of outermost definition around point"] | 225 | :help "Go to start of outermost definition around point"] |
| 227 | ["Start of def/class" python-beginning-of-innermost-defun | ||
| 228 | :help "Go to start of innermost definition around point"] | ||
| 229 | ["End of def/class" end-of-defun | 226 | ["End of def/class" end-of-defun |
| 230 | :help "Go to end of definition around point"] | 227 | :help "Go to end of definition around point"] |
| 231 | "-" | 228 | "-" |
| @@ -266,7 +263,10 @@ | |||
| 266 | (or "def" "class" "if" "elif" "else" "try" | 263 | (or "def" "class" "if" "elif" "else" "try" |
| 267 | "except" "finally" "for" "while" "with") | 264 | "except" "finally" "for" "while" "with") |
| 268 | symbol-end)) | 265 | symbol-end)) |
| 266 | `(decorator . ,(rx line-start (* space) ?@ (any letter ?_) | ||
| 267 | (* (any word ?_)))) | ||
| 269 | `(defun . ,(rx symbol-start (or "def" "class") symbol-end)) | 268 | `(defun . ,(rx symbol-start (or "def" "class") symbol-end)) |
| 269 | `(symbol-name . ,(rx (any letter ?_) (* (any word ?_)))) | ||
| 270 | `(open-paren . ,(rx (or "{" "[" "("))) | 270 | `(open-paren . ,(rx (or "{" "[" "("))) |
| 271 | `(close-paren . ,(rx (or "}" "]" ")"))) | 271 | `(close-paren . ,(rx (or "}" "]" ")"))) |
| 272 | `(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))) | 272 | `(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))) |
| @@ -870,109 +870,73 @@ With numeric ARG, just insert that many colons. With | |||
| 870 | 870 | ||
| 871 | ;;; Navigation | 871 | ;;; Navigation |
| 872 | 872 | ||
| 873 | (defcustom python-use-beginning-of-innermost-defun nil | 873 | (defvar python-nav-beginning-of-defun-regexp |
| 874 | "Set if `beginning-of-defun-function' should go to innermost defun." | 874 | (python-rx line-start (* space) defun (+ space) symbol-name) |
| 875 | :type 'string | ||
| 876 | :group 'python | ||
| 877 | :safe 'stringp) | ||
| 878 | |||
| 879 | (defvar python-beginning-of-defun-regexp | ||
| 880 | "^\\(def\\|class\\)[[:space:]]+[[:word:]]+" | ||
| 881 | "Regular expresion matching beginning of outermost class or function.") | ||
| 882 | |||
| 883 | (defvar python-beginning-of-innermost-defun-regexp | ||
| 884 | "^[[:space:]]*\\(def\\|class\\)[[:space:]]+[[:word:]]+" | ||
| 885 | "Regular expresion matching beginning of innermost class or function.") | 875 | "Regular expresion matching beginning of innermost class or function.") |
| 886 | 876 | ||
| 887 | (defun python-beginning-of-defun (&optional innermost) | 877 | (defun python-nav-beginning-of-defun () |
| 888 | "Move point to the beginning of innermost/outermost def or class. | 878 | "Move point to beginning-of-defun. |
| 889 | If INNERMOST is non-nil then move to the beginning of the | 879 | This is the main part of`python-beginning-of-defun-function' |
| 890 | innermost definition." | 880 | implementation." |
| 891 | (let ((starting-point (point-marker)) | 881 | (let ((indent-pos (save-excursion |
| 892 | (nonblank-line-indent) | 882 | (back-to-indentation) |
| 893 | (defun-indent) | 883 | (point-marker))) |
| 894 | (defun-point) | 884 | (include-decorators |
| 895 | (regexp (if innermost | 885 | (lambda () |
| 896 | python-beginning-of-innermost-defun-regexp | 886 | (when (save-excursion |
| 897 | python-beginning-of-defun-regexp))) | 887 | (forward-line -1) |
| 898 | (back-to-indentation) | 888 | (looking-at (python-rx decorator))) |
| 899 | (if (and (not (looking-at "@")) | 889 | (while (and (not (bobp)) |
| 900 | (not (looking-at regexp))) | 890 | (forward-line -1) |
| 901 | (forward-comment -1) | 891 | (looking-at (python-rx decorator)))) |
| 902 | (while (and (not (eobp)) | 892 | (when (not (bobp)) (forward-line 1)))))) |
| 903 | (forward-line 1) | 893 | (if (and (> (point) indent-pos) |
| 904 | (not (back-to-indentation)) | 894 | (save-excursion |
| 905 | (looking-at "@")))) | 895 | (goto-char (line-beginning-position)) |
| 906 | (when (not (looking-at regexp)) | 896 | (looking-at python-nav-beginning-of-defun-regexp))) |
| 907 | (re-search-backward regexp nil t)) | ||
| 908 | (setq nonblank-line-indent (+ (current-indentation) python-indent-offset)) | ||
| 909 | (setq defun-indent (current-indentation)) | ||
| 910 | (setq defun-point (point-marker)) | ||
| 911 | (if (> nonblank-line-indent defun-indent) | ||
| 912 | (progn | 897 | (progn |
| 913 | (goto-char defun-point) | 898 | (goto-char (line-beginning-position)) |
| 914 | (forward-line -1) | 899 | (funcall include-decorators)) |
| 915 | (while (and (looking-at "@") | 900 | (goto-char (line-beginning-position)) |
| 916 | (forward-line -1) | 901 | (re-search-backward python-nav-beginning-of-defun-regexp nil t) |
| 917 | (not (bobp)) | 902 | (goto-char (or (python-info-ppss-context 'string) (point))) |
| 918 | (not (back-to-indentation)))) | 903 | (funcall include-decorators)))) |
| 919 | (unless (bobp) | 904 | |
| 920 | (forward-line 1)) | 905 | (defun python-beginning-of-defun-function (&optional arg) |
| 921 | (point-marker)) | 906 | "Move point to the beginning of def or class. |
| 922 | (if innermost | 907 | With positive ARG move that number of functions forward. With |
| 923 | (python-beginning-of-defun) | 908 | negative do the same but backwards." |
| 924 | (goto-char starting-point) | 909 | (when (or (null arg) (= arg 0)) (setq arg 1)) |
| 925 | nil)))) | 910 | (if (> arg 0) |
| 926 | 911 | (dotimes (i arg) | |
| 927 | (defun python-beginning-of-defun-function () | 912 | (python-nav-beginning-of-defun)) |
| 928 | "Move point to the beginning of \(inner|outer)most def or class. | 913 | (dotimes (i (- arg)) |
| 929 | The point is moved to the beginning of innermost or outermost def | 914 | (python-end-of-defun-function) |
| 930 | or class given the value of | 915 | (forward-comment 1) |
| 931 | `python-use-beginning-of-innermost-defun'. Returns nil if point | 916 | (goto-char (line-end-position)) |
| 932 | is not in a def or class." | 917 | (when (not (eobp)) |
| 933 | (python-beginning-of-defun python-use-beginning-of-innermost-defun)) | 918 | (python-nav-beginning-of-defun))))) |
| 934 | |||
| 935 | (defun python-beginning-of-outermost-defun () | ||
| 936 | "Move point to the beginning of outermost def or class. | ||
| 937 | Returns nil if point is not in a def or class." | ||
| 938 | (interactive) | ||
| 939 | (python-beginning-of-defun nil)) | ||
| 940 | |||
| 941 | (defun python-beginning-of-innermost-defun () | ||
| 942 | "Move point to the beginning of innermost def or class. | ||
| 943 | Returns nil if point is not in a def or class." | ||
| 944 | (interactive) | ||
| 945 | (python-beginning-of-defun t)) | ||
| 946 | 919 | ||
| 947 | (defun python-end-of-defun-function () | 920 | (defun python-end-of-defun-function () |
| 948 | "Move point to the end of def or class. | 921 | "Move point to the end of def or class. |
| 949 | Returns nil if point is not in a def or class." | 922 | Returns nil if point is not in a def or class." |
| 950 | (let ((starting-point (point-marker)) | 923 | (interactive) |
| 951 | (defun-regexp (python-rx defun)) | 924 | (let ((beg-defun-indent) |
| 952 | (beg-defun-indent)) | 925 | (decorator-regexp "[[:space:]]*@")) |
| 953 | (back-to-indentation) | 926 | (when (looking-at decorator-regexp) |
| 954 | (if (looking-at "@") | 927 | (while (and (not (eobp)) |
| 955 | (while (and (not (eobp)) | 928 | (forward-line 1) |
| 956 | (forward-line 1) | 929 | (looking-at decorator-regexp)))) |
| 957 | (not (back-to-indentation)) | 930 | (when (not (looking-at python-nav-beginning-of-defun-regexp)) |
| 958 | (looking-at "@"))) | 931 | (python-beginning-of-defun-function)) |
| 959 | (while (and (not (bobp)) | 932 | (setq beg-defun-indent (current-indentation)) |
| 960 | (not (progn (back-to-indentation) (current-word))) | 933 | (forward-line 1) |
| 961 | (forward-line -1)))) | 934 | (while (and (forward-line 1) |
| 962 | (when (or (not (equal (current-indentation) 0)) | 935 | (not (eobp)) |
| 963 | (string-match defun-regexp (current-word))) | 936 | (or (not (current-word)) |
| 964 | (setq beg-defun-indent (save-excursion | 937 | (> (current-indentation) beg-defun-indent)))) |
| 965 | (or (looking-at defun-regexp) | 938 | (forward-comment 1) |
| 966 | (python-beginning-of-innermost-defun)) | 939 | (goto-char (line-beginning-position)))) |
| 967 | (current-indentation))) | ||
| 968 | (while (and (forward-line 1) | ||
| 969 | (not (eobp)) | ||
| 970 | (or (not (current-word)) | ||
| 971 | (> (current-indentation) beg-defun-indent)))) | ||
| 972 | (while (and (forward-comment -1) | ||
| 973 | (not (bobp)))) | ||
| 974 | (forward-line 1) | ||
| 975 | (point-marker)))) | ||
| 976 | 940 | ||
| 977 | 941 | ||
| 978 | ;;; Shell integration | 942 | ;;; Shell integration |