aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorJoakim Verona2012-07-27 02:22:03 +0200
committerJoakim Verona2012-07-27 02:22:03 +0200
commit5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f (patch)
tree5c55f1096a656a9759f0b53a0b5d1a2289bd366f /lisp/progmodes/python.el
parent0c5c85cf2b350c965bb1ffa5b2d77c2adebc406b (diff)
parent562157c814037dcba58a20cd6908a95992c22283 (diff)
downloademacs-5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f.tar.gz
emacs-5fb63197843dcae66f2fe0ddd6f4a9d560e9db2f.zip
upstream
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el626
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.
1126See `python-nav-forward-sentence' for more information." 1121With 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.
1133With negative argument, move backward repeatedly to start of sentence." 1128With ARG, repeat. With negative argument, move ARG times
1129backward 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
1153When optional argument INCLUDE-TYPE is non-nil the type is 1148 line-start (* whitespace) block-start)))
1154included 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)
1156list 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."
1176A cons cell with the form (DEFUN-NAME . POINT-MARKER) is returned 1171 (interactive "^")
1177when defun is completed, else nil. With optional argument RESCAN 1172 (when (python-nav-beginning-of-block)
1178forces `python-nav-list-defun-positions' to invalidate its 1173 (let ((block-indentation (current-indentation)))
1179cache." 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) 1186With ARG, repeat. See `python-nav-forward-block'."
1192 "Jump to the definition of DEF in current file. 1187 (interactive "^p")
1193Locations are cached; use a `C-u' prefix argument to force a 1188 (or arg (setq arg 1))
1194rescan." 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)))) 1193With ARG, repeat. With negative argument, move ARG times
1199 (let ((def-marker (cdr def))) 1194backward 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.
1219With ARG, do it that many times. Negative arg -N means
1220move 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.
1601When MSG is non-nil messages the first line of STRING. Return 1693When MSG is non-nil messages the first line of STRING. Return
1602the output." 1694the 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.
2380If not FORCE-INPUT is passed then what `current-word' returns 2477If not FORCE-INPUT is passed then what
2381will 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." 2479FORCE-PROCESS is passed what `python-shell-get-process' returns
2480is 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'.
2430Interactively, prompt for symbol." 2500Interactively, 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.
2455Set 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.")
2462It 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.
2479ELEMENT-LIST is the defun name split by \".\" and FULL-ELEMENT
2480is the same thing, the difference is that FULL-ELEMENT remains
2481untouched in all recursive calls.
2482Argument 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
2518The 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
2529This 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
2540Internally it uses `python-imenu-make-element-tree' to create all
2541branches 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
2565not inside a defun." 2521not 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.
2557With optional argument REPLACE-SELF convert \"self\" to current
2558parent 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.
2734TYPE can be 'comment, 'string or 'paren. It returns the start 2723TYPE can be `comment', `string' or `paren'. It returns the start
2735character address of the specified TYPE." 2724character 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.
2749The type returned can be 'comment, 'string or 'paren." 2739The 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