diff options
| author | Joakim Verona | 2012-07-27 02:22:03 +0200 |
|---|---|---|
| committer | Joakim Verona | 2012-07-27 02:22:03 +0200 |
| commit | 5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f (patch) | |
| tree | 5c55f1096a656a9759f0b53a0b5d1a2289bd366f /lisp/progmodes/python.el | |
| parent | 0c5c85cf2b350c965bb1ffa5b2d77c2adebc406b (diff) | |
| parent | 562157c814037dcba58a20cd6908a95992c22283 (diff) | |
| download | emacs-5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f.tar.gz emacs-5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f.zip | |
upstream
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 626 |
1 files changed, 319 insertions, 307 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index a43dc1eb1d3..132951aedc8 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; python.el --- Python's flying circus support for Emacs -*- coding: utf-8 -*- | 1 | ;;; python.el --- Python's flying circus support for Emacs |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003-2012 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -46,13 +46,16 @@ | |||
| 46 | 46 | ||
| 47 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are | 47 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are |
| 48 | ;; properly implemented. There are also specialized | 48 | ;; properly implemented. There are also specialized |
| 49 | ;; `forward-sentence' and `backward-sentence' replacements | 49 | ;; `forward-sentence' and `backward-sentence' replacements called |
| 50 | ;; (`python-nav-forward-sentence', `python-nav-backward-sentence' | 50 | ;; `python-nav-forward-block', `python-nav-backward-block' |
| 51 | ;; respectively). Extra functions `python-nav-sentence-start' and | 51 | ;; respectively which navigate between beginning of blocks of code. |
| 52 | ;; `python-nav-sentence-end' are included to move to the beginning and | 52 | ;; Extra functions `python-nav-forward-statement', |
| 53 | ;; to the end of a sentence while taking care of multiline definitions. | 53 | ;; `python-nav-backward-statement', |
| 54 | ;; `python-nav-jump-to-defun' is provided and allows jumping to a | 54 | ;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', |
| 55 | ;; function or class definition quickly in the current buffer. | 55 | ;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are |
| 56 | ;; included but no bound to any key. At last but not least the | ||
| 57 | ;; specialized `python-nav-forward-sexp-function' allows easy | ||
| 58 | ;; navigation between code blocks. | ||
| 56 | 59 | ||
| 57 | ;; Shell interaction: is provided and allows you to execute easily any | 60 | ;; Shell interaction: is provided and allows you to execute easily any |
| 58 | ;; block of code of your current buffer in an inferior Python process. | 61 | ;; block of code of your current buffer in an inferior Python process. |
| @@ -166,10 +169,10 @@ | |||
| 166 | ;; might guessed you should run `python-shell-send-buffer' from time | 169 | ;; might guessed you should run `python-shell-send-buffer' from time |
| 167 | ;; to time to get better results too. | 170 | ;; to time to get better results too. |
| 168 | 171 | ||
| 169 | ;; imenu: This mode supports imenu. It builds a plain or tree menu | 172 | ;; imenu: This mode supports imenu in its most basic form, letting it |
| 170 | ;; depending on the value of `python-imenu-make-tree'. Also you can | 173 | ;; build the necessary alist via `imenu-default-create-index-function' |
| 171 | ;; customize if menu items should include its type using | 174 | ;; by having set `imenu-extract-index-name-function' to |
| 172 | ;; `python-imenu-include-defun-type'. | 175 | ;; `python-info-current-defun'. |
| 173 | 176 | ||
| 174 | ;; If you used python-mode.el you probably will miss auto-indentation | 177 | ;; If you used python-mode.el you probably will miss auto-indentation |
| 175 | ;; when inserting newlines. To achieve the same behavior you have | 178 | ;; when inserting newlines. To achieve the same behavior you have |
| @@ -227,12 +230,12 @@ | |||
| 227 | (let ((map (make-sparse-keymap))) | 230 | (let ((map (make-sparse-keymap))) |
| 228 | ;; Movement | 231 | ;; Movement |
| 229 | (substitute-key-definition 'backward-sentence | 232 | (substitute-key-definition 'backward-sentence |
| 230 | 'python-nav-backward-sentence | 233 | 'python-nav-backward-block |
| 231 | map global-map) | 234 | map global-map) |
| 232 | (substitute-key-definition 'forward-sentence | 235 | (substitute-key-definition 'forward-sentence |
| 233 | 'python-nav-forward-sentence | 236 | 'python-nav-forward-block |
| 234 | map global-map) | 237 | map global-map) |
| 235 | (define-key map "\C-c\C-j" 'python-nav-jump-to-defun) | 238 | (define-key map "\C-c\C-j" 'imenu) |
| 236 | ;; Indent specific | 239 | ;; Indent specific |
| 237 | (define-key map "\177" 'python-indent-dedent-line-backspace) | 240 | (define-key map "\177" 'python-indent-dedent-line-backspace) |
| 238 | (define-key map (kbd "<backtab>") 'python-indent-dedent-line) | 241 | (define-key map (kbd "<backtab>") 'python-indent-dedent-line) |
| @@ -273,7 +276,7 @@ | |||
| 273 | :help "Go to end of definition around point"] | 276 | :help "Go to end of definition around point"] |
| 274 | ["Mark def/class" mark-defun | 277 | ["Mark def/class" mark-defun |
| 275 | :help "Mark outermost definition around point"] | 278 | :help "Mark outermost definition around point"] |
| 276 | ["Jump to def/class" python-nav-jump-to-defun | 279 | ["Jump to def/class" imenu |
| 277 | :help "Jump to a class or function definition"] | 280 | :help "Jump to a class or function definition"] |
| 278 | "--" | 281 | "--" |
| 279 | ("Skeletons") | 282 | ("Skeletons") |
| @@ -653,9 +656,7 @@ START is the buffer position where the sexp starts." | |||
| 653 | (while (and (re-search-backward | 656 | (while (and (re-search-backward |
| 654 | (python-rx block-start) nil t) | 657 | (python-rx block-start) nil t) |
| 655 | (or | 658 | (or |
| 656 | (python-info-ppss-context 'string) | 659 | (python-info-ppss-context-type) |
| 657 | (python-info-ppss-context 'comment) | ||
| 658 | (python-info-ppss-context 'paren) | ||
| 659 | (python-info-continuation-line-p)))) | 660 | (python-info-continuation-line-p)))) |
| 660 | (when (looking-at (python-rx block-start)) | 661 | (when (looking-at (python-rx block-start)) |
| 661 | (point-marker))))) | 662 | (point-marker))))) |
| @@ -664,7 +665,7 @@ START is the buffer position where the sexp starts." | |||
| 664 | ((setq start (save-excursion | 665 | ((setq start (save-excursion |
| 665 | (back-to-indentation) | 666 | (back-to-indentation) |
| 666 | (python-util-forward-comment -1) | 667 | (python-util-forward-comment -1) |
| 667 | (python-nav-sentence-start) | 668 | (python-nav-beginning-of-statement) |
| 668 | (point-marker))) | 669 | (point-marker))) |
| 669 | 'after-line) | 670 | 'after-line) |
| 670 | ;; Do not indent | 671 | ;; Do not indent |
| @@ -723,13 +724,9 @@ START is the buffer position where the sexp starts." | |||
| 723 | (goto-char (line-end-position)) | 724 | (goto-char (line-end-position)) |
| 724 | (while (and (re-search-backward | 725 | (while (and (re-search-backward |
| 725 | "\\." (line-beginning-position) t) | 726 | "\\." (line-beginning-position) t) |
| 726 | (or (python-info-ppss-context 'comment) | 727 | (python-info-ppss-context-type))) |
| 727 | (python-info-ppss-context 'string) | ||
| 728 | (python-info-ppss-context 'paren)))) | ||
| 729 | (if (and (looking-at "\\.") | 728 | (if (and (looking-at "\\.") |
| 730 | (not (or (python-info-ppss-context 'comment) | 729 | (not (python-info-ppss-context-type))) |
| 731 | (python-info-ppss-context 'string) | ||
| 732 | (python-info-ppss-context 'paren)))) | ||
| 733 | ;; The indentation is the same column of the | 730 | ;; The indentation is the same column of the |
| 734 | ;; first matching dot that's not inside a | 731 | ;; first matching dot that's not inside a |
| 735 | ;; comment, a string or a paren | 732 | ;; comment, a string or a paren |
| @@ -885,8 +882,7 @@ See `python-indent-line' for details." | |||
| 885 | (defun python-indent-dedent-line () | 882 | (defun python-indent-dedent-line () |
| 886 | "De-indent current line." | 883 | "De-indent current line." |
| 887 | (interactive "*") | 884 | (interactive "*") |
| 888 | (when (and (not (or (python-info-ppss-context 'string) | 885 | (when (and (not (python-info-ppss-comment-or-string-p)) |
| 889 | (python-info-ppss-context 'comment))) | ||
| 890 | (<= (point-marker) (save-excursion | 886 | (<= (point-marker) (save-excursion |
| 891 | (back-to-indentation) | 887 | (back-to-indentation) |
| 892 | (point-marker))) | 888 | (point-marker))) |
| @@ -977,8 +973,7 @@ With numeric ARG, just insert that many colons. With | |||
| 977 | (when (and (not arg) | 973 | (when (and (not arg) |
| 978 | (eolp) | 974 | (eolp) |
| 979 | (not (equal ?: (char-after (- (point-marker) 2)))) | 975 | (not (equal ?: (char-after (- (point-marker) 2)))) |
| 980 | (not (or (python-info-ppss-context 'string) | 976 | (not (python-info-ppss-comment-or-string-p))) |
| 981 | (python-info-ppss-context 'comment)))) | ||
| 982 | (let ((indentation (current-indentation)) | 977 | (let ((indentation (current-indentation)) |
| 983 | (calculated-indentation (python-indent-calculate-indentation))) | 978 | (calculated-indentation (python-indent-calculate-indentation))) |
| 984 | (python-info-closing-block-message) | 979 | (python-info-closing-block-message) |
| @@ -1097,10 +1092,10 @@ Returns nil if point is not in a def or class." | |||
| 1097 | (python-info-ppss-context-type)) | 1092 | (python-info-ppss-context-type)) |
| 1098 | (forward-line 1))))))) | 1093 | (forward-line 1))))))) |
| 1099 | 1094 | ||
| 1100 | (defun python-nav-sentence-start () | 1095 | (defun python-nav-beginning-of-statement () |
| 1101 | "Move to start of current sentence." | 1096 | "Move to start of current statement." |
| 1102 | (interactive "^") | 1097 | (interactive "^") |
| 1103 | (while (and (not (back-to-indentation)) | 1098 | (while (and (or (back-to-indentation) t) |
| 1104 | (not (bobp)) | 1099 | (not (bobp)) |
| 1105 | (when (or | 1100 | (when (or |
| 1106 | (save-excursion | 1101 | (save-excursion |
| @@ -1110,8 +1105,8 @@ Returns nil if point is not in a def or class." | |||
| 1110 | (python-info-ppss-context 'paren)) | 1105 | (python-info-ppss-context 'paren)) |
| 1111 | (forward-line -1))))) | 1106 | (forward-line -1))))) |
| 1112 | 1107 | ||
| 1113 | (defun python-nav-sentence-end () | 1108 | (defun python-nav-end-of-statement () |
| 1114 | "Move to end of current sentence." | 1109 | "Move to end of current statement." |
| 1115 | (interactive "^") | 1110 | (interactive "^") |
| 1116 | (while (and (goto-char (line-end-position)) | 1111 | (while (and (goto-char (line-end-position)) |
| 1117 | (not (eobp)) | 1112 | (not (eobp)) |
| @@ -1121,85 +1116,182 @@ Returns nil if point is not in a def or class." | |||
| 1121 | (python-info-ppss-context 'paren)) | 1116 | (python-info-ppss-context 'paren)) |
| 1122 | (forward-line 1))))) | 1117 | (forward-line 1))))) |
| 1123 | 1118 | ||
| 1124 | (defun python-nav-backward-sentence (&optional arg) | 1119 | (defun python-nav-backward-statement (&optional arg) |
| 1125 | "Move backward to start of sentence. With ARG, do it arg times. | 1120 | "Move backward to previous statement. |
| 1126 | See `python-nav-forward-sentence' for more information." | 1121 | With ARG, repeat. See `python-nav-forward-statement'." |
| 1127 | (interactive "^p") | 1122 | (interactive "^p") |
| 1128 | (or arg (setq arg 1)) | 1123 | (or arg (setq arg 1)) |
| 1129 | (python-nav-forward-sentence (- arg))) | 1124 | (python-nav-forward-statement (- arg))) |
| 1130 | 1125 | ||
| 1131 | (defun python-nav-forward-sentence (&optional arg) | 1126 | (defun python-nav-forward-statement (&optional arg) |
| 1132 | "Move forward to next end of sentence. With ARG, repeat. | 1127 | "Move forward to next statement. |
| 1133 | With negative argument, move backward repeatedly to start of sentence." | 1128 | With ARG, repeat. With negative argument, move ARG times |
| 1129 | backward to previous statement." | ||
| 1134 | (interactive "^p") | 1130 | (interactive "^p") |
| 1135 | (or arg (setq arg 1)) | 1131 | (or arg (setq arg 1)) |
| 1136 | (while (> arg 0) | 1132 | (while (> arg 0) |
| 1133 | (python-nav-end-of-statement) | ||
| 1137 | (python-util-forward-comment) | 1134 | (python-util-forward-comment) |
| 1138 | (python-nav-sentence-end) | 1135 | (python-nav-beginning-of-statement) |
| 1139 | (forward-line 1) | ||
| 1140 | (setq arg (1- arg))) | 1136 | (setq arg (1- arg))) |
| 1141 | (while (< arg 0) | 1137 | (while (< arg 0) |
| 1142 | (python-nav-sentence-end) | 1138 | (python-nav-beginning-of-statement) |
| 1143 | (python-util-forward-comment -1) | 1139 | (python-util-forward-comment -1) |
| 1144 | (python-nav-sentence-start) | 1140 | (python-nav-beginning-of-statement) |
| 1145 | (forward-line -1) | ||
| 1146 | (setq arg (1+ arg)))) | 1141 | (setq arg (1+ arg)))) |
| 1147 | 1142 | ||
| 1148 | (defvar python-nav-list-defun-positions-cache nil) | 1143 | (defun python-nav-beginning-of-block () |
| 1149 | (make-variable-buffer-local 'python-nav-list-defun-positions-cache) | 1144 | "Move to start of current block." |
| 1150 | 1145 | (interactive "^") | |
| 1151 | (defun python-nav-list-defun-positions (&optional include-type rescan) | 1146 | (let ((starting-pos (point)) |
| 1152 | "Make an Alist of defun names and point markers for current buffer. | 1147 | (block-regexp (python-rx |
| 1153 | When optional argument INCLUDE-TYPE is non-nil the type is | 1148 | line-start (* whitespace) block-start))) |
| 1154 | included the defun name. With optional argument RESCAN the | 1149 | (if (progn |
| 1155 | `python-nav-list-defun-positions-cache' is invalidated and the | 1150 | (python-nav-beginning-of-statement) |
| 1156 | list of defun is regenerated again." | 1151 | (looking-at (python-rx block-start))) |
| 1157 | (if (and python-nav-list-defun-positions-cache (not rescan)) | 1152 | (point-marker) |
| 1158 | python-nav-list-defun-positions-cache | 1153 | ;; Go to first line beginning a statement |
| 1159 | (let ((defs)) | 1154 | (while (and (not (bobp)) |
| 1160 | (save-restriction | 1155 | (or (and (python-nav-beginning-of-statement) nil) |
| 1161 | (widen) | 1156 | (python-info-current-line-comment-p) |
| 1162 | (save-excursion | 1157 | (python-info-current-line-empty-p))) |
| 1163 | (goto-char (point-max)) | 1158 | (forward-line -1)) |
| 1164 | (while (re-search-backward python-nav-beginning-of-defun-regexp nil t) | 1159 | (let ((block-matching-indent |
| 1165 | (when (and (not (python-info-ppss-context 'string)) | 1160 | (- (current-indentation) python-indent-offset))) |
| 1166 | (not (python-info-ppss-context 'comment)) | 1161 | (while |
| 1167 | (not (python-info-ppss-context 'parent))) | 1162 | (and (python-nav-backward-block) |
| 1168 | (add-to-list | 1163 | (> (current-indentation) block-matching-indent))) |
| 1169 | 'defs (cons | 1164 | (if (and (looking-at (python-rx block-start)) |
| 1170 | (python-info-current-defun include-type) | 1165 | (= (current-indentation) block-matching-indent)) |
| 1171 | (point-marker))))) | 1166 | (point-marker) |
| 1172 | (setq python-nav-list-defun-positions-cache defs)))))) | 1167 | (and (goto-char starting-pos) nil)))))) |
| 1173 | 1168 | ||
| 1174 | (defun python-nav-read-defun (&optional rescan) | 1169 | (defun python-nav-end-of-block () |
| 1175 | "Read a defun name of current buffer and return its point marker. | 1170 | "Move to end of current block." |
| 1176 | A cons cell with the form (DEFUN-NAME . POINT-MARKER) is returned | 1171 | (interactive "^") |
| 1177 | when defun is completed, else nil. With optional argument RESCAN | 1172 | (when (python-nav-beginning-of-block) |
| 1178 | forces `python-nav-list-defun-positions' to invalidate its | 1173 | (let ((block-indentation (current-indentation))) |
| 1179 | cache." | 1174 | (python-nav-end-of-statement) |
| 1180 | (let ((defs (python-nav-list-defun-positions nil rescan))) | 1175 | (while (and (forward-line 1) |
| 1181 | (minibuffer-with-setup-hook | 1176 | (not (eobp)) |
| 1182 | (lambda () | 1177 | (or (and (> (current-indentation) block-indentation) |
| 1183 | (setq minibuffer-completion-table (mapcar 'car defs))) | 1178 | (or (python-nav-end-of-statement) t)) |
| 1184 | (let ((stringdef | 1179 | (python-info-current-line-comment-p) |
| 1185 | (read-from-minibuffer | 1180 | (python-info-current-line-empty-p)))) |
| 1186 | "Jump to definition: " nil | 1181 | (python-util-forward-comment -1) |
| 1187 | minibuffer-local-must-match-map))) | 1182 | (point-marker)))) |
| 1188 | (when (not (string= stringdef "")) | 1183 | |
| 1189 | (assoc-string stringdef defs)))))) | 1184 | (defun python-nav-backward-block (&optional arg) |
| 1190 | 1185 | "Move backward to previous block of code. | |
| 1191 | (defun python-nav-jump-to-defun (def) | 1186 | With ARG, repeat. See `python-nav-forward-block'." |
| 1192 | "Jump to the definition of DEF in current file. | 1187 | (interactive "^p") |
| 1193 | Locations are cached; use a `C-u' prefix argument to force a | 1188 | (or arg (setq arg 1)) |
| 1194 | rescan." | 1189 | (python-nav-forward-block (- arg))) |
| 1195 | (interactive | 1190 | |
| 1196 | (list (python-nav-read-defun current-prefix-arg))) | 1191 | (defun python-nav-forward-block (&optional arg) |
| 1197 | (when (not (called-interactively-p 'interactive)) | 1192 | "Move forward to next block of code. |
| 1198 | (setq def (assoc-string def (python-nav-list-defun-positions)))) | 1193 | With ARG, repeat. With negative argument, move ARG times |
| 1199 | (let ((def-marker (cdr def))) | 1194 | backward to previous block." |
| 1200 | (when (markerp def-marker) | 1195 | (interactive "^p") |
| 1201 | (goto-char (marker-position def-marker)) | 1196 | (or arg (setq arg 1)) |
| 1202 | (back-to-indentation)))) | 1197 | (let ((block-start-regexp |
| 1198 | (python-rx line-start (* whitespace) block-start)) | ||
| 1199 | (starting-pos (point))) | ||
| 1200 | (while (> arg 0) | ||
| 1201 | (python-nav-end-of-statement) | ||
| 1202 | (while (and | ||
| 1203 | (re-search-forward block-start-regexp nil t) | ||
| 1204 | (python-info-ppss-context-type))) | ||
| 1205 | (setq arg (1- arg))) | ||
| 1206 | (while (< arg 0) | ||
| 1207 | (python-nav-beginning-of-statement) | ||
| 1208 | (while (and | ||
| 1209 | (re-search-backward block-start-regexp nil t) | ||
| 1210 | (python-info-ppss-context-type))) | ||
| 1211 | (setq arg (1+ arg))) | ||
| 1212 | (python-nav-beginning-of-statement) | ||
| 1213 | (if (not (looking-at (python-rx block-start))) | ||
| 1214 | (and (goto-char starting-pos) nil) | ||
| 1215 | (and (not (= (point) starting-pos)) (point-marker))))) | ||
| 1216 | |||
| 1217 | (defun python-nav-forward-sexp-function (&optional arg) | ||
| 1218 | "Move forward across one block of code. | ||
| 1219 | With ARG, do it that many times. Negative arg -N means | ||
| 1220 | move backward N times." | ||
| 1221 | (interactive "^p") | ||
| 1222 | (or arg (setq arg 1)) | ||
| 1223 | (while (> arg 0) | ||
| 1224 | (let ((block-starting-pos | ||
| 1225 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1226 | (block-ending-pos | ||
| 1227 | (save-excursion (python-nav-end-of-block))) | ||
| 1228 | (next-block-starting-pos | ||
| 1229 | (save-excursion (python-nav-forward-block)))) | ||
| 1230 | (cond ((not block-starting-pos) | ||
| 1231 | (python-nav-forward-block)) | ||
| 1232 | ((= (point) block-starting-pos) | ||
| 1233 | (if (or (not next-block-starting-pos) | ||
| 1234 | (< block-ending-pos next-block-starting-pos)) | ||
| 1235 | (python-nav-end-of-block) | ||
| 1236 | (python-nav-forward-block))) | ||
| 1237 | ((= block-ending-pos (point)) | ||
| 1238 | (let ((parent-block-end-pos | ||
| 1239 | (save-excursion | ||
| 1240 | (python-util-forward-comment) | ||
| 1241 | (python-nav-beginning-of-block) | ||
| 1242 | (python-nav-end-of-block)))) | ||
| 1243 | (if (and parent-block-end-pos | ||
| 1244 | (or (not next-block-starting-pos) | ||
| 1245 | (> next-block-starting-pos parent-block-end-pos))) | ||
| 1246 | (goto-char parent-block-end-pos) | ||
| 1247 | (python-nav-forward-block)))) | ||
| 1248 | (t (python-nav-end-of-block)))) | ||
| 1249 | (setq arg (1- arg))) | ||
| 1250 | (while (< arg 0) | ||
| 1251 | (let* ((block-starting-pos | ||
| 1252 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1253 | (block-ending-pos | ||
| 1254 | (save-excursion (python-nav-end-of-block))) | ||
| 1255 | (prev-block-ending-pos | ||
| 1256 | (save-excursion (when (python-nav-backward-block) | ||
| 1257 | (python-nav-end-of-block)))) | ||
| 1258 | (prev-block-parent-ending-pos | ||
| 1259 | (save-excursion | ||
| 1260 | (when prev-block-ending-pos | ||
| 1261 | (goto-char prev-block-ending-pos) | ||
| 1262 | (python-util-forward-comment) | ||
| 1263 | (python-nav-beginning-of-block) | ||
| 1264 | (python-nav-end-of-block))))) | ||
| 1265 | (cond ((not block-ending-pos) | ||
| 1266 | (and (python-nav-backward-block) | ||
| 1267 | (python-nav-end-of-block))) | ||
| 1268 | ((= (point) block-ending-pos) | ||
| 1269 | (let ((candidates)) | ||
| 1270 | (dolist (name | ||
| 1271 | '(prev-block-parent-ending-pos | ||
| 1272 | prev-block-ending-pos | ||
| 1273 | block-ending-pos | ||
| 1274 | block-starting-pos)) | ||
| 1275 | (when (and (symbol-value name) | ||
| 1276 | (< (symbol-value name) (point))) | ||
| 1277 | (add-to-list 'candidates (symbol-value name)))) | ||
| 1278 | (goto-char (apply 'max candidates)))) | ||
| 1279 | ((> (point) block-ending-pos) | ||
| 1280 | (python-nav-end-of-block)) | ||
| 1281 | ((= (point) block-starting-pos) | ||
| 1282 | (if (not (> (point) (or prev-block-ending-pos (point)))) | ||
| 1283 | (python-nav-backward-block) | ||
| 1284 | (goto-char prev-block-ending-pos) | ||
| 1285 | (let ((parent-block-ending-pos | ||
| 1286 | (save-excursion | ||
| 1287 | (python-nav-forward-sexp-function) | ||
| 1288 | (and (not (looking-at (python-rx block-start))) | ||
| 1289 | (point))))) | ||
| 1290 | (when (and parent-block-ending-pos | ||
| 1291 | (> parent-block-ending-pos prev-block-ending-pos)) | ||
| 1292 | (goto-char parent-block-ending-pos))))) | ||
| 1293 | (t (python-nav-beginning-of-block)))) | ||
| 1294 | (setq arg (1+ arg)))) | ||
| 1203 | 1295 | ||
| 1204 | 1296 | ||
| 1205 | ;;; Shell integration | 1297 | ;;; Shell integration |
| @@ -1600,24 +1692,29 @@ When MSG is non-nil messages the first line of STRING." | |||
| 1600 | "Send STRING to PROCESS and inhibit output. | 1692 | "Send STRING to PROCESS and inhibit output. |
| 1601 | When MSG is non-nil messages the first line of STRING. Return | 1693 | When MSG is non-nil messages the first line of STRING. Return |
| 1602 | the output." | 1694 | the output." |
| 1603 | (let* ((output-buffer) | 1695 | (let* ((output-buffer "") |
| 1604 | (process (or process (python-shell-get-or-create-process))) | 1696 | (process (or process (python-shell-get-or-create-process))) |
| 1605 | (comint-preoutput-filter-functions | 1697 | (comint-preoutput-filter-functions |
| 1606 | (append comint-preoutput-filter-functions | 1698 | (append comint-preoutput-filter-functions |
| 1607 | '(ansi-color-filter-apply | 1699 | '(ansi-color-filter-apply |
| 1608 | (lambda (string) | 1700 | (lambda (string) |
| 1609 | (setq output-buffer (concat output-buffer string)) | 1701 | (setq output-buffer (concat output-buffer string)) |
| 1610 | ""))))) | 1702 | "")))) |
| 1611 | (python-shell-send-string string process msg) | 1703 | (inhibit-quit t)) |
| 1612 | (accept-process-output process) | 1704 | (or |
| 1613 | (replace-regexp-in-string | 1705 | (with-local-quit |
| 1614 | (if (> (length python-shell-prompt-output-regexp) 0) | 1706 | (python-shell-send-string string process msg) |
| 1615 | (format "\n*%s$\\|^%s\\|\n$" | 1707 | (accept-process-output process) |
| 1616 | python-shell-prompt-regexp | 1708 | (replace-regexp-in-string |
| 1617 | (or python-shell-prompt-output-regexp "")) | 1709 | (if (> (length python-shell-prompt-output-regexp) 0) |
| 1618 | (format "\n*$\\|^%s\\|\n$" | 1710 | (format "\n*%s$\\|^%s\\|\n$" |
| 1619 | python-shell-prompt-regexp)) | 1711 | python-shell-prompt-regexp |
| 1620 | "" output-buffer))) | 1712 | (or python-shell-prompt-output-regexp "")) |
| 1713 | (format "\n*$\\|^%s\\|\n$" | ||
| 1714 | python-shell-prompt-regexp)) | ||
| 1715 | "" output-buffer)) | ||
| 1716 | (with-current-buffer (process-buffer process) | ||
| 1717 | (comint-interrupt-subjob))))) | ||
| 1621 | 1718 | ||
| 1622 | (defun python-shell-internal-send-string (string) | 1719 | (defun python-shell-internal-send-string (string) |
| 1623 | "Send STRING to the Internal Python interpreter. | 1720 | "Send STRING to the Internal Python interpreter. |
| @@ -2140,8 +2237,7 @@ the if condition." | |||
| 2140 | ;; Only expand in code. | 2237 | ;; Only expand in code. |
| 2141 | :enable-function (lambda () | 2238 | :enable-function (lambda () |
| 2142 | (and | 2239 | (and |
| 2143 | (not (or (python-info-ppss-context 'string) | 2240 | (not (python-info-ppss-comment-or-string-p)) |
| 2144 | (python-info-ppss-context 'comment))) | ||
| 2145 | python-skeleton-autoinsert))) | 2241 | python-skeleton-autoinsert))) |
| 2146 | 2242 | ||
| 2147 | (defmacro python-skeleton-define (name doc &rest skel) | 2243 | (defmacro python-skeleton-define (name doc &rest skel) |
| @@ -2152,7 +2248,8 @@ be added to `python-mode-abbrev-table'." | |||
| 2152 | (let* ((name (symbol-name name)) | 2248 | (let* ((name (symbol-name name)) |
| 2153 | (function-name (intern (concat "python-skeleton-" name)))) | 2249 | (function-name (intern (concat "python-skeleton-" name)))) |
| 2154 | `(progn | 2250 | `(progn |
| 2155 | (define-abbrev python-mode-abbrev-table ,name "" ',function-name) | 2251 | (define-abbrev python-mode-abbrev-table ,name "" ',function-name |
| 2252 | :system t) | ||
| 2156 | (setq python-skeleton-available | 2253 | (setq python-skeleton-available |
| 2157 | (cons ',function-name python-skeleton-available)) | 2254 | (cons ',function-name python-skeleton-available)) |
| 2158 | (define-skeleton ,function-name | 2255 | (define-skeleton ,function-name |
| @@ -2377,46 +2474,19 @@ Runs COMMAND, a shell command, as if by `compile'. See | |||
| 2377 | 2474 | ||
| 2378 | (defun python-eldoc--get-doc-at-point (&optional force-input force-process) | 2475 | (defun python-eldoc--get-doc-at-point (&optional force-input force-process) |
| 2379 | "Internal implementation to get documentation at point. | 2476 | "Internal implementation to get documentation at point. |
| 2380 | If not FORCE-INPUT is passed then what `current-word' returns | 2477 | If not FORCE-INPUT is passed then what |
| 2381 | will be used. If not FORCE-PROCESS is passed what | 2478 | `python-info-current-symbol' returns will be used. If not |
| 2382 | `python-shell-get-process' returns is used." | 2479 | FORCE-PROCESS is passed what `python-shell-get-process' returns |
| 2480 | is used." | ||
| 2383 | (let ((process (or force-process (python-shell-get-process)))) | 2481 | (let ((process (or force-process (python-shell-get-process)))) |
| 2384 | (if (not process) | 2482 | (if (not process) |
| 2385 | "Eldoc needs an inferior Python process running." | 2483 | (error "Eldoc needs an inferior Python process running") |
| 2386 | (let* ((current-defun (python-info-current-defun)) | 2484 | (let ((input (or force-input |
| 2387 | (input (or force-input | 2485 | (python-info-current-symbol t)))) |
| 2388 | (with-syntax-table python-dotty-syntax-table | 2486 | (and input |
| 2389 | (if (not current-defun) | 2487 | (python-shell-send-string-no-output |
| 2390 | (current-word) | 2488 | (format python-eldoc-string-code input) |
| 2391 | (concat current-defun "." (current-word)))))) | 2489 | process)))))) |
| 2392 | (ppss (syntax-ppss)) | ||
| 2393 | (help (when (and | ||
| 2394 | input | ||
| 2395 | (not (string= input (concat current-defun "."))) | ||
| 2396 | (not (or (python-info-ppss-context 'string ppss) | ||
| 2397 | (python-info-ppss-context 'comment ppss)))) | ||
| 2398 | (when (string-match | ||
| 2399 | (concat | ||
| 2400 | (regexp-quote (concat current-defun ".")) | ||
| 2401 | "self\\.") input) | ||
| 2402 | (with-temp-buffer | ||
| 2403 | (insert input) | ||
| 2404 | (goto-char (point-min)) | ||
| 2405 | (forward-word) | ||
| 2406 | (forward-char) | ||
| 2407 | (delete-region | ||
| 2408 | (point-marker) (search-forward "self.")) | ||
| 2409 | (setq input (buffer-substring | ||
| 2410 | (point-min) (point-max))))) | ||
| 2411 | (python-shell-send-string-no-output | ||
| 2412 | (format python-eldoc-string-code input) process)))) | ||
| 2413 | (with-current-buffer (process-buffer process) | ||
| 2414 | (when comint-last-prompt-overlay | ||
| 2415 | (delete-region comint-last-input-end | ||
| 2416 | (overlay-start comint-last-prompt-overlay)))) | ||
| 2417 | (when (and help | ||
| 2418 | (not (string= help "\n"))) | ||
| 2419 | help))))) | ||
| 2420 | 2490 | ||
| 2421 | (defun python-eldoc-function () | 2491 | (defun python-eldoc-function () |
| 2422 | "`eldoc-documentation-function' for Python. | 2492 | "`eldoc-documentation-function' for Python. |
| @@ -2429,130 +2499,16 @@ inferior python process is updated properly." | |||
| 2429 | "Get help on SYMBOL using `help'. | 2499 | "Get help on SYMBOL using `help'. |
| 2430 | Interactively, prompt for symbol." | 2500 | Interactively, prompt for symbol." |
| 2431 | (interactive | 2501 | (interactive |
| 2432 | (let ((symbol (with-syntax-table python-dotty-syntax-table | 2502 | (let ((symbol (python-info-current-symbol t)) |
| 2433 | (current-word))) | ||
| 2434 | (enable-recursive-minibuffers t)) | 2503 | (enable-recursive-minibuffers t)) |
| 2435 | (list (read-string (if symbol | 2504 | (list (read-string (if symbol |
| 2436 | (format "Describe symbol (default %s): " symbol) | 2505 | (format "Describe symbol (default %s): " symbol) |
| 2437 | "Describe symbol: ") | 2506 | "Describe symbol: ") |
| 2438 | nil nil symbol)))) | 2507 | nil nil symbol)))) |
| 2439 | (let ((process (python-shell-get-process))) | 2508 | (message (python-eldoc--get-doc-at-point symbol))) |
| 2440 | (if (not process) | ||
| 2441 | (message "Eldoc needs an inferior Python process running.") | ||
| 2442 | (message (python-eldoc--get-doc-at-point symbol process))))) | ||
| 2443 | |||
| 2444 | |||
| 2445 | ;;; Imenu | ||
| 2446 | |||
| 2447 | (defcustom python-imenu-include-defun-type t | ||
| 2448 | "Non-nil make imenu items to include its type." | ||
| 2449 | :type 'boolean | ||
| 2450 | :group 'python | ||
| 2451 | :safe 'booleanp) | ||
| 2452 | |||
| 2453 | (defcustom python-imenu-make-tree t | ||
| 2454 | "Non-nil make imenu to build a tree menu. | ||
| 2455 | Set to nil for speed." | ||
| 2456 | :type 'boolean | ||
| 2457 | :group 'python | ||
| 2458 | :safe 'booleanp) | ||
| 2459 | 2509 | ||
| 2460 | (defcustom python-imenu-subtree-root-label "<Jump to %s>" | 2510 | (add-to-list 'debug-ignored-errors |
| 2461 | "Label displayed to navigate to root from a subtree. | 2511 | "^Eldoc needs an inferior Python process running.") |
| 2462 | It can contain a \"%s\" which will be replaced with the root name." | ||
| 2463 | :type 'string | ||
| 2464 | :group 'python | ||
| 2465 | :safe 'stringp) | ||
| 2466 | |||
| 2467 | (defvar python-imenu-index-alist nil | ||
| 2468 | "Calculated index tree for imenu.") | ||
| 2469 | |||
| 2470 | (defun python-imenu-tree-assoc (keylist tree) | ||
| 2471 | "Using KEYLIST traverse TREE." | ||
| 2472 | (if keylist | ||
| 2473 | (python-imenu-tree-assoc (cdr keylist) | ||
| 2474 | (ignore-errors (assoc (car keylist) tree))) | ||
| 2475 | tree)) | ||
| 2476 | |||
| 2477 | (defun python-imenu-make-element-tree (element-list full-element plain-index) | ||
| 2478 | "Make a tree from plain alist of module names. | ||
| 2479 | ELEMENT-LIST is the defun name split by \".\" and FULL-ELEMENT | ||
| 2480 | is the same thing, the difference is that FULL-ELEMENT remains | ||
| 2481 | untouched in all recursive calls. | ||
| 2482 | Argument PLAIN-INDEX is the calculated plain index used to build the tree." | ||
| 2483 | (when (not (python-imenu-tree-assoc full-element python-imenu-index-alist)) | ||
| 2484 | (when element-list | ||
| 2485 | (let* ((subelement-point (cdr (assoc | ||
| 2486 | (mapconcat #'identity full-element ".") | ||
| 2487 | plain-index))) | ||
| 2488 | (subelement-name (car element-list)) | ||
| 2489 | (subelement-position (python-util-position | ||
| 2490 | subelement-name full-element)) | ||
| 2491 | (subelement-path (when subelement-position | ||
| 2492 | (butlast | ||
| 2493 | full-element | ||
| 2494 | (- (length full-element) | ||
| 2495 | subelement-position))))) | ||
| 2496 | (let ((path-ref (python-imenu-tree-assoc subelement-path | ||
| 2497 | python-imenu-index-alist))) | ||
| 2498 | (if (not path-ref) | ||
| 2499 | (push (cons subelement-name subelement-point) | ||
| 2500 | python-imenu-index-alist) | ||
| 2501 | (when (not (listp (cdr path-ref))) | ||
| 2502 | ;; Modify root cdr to be a list. | ||
| 2503 | (setcdr path-ref | ||
| 2504 | (list (cons (format python-imenu-subtree-root-label | ||
| 2505 | (car path-ref)) | ||
| 2506 | (cdr (assoc | ||
| 2507 | (mapconcat #'identity | ||
| 2508 | subelement-path ".") | ||
| 2509 | plain-index)))))) | ||
| 2510 | (when (not (assoc subelement-name path-ref)) | ||
| 2511 | (push (cons subelement-name subelement-point) (cdr path-ref)))))) | ||
| 2512 | (python-imenu-make-element-tree (cdr element-list) | ||
| 2513 | full-element plain-index)))) | ||
| 2514 | |||
| 2515 | (defun python-imenu-make-tree (index) | ||
| 2516 | "Build the imenu alist tree from plain INDEX. | ||
| 2517 | |||
| 2518 | The idea of this function is that given the alist: | ||
| 2519 | |||
| 2520 | '((\"Test\" . 100) | ||
| 2521 | (\"Test.__init__\" . 200) | ||
| 2522 | (\"Test.some_method\" . 300) | ||
| 2523 | (\"Test.some_method.another\" . 400) | ||
| 2524 | (\"Test.something_else\" . 500) | ||
| 2525 | (\"test\" . 600) | ||
| 2526 | (\"test.reprint\" . 700) | ||
| 2527 | (\"test.reprint\" . 800)) | ||
| 2528 | |||
| 2529 | This tree gets built: | ||
| 2530 | |||
| 2531 | '((\"Test\" . ((\"jump to...\" . 100) | ||
| 2532 | (\"__init__\" . 200) | ||
| 2533 | (\"some_method\" . ((\"jump to...\" . 300) | ||
| 2534 | (\"another\" . 400))) | ||
| 2535 | (\"something_else\" . 500))) | ||
| 2536 | (\"test\" . ((\"jump to...\" . 600) | ||
| 2537 | (\"reprint\" . 700) | ||
| 2538 | (\"reprint\" . 800)))) | ||
| 2539 | |||
| 2540 | Internally it uses `python-imenu-make-element-tree' to create all | ||
| 2541 | branches for each element." | ||
| 2542 | (setq python-imenu-index-alist nil) | ||
| 2543 | (mapc (lambda (element) | ||
| 2544 | (python-imenu-make-element-tree element element index)) | ||
| 2545 | (mapcar (lambda (element) | ||
| 2546 | (split-string (car element) "\\." t)) index)) | ||
| 2547 | python-imenu-index-alist) | ||
| 2548 | |||
| 2549 | (defun python-imenu-create-index () | ||
| 2550 | "`imenu-create-index-function' for Python." | ||
| 2551 | (let ((index | ||
| 2552 | (python-nav-list-defun-positions python-imenu-include-defun-type))) | ||
| 2553 | (if python-imenu-make-tree | ||
| 2554 | (python-imenu-make-tree index) | ||
| 2555 | index))) | ||
| 2556 | 2512 | ||
| 2557 | 2513 | ||
| 2558 | ;;; Misc helpers | 2514 | ;;; Misc helpers |
| @@ -2564,18 +2520,27 @@ This function is compatible to be used as | |||
| 2564 | `add-log-current-defun-function' since it returns nil if point is | 2520 | `add-log-current-defun-function' since it returns nil if point is |
| 2565 | not inside a defun." | 2521 | not inside a defun." |
| 2566 | (let ((names '()) | 2522 | (let ((names '()) |
| 2567 | (min-indent) | 2523 | (starting-indentation) |
| 2524 | (starting-point) | ||
| 2568 | (first-run t)) | 2525 | (first-run t)) |
| 2569 | (save-restriction | 2526 | (save-restriction |
| 2570 | (widen) | 2527 | (widen) |
| 2571 | (save-excursion | 2528 | (save-excursion |
| 2529 | (setq starting-point (point-marker)) | ||
| 2530 | (setq starting-indentation (save-excursion | ||
| 2531 | (python-nav-beginning-of-statement) | ||
| 2532 | (current-indentation))) | ||
| 2572 | (end-of-line 1) | 2533 | (end-of-line 1) |
| 2573 | (setq min-indent (current-indentation)) | ||
| 2574 | (while (python-beginning-of-defun-function 1) | 2534 | (while (python-beginning-of-defun-function 1) |
| 2575 | (when (or (< (current-indentation) min-indent) | 2535 | (when (or (< (current-indentation) starting-indentation) |
| 2576 | first-run) | 2536 | (and first-run |
| 2537 | (< | ||
| 2538 | starting-point | ||
| 2539 | (save-excursion | ||
| 2540 | (python-end-of-defun-function) | ||
| 2541 | (point-marker))))) | ||
| 2577 | (setq first-run nil) | 2542 | (setq first-run nil) |
| 2578 | (setq min-indent (current-indentation)) | 2543 | (setq starting-indentation (current-indentation)) |
| 2579 | (looking-at python-nav-beginning-of-defun-regexp) | 2544 | (looking-at python-nav-beginning-of-defun-regexp) |
| 2580 | (setq names (cons | 2545 | (setq names (cons |
| 2581 | (if (not include-type) | 2546 | (if (not include-type) |
| @@ -2587,6 +2552,36 @@ not inside a defun." | |||
| 2587 | (when names | 2552 | (when names |
| 2588 | (mapconcat (lambda (string) string) names ".")))) | 2553 | (mapconcat (lambda (string) string) names ".")))) |
| 2589 | 2554 | ||
| 2555 | (defun python-info-current-symbol (&optional replace-self) | ||
| 2556 | "Return current symbol using dotty syntax. | ||
| 2557 | With optional argument REPLACE-SELF convert \"self\" to current | ||
| 2558 | parent defun name." | ||
| 2559 | (let ((name | ||
| 2560 | (and (not (python-info-ppss-comment-or-string-p)) | ||
| 2561 | (with-syntax-table python-dotty-syntax-table | ||
| 2562 | (let ((sym (symbol-at-point))) | ||
| 2563 | (and sym | ||
| 2564 | (substring-no-properties (symbol-name sym)))))))) | ||
| 2565 | (when name | ||
| 2566 | (if (not replace-self) | ||
| 2567 | name | ||
| 2568 | (let ((current-defun (python-info-current-defun))) | ||
| 2569 | (if (not current-defun) | ||
| 2570 | name | ||
| 2571 | (replace-regexp-in-string | ||
| 2572 | (python-rx line-start word-start "self" word-end ?.) | ||
| 2573 | (concat | ||
| 2574 | (mapconcat 'identity | ||
| 2575 | (butlast (split-string current-defun "\\.")) | ||
| 2576 | ".") ".") | ||
| 2577 | name))))))) | ||
| 2578 | |||
| 2579 | (defsubst python-info-beginning-of-block-statement-p () | ||
| 2580 | "Return non-nil if current statement opens a block." | ||
| 2581 | (save-excursion | ||
| 2582 | (python-nav-beginning-of-statement) | ||
| 2583 | (looking-at (python-rx block-start)))) | ||
| 2584 | |||
| 2590 | (defun python-info-closing-block () | 2585 | (defun python-info-closing-block () |
| 2591 | "Return the point of the block the current line closes." | 2586 | "Return the point of the block the current line closes." |
| 2592 | (let ((closing-word (save-excursion | 2587 | (let ((closing-word (save-excursion |
| @@ -2678,24 +2673,20 @@ where the continued line ends." | |||
| 2678 | (cond ((equal context-type 'paren) | 2673 | (cond ((equal context-type 'paren) |
| 2679 | ;; Lines inside a paren are always a continuation line | 2674 | ;; Lines inside a paren are always a continuation line |
| 2680 | ;; (except the first one). | 2675 | ;; (except the first one). |
| 2681 | (when (equal (python-info-ppss-context-type) 'paren) | 2676 | (python-util-forward-comment -1) |
| 2682 | (python-util-forward-comment -1) | 2677 | (point-marker)) |
| 2683 | (python-util-forward-comment -1) | 2678 | ((member context-type '(string comment)) |
| 2684 | (point-marker))) | ||
| 2685 | ((or (equal context-type 'comment) | ||
| 2686 | (equal context-type 'string)) | ||
| 2687 | ;; move forward an roll again | 2679 | ;; move forward an roll again |
| 2688 | (goto-char context-start) | 2680 | (goto-char context-start) |
| 2689 | (python-util-forward-comment) | 2681 | (python-util-forward-comment) |
| 2690 | (python-info-continuation-line-p)) | 2682 | (python-info-continuation-line-p)) |
| 2691 | (t | 2683 | (t |
| 2692 | ;; Not within a paren, string or comment, the only way we are | 2684 | ;; Not within a paren, string or comment, the only way |
| 2693 | ;; dealing with a continuation line is that previous line | 2685 | ;; we are dealing with a continuation line is that |
| 2694 | ;; contains a backslash, and this can only be the previous line | 2686 | ;; previous line contains a backslash, and this can |
| 2695 | ;; from current | 2687 | ;; only be the previous line from current |
| 2696 | (back-to-indentation) | 2688 | (back-to-indentation) |
| 2697 | (python-util-forward-comment -1) | 2689 | (python-util-forward-comment -1) |
| 2698 | (python-util-forward-comment -1) | ||
| 2699 | (when (and (equal (1- line-start) (line-number-at-pos)) | 2690 | (when (and (equal (1- line-start) (line-number-at-pos)) |
| 2700 | (python-info-line-ends-backslash-p)) | 2691 | (python-info-line-ends-backslash-p)) |
| 2701 | (point-marker)))))))) | 2692 | (point-marker)))))))) |
| @@ -2723,40 +2714,37 @@ operator." | |||
| 2723 | assignment-operator | 2714 | assignment-operator |
| 2724 | not-simple-operator) | 2715 | not-simple-operator) |
| 2725 | (line-end-position) t) | 2716 | (line-end-position) t) |
| 2726 | (not (or (python-info-ppss-context 'string) | 2717 | (not (python-info-ppss-context-type)))) |
| 2727 | (python-info-ppss-context 'paren) | ||
| 2728 | (python-info-ppss-context 'comment))))) | ||
| 2729 | (skip-syntax-forward "\s") | 2718 | (skip-syntax-forward "\s") |
| 2730 | (point-marker))))) | 2719 | (point-marker))))) |
| 2731 | 2720 | ||
| 2732 | (defun python-info-ppss-context (type &optional syntax-ppss) | 2721 | (defun python-info-ppss-context (type &optional syntax-ppss) |
| 2733 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. | 2722 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. |
| 2734 | TYPE can be 'comment, 'string or 'paren. It returns the start | 2723 | TYPE can be `comment', `string' or `paren'. It returns the start |
| 2735 | character address of the specified TYPE." | 2724 | character address of the specified TYPE." |
| 2736 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | 2725 | (let ((ppss (or syntax-ppss (syntax-ppss)))) |
| 2737 | (case type | 2726 | (case type |
| 2738 | ('comment | 2727 | (comment |
| 2739 | (and (nth 4 ppss) | 2728 | (and (nth 4 ppss) |
| 2740 | (nth 8 ppss))) | 2729 | (nth 8 ppss))) |
| 2741 | ('string | 2730 | (string |
| 2742 | (nth 8 ppss)) | 2731 | (and (not (nth 4 ppss)) |
| 2743 | ('paren | 2732 | (nth 8 ppss))) |
| 2733 | (paren | ||
| 2744 | (nth 1 ppss)) | 2734 | (nth 1 ppss)) |
| 2745 | (t nil)))) | 2735 | (t nil)))) |
| 2746 | 2736 | ||
| 2747 | (defun python-info-ppss-context-type (&optional syntax-ppss) | 2737 | (defun python-info-ppss-context-type (&optional syntax-ppss) |
| 2748 | "Return the context type using SYNTAX-PPSS. | 2738 | "Return the context type using SYNTAX-PPSS. |
| 2749 | The type returned can be 'comment, 'string or 'paren." | 2739 | The type returned can be `comment', `string' or `paren'." |
| 2750 | (let ((ppss (or syntax-ppss (syntax-ppss)))) | 2740 | (let ((ppss (or syntax-ppss (syntax-ppss)))) |
| 2751 | (cond | 2741 | (cond |
| 2752 | ((and (nth 4 ppss) | 2742 | ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string)) |
| 2753 | (nth 8 ppss)) | 2743 | ((nth 1 ppss) 'paren)))) |
| 2754 | 'comment) | 2744 | |
| 2755 | ((nth 8 ppss) | 2745 | (defsubst python-info-ppss-comment-or-string-p () |
| 2756 | 'string) | 2746 | "Return non-nil if point is inside 'comment or 'string." |
| 2757 | ((nth 1 ppss) | 2747 | (nth 8 (syntax-ppss))) |
| 2758 | 'paren) | ||
| 2759 | (t nil)))) | ||
| 2760 | 2748 | ||
| 2761 | (defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) | 2749 | (defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) |
| 2762 | "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." | 2750 | "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." |
| @@ -2765,6 +2753,20 @@ The type returned can be 'comment, 'string or 'paren." | |||
| 2765 | (beginning-of-line 1) | 2753 | (beginning-of-line 1) |
| 2766 | (looking-at python-nav-beginning-of-defun-regexp)))) | 2754 | (looking-at python-nav-beginning-of-defun-regexp)))) |
| 2767 | 2755 | ||
| 2756 | (defun python-info-current-line-comment-p () | ||
| 2757 | "Check if current line is a comment line." | ||
| 2758 | (char-equal (or (char-after (+ (point) (current-indentation))) ?_) ?#)) | ||
| 2759 | |||
| 2760 | (defun python-info-current-line-empty-p () | ||
| 2761 | "Check if current line is empty, ignoring whitespace." | ||
| 2762 | (save-excursion | ||
| 2763 | (beginning-of-line 1) | ||
| 2764 | (looking-at | ||
| 2765 | (python-rx line-start (* whitespace) | ||
| 2766 | (group (* not-newline)) | ||
| 2767 | (* whitespace) line-end)) | ||
| 2768 | (string-equal "" (match-string-no-properties 1)))) | ||
| 2769 | |||
| 2768 | 2770 | ||
| 2769 | ;;; Utility functions | 2771 | ;;; Utility functions |
| 2770 | 2772 | ||
| @@ -2817,6 +2819,9 @@ if that value is non-nil." | |||
| 2817 | (set (make-local-variable 'parse-sexp-lookup-properties) t) | 2819 | (set (make-local-variable 'parse-sexp-lookup-properties) t) |
| 2818 | (set (make-local-variable 'parse-sexp-ignore-comments) t) | 2820 | (set (make-local-variable 'parse-sexp-ignore-comments) t) |
| 2819 | 2821 | ||
| 2822 | (set (make-local-variable 'forward-sexp-function) | ||
| 2823 | 'python-nav-forward-sexp-function) | ||
| 2824 | |||
| 2820 | (set (make-local-variable 'font-lock-defaults) | 2825 | (set (make-local-variable 'font-lock-defaults) |
| 2821 | '(python-font-lock-keywords nil nil nil nil)) | 2826 | '(python-font-lock-keywords nil nil nil nil)) |
| 2822 | 2827 | ||
| @@ -2842,7 +2847,8 @@ if that value is non-nil." | |||
| 2842 | (add-hook 'post-self-insert-hook | 2847 | (add-hook 'post-self-insert-hook |
| 2843 | 'python-indent-post-self-insert-function nil 'local) | 2848 | 'python-indent-post-self-insert-function nil 'local) |
| 2844 | 2849 | ||
| 2845 | (setq imenu-create-index-function #'python-imenu-create-index) | 2850 | (set (make-local-variable 'imenu-extract-index-name-function) |
| 2851 | #'python-info-current-defun) | ||
| 2846 | 2852 | ||
| 2847 | (set (make-local-variable 'add-log-current-defun-function) | 2853 | (set (make-local-variable 'add-log-current-defun-function) |
| 2848 | #'python-info-current-defun) | 2854 | #'python-info-current-defun) |
| @@ -2880,4 +2886,10 @@ if that value is non-nil." | |||
| 2880 | 2886 | ||
| 2881 | 2887 | ||
| 2882 | (provide 'python) | 2888 | (provide 'python) |
| 2889 | |||
| 2890 | ;; Local Variables: | ||
| 2891 | ;; coding: utf-8 | ||
| 2892 | ;; indent-tabs-mode: nil | ||
| 2893 | ;; End: | ||
| 2894 | |||
| 2883 | ;;; python.el ends here | 2895 | ;;; python.el ends here |