diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 732 |
1 files changed, 463 insertions, 269 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f5e4bffd598..ff805d64024 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -229,12 +229,9 @@ | |||
| 229 | (defvar python-mode-map | 229 | (defvar python-mode-map |
| 230 | (let ((map (make-sparse-keymap))) | 230 | (let ((map (make-sparse-keymap))) |
| 231 | ;; Movement | 231 | ;; Movement |
| 232 | (substitute-key-definition 'backward-sentence | 232 | (define-key map [remap backward-sentence] 'python-nav-backward-block) |
| 233 | 'python-nav-backward-block | 233 | (define-key map [remap forward-sentence] 'python-nav-forward-block) |
| 234 | map global-map) | 234 | (define-key map [remap backward-up-list] 'python-nav-backward-up-list) |
| 235 | (substitute-key-definition 'forward-sentence | ||
| 236 | 'python-nav-forward-block | ||
| 237 | map global-map) | ||
| 238 | (define-key map "\C-c\C-j" 'imenu) | 235 | (define-key map "\C-c\C-j" 'imenu) |
| 239 | ;; Indent specific | 236 | ;; Indent specific |
| 240 | (define-key map "\177" 'python-indent-dedent-line-backspace) | 237 | (define-key map "\177" 'python-indent-dedent-line-backspace) |
| @@ -337,19 +334,28 @@ | |||
| 337 | "==" ">=" "is" "not"))) | 334 | "==" ">=" "is" "not"))) |
| 338 | ;; FIXME: Use regexp-opt. | 335 | ;; FIXME: Use regexp-opt. |
| 339 | (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" | 336 | (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" |
| 340 | ">>=" "<<=" "&=" "^=" "|=")))) | 337 | ">>=" "<<=" "&=" "^=" "|="))) |
| 341 | "Additional Python specific sexps for `python-rx'")) | 338 | (string-delimiter . ,(rx (and |
| 342 | 339 | ;; Match even number of backslashes. | |
| 343 | (defmacro python-rx (&rest regexps) | 340 | (or (not (any ?\\ ?\' ?\")) point |
| 344 | "Python mode specialized rx macro. | 341 | ;; Quotes might be preceded by a escaped quote. |
| 342 | (and (or (not (any ?\\)) point) ?\\ | ||
| 343 | (* ?\\ ?\\) (any ?\' ?\"))) | ||
| 344 | (* ?\\ ?\\) | ||
| 345 | ;; Match single or triple quotes of any kind. | ||
| 346 | (group (or "\"" "\"\"\"" "'" "'''")))))) | ||
| 347 | "Additional Python specific sexps for `python-rx'") | ||
| 348 | |||
| 349 | (defmacro python-rx (&rest regexps) | ||
| 350 | "Python mode specialized rx macro. | ||
| 345 | This variant of `rx' supports common python named REGEXPS." | 351 | This variant of `rx' supports common python named REGEXPS." |
| 346 | (let ((rx-constituents (append python-rx-constituents rx-constituents))) | 352 | (let ((rx-constituents (append python-rx-constituents rx-constituents))) |
| 347 | (cond ((null regexps) | 353 | (cond ((null regexps) |
| 348 | (error "No regexp")) | 354 | (error "No regexp")) |
| 349 | ((cdr regexps) | 355 | ((cdr regexps) |
| 350 | (rx-to-string `(and ,@regexps) t)) | 356 | (rx-to-string `(and ,@regexps) t)) |
| 351 | (t | 357 | (t |
| 352 | (rx-to-string (car regexps) t))))) | 358 | (rx-to-string (car regexps) t)))))) |
| 353 | 359 | ||
| 354 | 360 | ||
| 355 | ;;; Font-lock and syntax | 361 | ;;; Font-lock and syntax |
| @@ -498,16 +504,7 @@ The type returned can be `comment', `string' or `paren'." | |||
| 498 | 504 | ||
| 499 | (defconst python-syntax-propertize-function | 505 | (defconst python-syntax-propertize-function |
| 500 | (syntax-propertize-rules | 506 | (syntax-propertize-rules |
| 501 | ((rx | 507 | ((python-rx string-delimiter) |
| 502 | (and | ||
| 503 | ;; Match even number of backslashes. | ||
| 504 | (or (not (any ?\\ ?\' ?\")) point | ||
| 505 | ;; Quotes might be preceeded by a escaped quote. | ||
| 506 | (and (or (not (any ?\\)) point) ?\\ | ||
| 507 | (* ?\\ ?\\) (any ?\' ?\"))) | ||
| 508 | (* ?\\ ?\\) | ||
| 509 | ;; Match single or triple quotes of any kind. | ||
| 510 | (group (or "\"" "\"\"\"" "'" "'''")))) | ||
| 511 | (0 (ignore (python-syntax-stringify)))))) | 508 | (0 (ignore (python-syntax-stringify)))))) |
| 512 | 509 | ||
| 513 | (defsubst python-syntax-count-quotes (quote-char &optional point limit) | 510 | (defsubst python-syntax-count-quotes (quote-char &optional point limit) |
| @@ -676,12 +673,12 @@ START is the buffer position where the sexp starts." | |||
| 676 | (goto-char (line-beginning-position)) | 673 | (goto-char (line-beginning-position)) |
| 677 | (bobp)) | 674 | (bobp)) |
| 678 | 'no-indent) | 675 | 'no-indent) |
| 679 | ;; Inside a paren | ||
| 680 | ((setq start (python-syntax-context 'paren ppss)) | ||
| 681 | 'inside-paren) | ||
| 682 | ;; Inside string | 676 | ;; Inside string |
| 683 | ((setq start (python-syntax-context 'string ppss)) | 677 | ((setq start (python-syntax-context 'string ppss)) |
| 684 | 'inside-string) | 678 | 'inside-string) |
| 679 | ;; Inside a paren | ||
| 680 | ((setq start (python-syntax-context 'paren ppss)) | ||
| 681 | 'inside-paren) | ||
| 685 | ;; After backslash | 682 | ;; After backslash |
| 686 | ((setq start (when (not (or (python-syntax-context 'string ppss) | 683 | ((setq start (when (not (or (python-syntax-context 'string ppss) |
| 687 | (python-syntax-context 'comment ppss))) | 684 | (python-syntax-context 'comment ppss))) |
| @@ -710,7 +707,7 @@ START is the buffer position where the sexp starts." | |||
| 710 | ;; After normal line | 707 | ;; After normal line |
| 711 | ((setq start (save-excursion | 708 | ((setq start (save-excursion |
| 712 | (back-to-indentation) | 709 | (back-to-indentation) |
| 713 | (python-util-forward-comment -1) | 710 | (skip-chars-backward (rx (or whitespace ?\n))) |
| 714 | (python-nav-beginning-of-statement) | 711 | (python-nav-beginning-of-statement) |
| 715 | (point-marker))) | 712 | (point-marker))) |
| 716 | 'after-line) | 713 | 'after-line) |
| @@ -973,7 +970,16 @@ Called from a program, START and END specify the region to indent." | |||
| 973 | (back-to-indentation) | 970 | (back-to-indentation) |
| 974 | (setq word (current-word)) | 971 | (setq word (current-word)) |
| 975 | (forward-line 1) | 972 | (forward-line 1) |
| 976 | (when word | 973 | (when (and word |
| 974 | ;; Don't mess with strings, unless it's the | ||
| 975 | ;; enclosing set of quotes. | ||
| 976 | (or (not (python-syntax-context 'string)) | ||
| 977 | (eq | ||
| 978 | (syntax-after | ||
| 979 | (+ (1- (point)) | ||
| 980 | (current-indentation) | ||
| 981 | (python-syntax-count-quotes (char-after) (point)))) | ||
| 982 | (string-to-syntax "|")))) | ||
| 977 | (beginning-of-line) | 983 | (beginning-of-line) |
| 978 | (delete-horizontal-space) | 984 | (delete-horizontal-space) |
| 979 | (indent-to (python-indent-calculate-indentation))))) | 985 | (indent-to (python-indent-calculate-indentation))))) |
| @@ -1160,7 +1166,8 @@ Returns nil if point is not in a def or class." | |||
| 1160 | (python-info-line-ends-backslash-p)) | 1166 | (python-info-line-ends-backslash-p)) |
| 1161 | (python-syntax-context 'string) | 1167 | (python-syntax-context 'string) |
| 1162 | (python-syntax-context 'paren)) | 1168 | (python-syntax-context 'paren)) |
| 1163 | (forward-line -1))))) | 1169 | (forward-line -1)))) |
| 1170 | (point-marker)) | ||
| 1164 | 1171 | ||
| 1165 | (defun python-nav-end-of-statement () | 1172 | (defun python-nav-end-of-statement () |
| 1166 | "Move to end of current statement." | 1173 | "Move to end of current statement." |
| @@ -1171,7 +1178,8 @@ Returns nil if point is not in a def or class." | |||
| 1171 | (python-info-line-ends-backslash-p) | 1178 | (python-info-line-ends-backslash-p) |
| 1172 | (python-syntax-context 'string) | 1179 | (python-syntax-context 'string) |
| 1173 | (python-syntax-context 'paren)) | 1180 | (python-syntax-context 'paren)) |
| 1174 | (forward-line 1))))) | 1181 | (forward-line 1)))) |
| 1182 | (point-marker)) | ||
| 1175 | 1183 | ||
| 1176 | (defun python-nav-backward-statement (&optional arg) | 1184 | (defun python-nav-backward-statement (&optional arg) |
| 1177 | "Move backward to previous statement. | 1185 | "Move backward to previous statement. |
| @@ -1286,151 +1294,104 @@ When ARG > 0 move forward, else if ARG is < 0." | |||
| 1286 | (while (and (funcall search-fn paren-regexp nil t) | 1294 | (while (and (funcall search-fn paren-regexp nil t) |
| 1287 | (python-syntax-context 'paren))))))) | 1295 | (python-syntax-context 'paren))))))) |
| 1288 | 1296 | ||
| 1289 | (defun python-nav--forward-sexp () | 1297 | (defun python-nav--forward-sexp (&optional dir) |
| 1290 | "Move to forward sexp." | 1298 | "Move to forward sexp. |
| 1291 | (case (python-syntax-context-type) | 1299 | With positive Optional argument DIR direction move forward, else |
| 1292 | (string | 1300 | backwards." |
| 1293 | ;; Inside of a string, get out of it. | 1301 | (setq dir (or dir 1)) |
| 1294 | (while (and (re-search-forward "[\"']" nil t) | 1302 | (unless (= dir 0) |
| 1295 | (python-syntax-context 'string)))) | 1303 | (let* ((forward-p (if (> dir 0) |
| 1296 | (comment | 1304 | (and (setq dir 1) t) |
| 1297 | ;; Inside of a comment, just move forward. | 1305 | (and (setq dir -1) nil))) |
| 1298 | (python-util-forward-comment)) | 1306 | (re-search-fn (if forward-p |
| 1299 | (paren | 1307 | 're-search-forward |
| 1300 | (python-nav-lisp-forward-sexp-safe 1)) | 1308 | 're-search-backward)) |
| 1301 | (t | 1309 | (context-type (python-syntax-context-type))) |
| 1302 | (if (and (not (eobp)) | 1310 | (cond |
| 1303 | (= (syntax-class (syntax-after (point))) 4)) | 1311 | ((eq context-type 'string) |
| 1304 | ;; Looking an open-paren | 1312 | ;; Inside of a string, get out of it. |
| 1305 | (python-nav-lisp-forward-sexp-safe 1) | 1313 | (while (and (funcall re-search-fn "[\"']" nil t) |
| 1306 | (let ((block-starting-pos | 1314 | (python-syntax-context 'string)))) |
| 1307 | (save-excursion (python-nav-beginning-of-block))) | 1315 | ((eq context-type 'comment) |
| 1308 | (block-ending-pos | 1316 | ;; Inside of a comment, just move forward. |
| 1309 | (save-excursion (python-nav-end-of-block))) | 1317 | (python-util-forward-comment dir)) |
| 1310 | (next-block-starting-pos | 1318 | ((or (eq context-type 'paren) |
| 1311 | (save-excursion (python-nav-forward-block)))) | 1319 | (and forward-p (looking-at (python-rx open-paren))) |
| 1312 | (cond | 1320 | (and (not forward-p) |
| 1313 | ((not block-starting-pos) | 1321 | (eq (syntax-class (syntax-after (1- (point)))) |
| 1314 | ;; Not inside a block, move to closest one. | 1322 | (car (string-to-syntax ")"))))) |
| 1315 | (and next-block-starting-pos | 1323 | ;; Inside a paren or looking at it, lisp knows what to do. |
| 1316 | (goto-char next-block-starting-pos))) | 1324 | (python-nav-lisp-forward-sexp-safe dir)) |
| 1317 | ((= (point) block-starting-pos) | 1325 | (t |
| 1318 | ;; Point is at beginning of block | 1326 | ;; This part handles the lispy feel of |
| 1319 | (if (and next-block-starting-pos | 1327 | ;; `python-nav-forward-sexp'. Knowing everything about the |
| 1320 | (< next-block-starting-pos block-ending-pos)) | 1328 | ;; current context and the context of the next sexp tries to |
| 1321 | ;; Beginning of next block is closer than current's | 1329 | ;; follow the lisp sexp motion commands in a symmetric manner. |
| 1322 | ;; end, move to it. | 1330 | (let* ((context |
| 1323 | (goto-char next-block-starting-pos) | 1331 | (cond |
| 1324 | (goto-char block-ending-pos))) | 1332 | ((python-info-beginning-of-block-p) 'block-start) |
| 1325 | ((= block-ending-pos (point)) | 1333 | ((python-info-end-of-block-p) 'block-end) |
| 1326 | ;; Point is at end of current block | 1334 | ((python-info-beginning-of-statement-p) 'statement-start) |
| 1327 | (let ((parent-block-end-pos | 1335 | ((python-info-end-of-statement-p) 'statement-end))) |
| 1328 | (save-excursion | 1336 | (next-sexp-pos |
| 1329 | (python-util-forward-comment) | 1337 | (save-excursion |
| 1330 | (python-nav-beginning-of-block) | 1338 | (python-nav-lisp-forward-sexp-safe dir) |
| 1331 | (python-nav-end-of-block)))) | 1339 | (point))) |
| 1332 | (if (and parent-block-end-pos | 1340 | (next-sexp-context |
| 1333 | (or (not next-block-starting-pos) | 1341 | (save-excursion |
| 1334 | (> next-block-starting-pos parent-block-end-pos))) | 1342 | (goto-char next-sexp-pos) |
| 1335 | ;; If the parent block ends before next block | 1343 | (cond |
| 1336 | ;; starts move to it. | 1344 | ((python-info-beginning-of-block-p) 'block-start) |
| 1337 | (goto-char parent-block-end-pos) | 1345 | ((python-info-end-of-block-p) 'block-end) |
| 1338 | (and next-block-starting-pos | 1346 | ((python-info-beginning-of-statement-p) 'statement-start) |
| 1339 | (goto-char next-block-starting-pos))))) | 1347 | ((python-info-end-of-statement-p) 'statement-end) |
| 1340 | (t (python-nav-end-of-block)))))))) | 1348 | ((python-info-statement-starts-block-p) 'starts-block) |
| 1349 | ((python-info-statement-ends-block-p) 'ends-block))))) | ||
| 1350 | (if forward-p | ||
| 1351 | (cond ((and (not (eobp)) | ||
| 1352 | (python-info-current-line-empty-p)) | ||
| 1353 | (python-util-forward-comment dir) | ||
| 1354 | (python-nav--forward-sexp dir)) | ||
| 1355 | ((eq context 'block-start) | ||
| 1356 | (python-nav-end-of-block)) | ||
| 1357 | ((eq context 'statement-start) | ||
| 1358 | (python-nav-end-of-statement)) | ||
| 1359 | ((and (memq context '(statement-end block-end)) | ||
| 1360 | (eq next-sexp-context 'ends-block)) | ||
| 1361 | (goto-char next-sexp-pos) | ||
| 1362 | (python-nav-end-of-block)) | ||
| 1363 | ((and (memq context '(statement-end block-end)) | ||
| 1364 | (eq next-sexp-context 'starts-block)) | ||
| 1365 | (goto-char next-sexp-pos) | ||
| 1366 | (python-nav-end-of-block)) | ||
| 1367 | ((memq context '(statement-end block-end)) | ||
| 1368 | (goto-char next-sexp-pos) | ||
| 1369 | (python-nav-end-of-statement)) | ||
| 1370 | (t (goto-char next-sexp-pos))) | ||
| 1371 | (cond ((and (not (bobp)) | ||
| 1372 | (python-info-current-line-empty-p)) | ||
| 1373 | (python-util-forward-comment dir) | ||
| 1374 | (python-nav--forward-sexp dir)) | ||
| 1375 | ((eq context 'block-end) | ||
| 1376 | (python-nav-beginning-of-block)) | ||
| 1377 | ((eq context 'statement-end) | ||
| 1378 | (python-nav-beginning-of-statement)) | ||
| 1379 | ((and (memq context '(statement-start block-start)) | ||
| 1380 | (eq next-sexp-context 'starts-block)) | ||
| 1381 | (goto-char next-sexp-pos) | ||
| 1382 | (python-nav-beginning-of-block)) | ||
| 1383 | ((and (memq context '(statement-start block-start)) | ||
| 1384 | (eq next-sexp-context 'ends-block)) | ||
| 1385 | (goto-char next-sexp-pos) | ||
| 1386 | (python-nav-beginning-of-block)) | ||
| 1387 | ((memq context '(statement-start block-start)) | ||
| 1388 | (goto-char next-sexp-pos) | ||
| 1389 | (python-nav-beginning-of-statement)) | ||
| 1390 | (t (goto-char next-sexp-pos)))))))))) | ||
| 1341 | 1391 | ||
| 1342 | (defun python-nav--backward-sexp () | 1392 | (defun python-nav--backward-sexp () |
| 1343 | "Move to backward sexp." | 1393 | "Move to backward sexp." |
| 1344 | (case (python-syntax-context-type) | 1394 | (python-nav--forward-sexp -1)) |
| 1345 | (string | ||
| 1346 | ;; Inside of a string, get out of it. | ||
| 1347 | (while (and (re-search-backward "[\"']" nil t) | ||
| 1348 | (python-syntax-context 'string)))) | ||
| 1349 | (comment | ||
| 1350 | ;; Inside of a comment, just move backward. | ||
| 1351 | (python-util-forward-comment -1)) | ||
| 1352 | (paren | ||
| 1353 | ;; Handle parens like we are lisp. | ||
| 1354 | (python-nav-lisp-forward-sexp-safe -1)) | ||
| 1355 | (t | ||
| 1356 | (let* ((block-starting-pos | ||
| 1357 | (save-excursion (python-nav-beginning-of-block))) | ||
| 1358 | (block-ending-pos | ||
| 1359 | (save-excursion (python-nav-end-of-block))) | ||
| 1360 | (prev-block-ending-pos | ||
| 1361 | (save-excursion (when (python-nav-backward-block) | ||
| 1362 | (python-nav-end-of-block)))) | ||
| 1363 | (prev-block-parent-ending-pos | ||
| 1364 | (save-excursion | ||
| 1365 | (when prev-block-ending-pos | ||
| 1366 | (goto-char prev-block-ending-pos) | ||
| 1367 | (python-util-forward-comment) | ||
| 1368 | (python-nav-beginning-of-block) | ||
| 1369 | (python-nav-end-of-block))))) | ||
| 1370 | (if (and (not (bobp)) | ||
| 1371 | (= (syntax-class (syntax-after (1- (point)))) 5)) | ||
| 1372 | ;; Char before point is a paren closing char, handle it | ||
| 1373 | ;; like we are lisp. | ||
| 1374 | (python-nav-lisp-forward-sexp-safe -1) | ||
| 1375 | (cond | ||
| 1376 | ((not block-ending-pos) | ||
| 1377 | ;; Not in and ending pos, move to end of previous block. | ||
| 1378 | (and (python-nav-backward-block) | ||
| 1379 | (python-nav-end-of-block))) | ||
| 1380 | ((= (point) block-ending-pos) | ||
| 1381 | ;; In ending pos, we need to search backwards for the | ||
| 1382 | ;; closest point looking the list of candidates from here. | ||
| 1383 | (let ((candidates)) | ||
| 1384 | (dolist (name | ||
| 1385 | '(prev-block-parent-ending-pos | ||
| 1386 | prev-block-ending-pos | ||
| 1387 | block-ending-pos | ||
| 1388 | block-starting-pos)) | ||
| 1389 | (when (and (symbol-value name) | ||
| 1390 | (< (symbol-value name) (point))) | ||
| 1391 | (add-to-list 'candidates (symbol-value name)))) | ||
| 1392 | (goto-char (apply 'max candidates)))) | ||
| 1393 | ((> (point) block-ending-pos) | ||
| 1394 | ;; After an ending position, move to it. | ||
| 1395 | (goto-char block-ending-pos)) | ||
| 1396 | ((= (point) block-starting-pos) | ||
| 1397 | ;; On a block starting position. | ||
| 1398 | (if (not (> (point) (or prev-block-ending-pos (point)))) | ||
| 1399 | ;; Point is after the end position of the block that | ||
| 1400 | ;; wraps the current one, just move a block backward. | ||
| 1401 | (python-nav-backward-block) | ||
| 1402 | ;; If we got here we are facing a case like this one: | ||
| 1403 | ;; | ||
| 1404 | ;; try: | ||
| 1405 | ;; return here() | ||
| 1406 | ;; except Exception as e: | ||
| 1407 | ;; | ||
| 1408 | ;; Where point is on the "except" and must move to the | ||
| 1409 | ;; end of "here()". | ||
| 1410 | (goto-char prev-block-ending-pos) | ||
| 1411 | (let ((parent-block-ending-pos | ||
| 1412 | (save-excursion | ||
| 1413 | (python-nav-forward-sexp) | ||
| 1414 | (and (not (looking-at (python-rx block-start))) | ||
| 1415 | (point))))) | ||
| 1416 | (when (and parent-block-ending-pos | ||
| 1417 | (> parent-block-ending-pos prev-block-ending-pos)) | ||
| 1418 | ;; If we got here we are facing a case like this one: | ||
| 1419 | ;; | ||
| 1420 | ;; except ImportError: | ||
| 1421 | ;; if predicate(): | ||
| 1422 | ;; processing() | ||
| 1423 | ;; here() | ||
| 1424 | ;; except AttributeError: | ||
| 1425 | ;; | ||
| 1426 | ;; Where point is on the "except" and must move to | ||
| 1427 | ;; the end of "here()". Without this extra step we'd | ||
| 1428 | ;; just get to the end of processing(). | ||
| 1429 | (goto-char parent-block-ending-pos))))) | ||
| 1430 | (t | ||
| 1431 | (if (and prev-block-ending-pos (< prev-block-ending-pos (point))) | ||
| 1432 | (goto-char prev-block-ending-pos) | ||
| 1433 | (python-nav-beginning-of-block))))))))) | ||
| 1434 | 1395 | ||
| 1435 | (defun python-nav-forward-sexp (&optional arg) | 1396 | (defun python-nav-forward-sexp (&optional arg) |
| 1436 | "Move forward across one block of code. | 1397 | "Move forward across one block of code. |
| @@ -1445,6 +1406,67 @@ move backward N times." | |||
| 1445 | (python-nav--backward-sexp) | 1406 | (python-nav--backward-sexp) |
| 1446 | (setq arg (1+ arg)))) | 1407 | (setq arg (1+ arg)))) |
| 1447 | 1408 | ||
| 1409 | (defun python-nav--up-list (&optional dir) | ||
| 1410 | "Internal implementation of `python-nav-up-list'. | ||
| 1411 | DIR is always 1 or -1 and comes sanitized from | ||
| 1412 | `python-nav-up-list' calls." | ||
| 1413 | (let ((context (python-syntax-context-type)) | ||
| 1414 | (forward-p (> dir 0))) | ||
| 1415 | (cond | ||
| 1416 | ((memq context '(string comment))) | ||
| 1417 | ((eq context 'paren) | ||
| 1418 | (let ((forward-sexp-function)) | ||
| 1419 | (up-list dir))) | ||
| 1420 | ((and forward-p (python-info-end-of-block-p)) | ||
| 1421 | (let ((parent-end-pos | ||
| 1422 | (save-excursion | ||
| 1423 | (let ((indentation (and | ||
| 1424 | (python-nav-beginning-of-block) | ||
| 1425 | (current-indentation)))) | ||
| 1426 | (while (and indentation | ||
| 1427 | (> indentation 0) | ||
| 1428 | (>= (current-indentation) indentation) | ||
| 1429 | (python-nav-backward-block))) | ||
| 1430 | (python-nav-end-of-block))))) | ||
| 1431 | (and (> (or parent-end-pos (point)) (point)) | ||
| 1432 | (goto-char parent-end-pos)))) | ||
| 1433 | (forward-p (python-nav-end-of-block)) | ||
| 1434 | ((and (not forward-p) | ||
| 1435 | (> (current-indentation) 0) | ||
| 1436 | (python-info-beginning-of-block-p)) | ||
| 1437 | (let ((prev-block-pos | ||
| 1438 | (save-excursion | ||
| 1439 | (let ((indentation (current-indentation))) | ||
| 1440 | (while (and (python-nav-backward-block) | ||
| 1441 | (>= (current-indentation) indentation)))) | ||
| 1442 | (point)))) | ||
| 1443 | (and (> (point) prev-block-pos) | ||
| 1444 | (goto-char prev-block-pos)))) | ||
| 1445 | ((not forward-p) (python-nav-beginning-of-block))))) | ||
| 1446 | |||
| 1447 | (defun python-nav-up-list (&optional arg) | ||
| 1448 | "Move forward out of one level of parentheses (or blocks). | ||
| 1449 | With ARG, do this that many times. | ||
| 1450 | A negative argument means move backward but still to a less deep spot. | ||
| 1451 | This command assumes point is not in a string or comment." | ||
| 1452 | (interactive "^p") | ||
| 1453 | (or arg (setq arg 1)) | ||
| 1454 | (while (> arg 0) | ||
| 1455 | (python-nav--up-list 1) | ||
| 1456 | (setq arg (1- arg))) | ||
| 1457 | (while (< arg 0) | ||
| 1458 | (python-nav--up-list -1) | ||
| 1459 | (setq arg (1+ arg)))) | ||
| 1460 | |||
| 1461 | (defun python-nav-backward-up-list (&optional arg) | ||
| 1462 | "Move backward out of one level of parentheses (or blocks). | ||
| 1463 | With ARG, do this that many times. | ||
| 1464 | A negative argument means move backward but still to a less deep spot. | ||
| 1465 | This command assumes point is not in a string or comment." | ||
| 1466 | (interactive "^p") | ||
| 1467 | (or arg (setq arg 1)) | ||
| 1468 | (python-nav-up-list (- arg))) | ||
| 1469 | |||
| 1448 | 1470 | ||
| 1449 | ;;; Shell integration | 1471 | ;;; Shell integration |
| 1450 | 1472 | ||
| @@ -1643,6 +1665,22 @@ uniqueness for different types of configurations." | |||
| 1643 | OUTPUT is a string with the contents of the buffer." | 1665 | OUTPUT is a string with the contents of the buffer." |
| 1644 | (ansi-color-filter-apply output)) | 1666 | (ansi-color-filter-apply output)) |
| 1645 | 1667 | ||
| 1668 | (defvar python-shell--parent-buffer nil) | ||
| 1669 | |||
| 1670 | (defvar python-shell-output-syntax-table | ||
| 1671 | (let ((table (make-syntax-table python-dotty-syntax-table))) | ||
| 1672 | (modify-syntax-entry ?\' "." table) | ||
| 1673 | (modify-syntax-entry ?\" "." table) | ||
| 1674 | (modify-syntax-entry ?\( "." table) | ||
| 1675 | (modify-syntax-entry ?\[ "." table) | ||
| 1676 | (modify-syntax-entry ?\{ "." table) | ||
| 1677 | (modify-syntax-entry ?\) "." table) | ||
| 1678 | (modify-syntax-entry ?\] "." table) | ||
| 1679 | (modify-syntax-entry ?\} "." table) | ||
| 1680 | table) | ||
| 1681 | "Syntax table for shell output. | ||
| 1682 | It makes parens and quotes be treated as punctuation chars.") | ||
| 1683 | |||
| 1646 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" | 1684 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" |
| 1647 | "Major mode for Python inferior process. | 1685 | "Major mode for Python inferior process. |
| 1648 | Runs a Python interpreter as a subprocess of Emacs, with Python | 1686 | Runs a Python interpreter as a subprocess of Emacs, with Python |
| @@ -1665,12 +1703,13 @@ initialization of the interpreter via `python-shell-setup-codes' | |||
| 1665 | variable. | 1703 | variable. |
| 1666 | 1704 | ||
| 1667 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" | 1705 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" |
| 1668 | (set-syntax-table python-mode-syntax-table) | 1706 | (and python-shell--parent-buffer |
| 1669 | (setq mode-line-process '(":%s")) | 1707 | (python-util-clone-local-variables python-shell--parent-buffer)) |
| 1670 | (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" | 1708 | (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" |
| 1671 | python-shell-prompt-regexp | 1709 | python-shell-prompt-regexp |
| 1672 | python-shell-prompt-block-regexp | 1710 | python-shell-prompt-block-regexp |
| 1673 | python-shell-prompt-pdb-regexp)) | 1711 | python-shell-prompt-pdb-regexp)) |
| 1712 | (setq mode-line-process '(":%s")) | ||
| 1674 | (make-local-variable 'comint-output-filter-functions) | 1713 | (make-local-variable 'comint-output-filter-functions) |
| 1675 | (add-hook 'comint-output-filter-functions | 1714 | (add-hook 'comint-output-filter-functions |
| 1676 | 'python-comint-output-filter-function) | 1715 | 'python-comint-output-filter-function) |
| @@ -1690,10 +1729,21 @@ variable. | |||
| 1690 | (make-local-variable 'python-pdbtrack-tracked-buffer) | 1729 | (make-local-variable 'python-pdbtrack-tracked-buffer) |
| 1691 | (make-local-variable 'python-shell-internal-last-output) | 1730 | (make-local-variable 'python-shell-internal-last-output) |
| 1692 | (when python-shell-enable-font-lock | 1731 | (when python-shell-enable-font-lock |
| 1732 | (set-syntax-table python-mode-syntax-table) | ||
| 1693 | (set (make-local-variable 'font-lock-defaults) | 1733 | (set (make-local-variable 'font-lock-defaults) |
| 1694 | '(python-font-lock-keywords nil nil nil nil)) | 1734 | '(python-font-lock-keywords nil nil nil nil)) |
| 1695 | (set (make-local-variable 'syntax-propertize-function) | 1735 | (set (make-local-variable 'syntax-propertize-function) |
| 1696 | python-syntax-propertize-function)) | 1736 | (syntax-propertize-rules |
| 1737 | (comint-prompt-regexp | ||
| 1738 | (0 (ignore | ||
| 1739 | (put-text-property | ||
| 1740 | comint-last-input-start end 'syntax-table | ||
| 1741 | python-shell-output-syntax-table) | ||
| 1742 | (font-lock-unfontify-region comint-last-input-start end)))) | ||
| 1743 | ((python-rx string-delimiter) | ||
| 1744 | (0 (ignore | ||
| 1745 | (and (not (eq (get-text-property start 'field) 'output)) | ||
| 1746 | (python-syntax-stringify)))))))) | ||
| 1697 | (compilation-shell-minor-mode 1)) | 1747 | (compilation-shell-minor-mode 1)) |
| 1698 | 1748 | ||
| 1699 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) | 1749 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) |
| @@ -1716,11 +1766,10 @@ killed." | |||
| 1716 | (let* ((cmdlist (split-string-and-unquote cmd)) | 1766 | (let* ((cmdlist (split-string-and-unquote cmd)) |
| 1717 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name | 1767 | (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name |
| 1718 | (car cmdlist) nil (cdr cmdlist))) | 1768 | (car cmdlist) nil (cdr cmdlist))) |
| 1719 | (current-buffer (current-buffer)) | 1769 | (python-shell--parent-buffer (current-buffer)) |
| 1720 | (process (get-buffer-process buffer))) | 1770 | (process (get-buffer-process buffer))) |
| 1721 | (with-current-buffer buffer | 1771 | (with-current-buffer buffer |
| 1722 | (inferior-python-mode) | 1772 | (inferior-python-mode)) |
| 1723 | (python-util-clone-local-variables current-buffer)) | ||
| 1724 | (accept-process-output process) | 1773 | (accept-process-output process) |
| 1725 | (and pop (pop-to-buffer buffer t)) | 1774 | (and pop (pop-to-buffer buffer t)) |
| 1726 | (and internal (set-process-query-on-exit-flag process nil)))) | 1775 | (and internal (set-process-query-on-exit-flag process nil)))) |
| @@ -1861,26 +1910,41 @@ When MSG is non-nil messages the first line of STRING." | |||
| 1861 | (string-match "\n[ \t].*\n?$" string)) | 1910 | (string-match "\n[ \t].*\n?$" string)) |
| 1862 | (comint-send-string process "\n"))))) | 1911 | (comint-send-string process "\n"))))) |
| 1863 | 1912 | ||
| 1864 | ;; Shell output catching stolen from gud-gdb | 1913 | (defvar python-shell-output-filter-in-progress nil) |
| 1865 | (defvar python-shell-fetch-lines-in-progress nil) | 1914 | (defvar python-shell-output-filter-buffer nil) |
| 1866 | (defvar python-shell-fetch-lines-string nil) | 1915 | |
| 1867 | (defvar python-shell-fetched-lines nil) | 1916 | (defun python-shell-output-filter (string) |
| 1868 | 1917 | "Filter used in `python-shell-send-string-no-output' to grab output. | |
| 1869 | (defun python-shell-fetch-lines-filter (string) | 1918 | STRING is the output received to this point from the process. |
| 1870 | "Filter used to read the list of lines output by a command. | 1919 | This filter saves received output from the process in |
| 1871 | STRING is the output to filter." | 1920 | `python-shell-output-filter-buffer' and stops receiving it after |
| 1872 | (setq string (concat python-shell-fetch-lines-string string)) | 1921 | detecting a prompt at the end of the buffer." |
| 1873 | (while (string-match "\n" string) | 1922 | (setq |
| 1874 | (push (substring string 0 (match-beginning 0)) | 1923 | string (ansi-color-filter-apply string) |
| 1875 | python-shell-fetched-lines) | 1924 | python-shell-output-filter-buffer |
| 1876 | (setq string (substring string (match-end 0)))) | 1925 | (concat python-shell-output-filter-buffer string)) |
| 1877 | (if (equal (string-match comint-prompt-regexp string) 0) | 1926 | (when (string-match |
| 1878 | (progn | 1927 | ;; XXX: It seems on OSX an extra carriage return is attached |
| 1879 | (setq python-shell-fetch-lines-in-progress nil) | 1928 | ;; at the end of output, this handles that too. |
| 1880 | string) | 1929 | (format "\r?\n\\(?:%s\\|%s\\|%s\\)$" |
| 1881 | (progn | 1930 | python-shell-prompt-regexp |
| 1882 | (setq python-shell-fetch-lines-string string) | 1931 | python-shell-prompt-block-regexp |
| 1883 | ""))) | 1932 | python-shell-prompt-pdb-regexp) |
| 1933 | python-shell-output-filter-buffer) | ||
| 1934 | ;; Output ends when `python-shell-output-filter-buffer' contains | ||
| 1935 | ;; the prompt attached at the end of it. | ||
| 1936 | (setq python-shell-output-filter-in-progress nil | ||
| 1937 | python-shell-output-filter-buffer | ||
| 1938 | (substring python-shell-output-filter-buffer | ||
| 1939 | 0 (match-beginning 0))) | ||
| 1940 | (when (and (> (length python-shell-prompt-output-regexp) 0) | ||
| 1941 | (string-match (concat "^" python-shell-prompt-output-regexp) | ||
| 1942 | python-shell-output-filter-buffer)) | ||
| 1943 | ;; Some shells, like iPython might append a prompt before the | ||
| 1944 | ;; output, clean that. | ||
| 1945 | (setq python-shell-output-filter-buffer | ||
| 1946 | (substring python-shell-output-filter-buffer (match-end 0))))) | ||
| 1947 | "") | ||
| 1884 | 1948 | ||
| 1885 | (defun python-shell-send-string-no-output (string &optional process msg) | 1949 | (defun python-shell-send-string-no-output (string &optional process msg) |
| 1886 | "Send STRING to PROCESS and inhibit output. | 1950 | "Send STRING to PROCESS and inhibit output. |
| @@ -1888,18 +1952,20 @@ When MSG is non-nil messages the first line of STRING. Return | |||
| 1888 | the output." | 1952 | the output." |
| 1889 | (let ((process (or process (python-shell-get-or-create-process))) | 1953 | (let ((process (or process (python-shell-get-or-create-process))) |
| 1890 | (comint-preoutput-filter-functions | 1954 | (comint-preoutput-filter-functions |
| 1891 | '(python-shell-fetch-lines-filter)) | 1955 | '(python-shell-output-filter)) |
| 1892 | (python-shell-fetch-lines-in-progress t) | 1956 | (python-shell-output-filter-in-progress t) |
| 1893 | (inhibit-quit t)) | 1957 | (inhibit-quit t)) |
| 1894 | (or | 1958 | (or |
| 1895 | (with-local-quit | 1959 | (with-local-quit |
| 1896 | (python-shell-send-string string process msg) | 1960 | (python-shell-send-string string process msg) |
| 1897 | (while python-shell-fetch-lines-in-progress | 1961 | (while python-shell-output-filter-in-progress |
| 1962 | ;; `python-shell-output-filter' takes care of setting | ||
| 1963 | ;; `python-shell-output-filter-in-progress' to NIL after it | ||
| 1964 | ;; detects end of output. | ||
| 1898 | (accept-process-output process)) | 1965 | (accept-process-output process)) |
| 1899 | (prog1 | 1966 | (prog1 |
| 1900 | (mapconcat #'identity | 1967 | python-shell-output-filter-buffer |
| 1901 | (reverse python-shell-fetched-lines) "\n") | 1968 | (setq python-shell-output-filter-buffer nil))) |
| 1902 | (setq python-shell-fetched-lines nil))) | ||
| 1903 | (with-current-buffer (process-buffer process) | 1969 | (with-current-buffer (process-buffer process) |
| 1904 | (comint-interrupt-subjob))))) | 1970 | (comint-interrupt-subjob))))) |
| 1905 | 1971 | ||
| @@ -2264,37 +2330,105 @@ inferior python process is updated properly." | |||
| 2264 | 2330 | ||
| 2265 | (defcustom python-fill-comment-function 'python-fill-comment | 2331 | (defcustom python-fill-comment-function 'python-fill-comment |
| 2266 | "Function to fill comments. | 2332 | "Function to fill comments. |
| 2267 | This is the function used by `python-fill-paragraph-function' to | 2333 | This is the function used by `python-fill-paragraph' to |
| 2268 | fill comments." | 2334 | fill comments." |
| 2269 | :type 'symbol | 2335 | :type 'symbol |
| 2270 | :group 'python | 2336 | :group 'python) |
| 2271 | :safe 'symbolp) | ||
| 2272 | 2337 | ||
| 2273 | (defcustom python-fill-string-function 'python-fill-string | 2338 | (defcustom python-fill-string-function 'python-fill-string |
| 2274 | "Function to fill strings. | 2339 | "Function to fill strings. |
| 2275 | This is the function used by `python-fill-paragraph-function' to | 2340 | This is the function used by `python-fill-paragraph' to |
| 2276 | fill strings." | 2341 | fill strings." |
| 2277 | :type 'symbol | 2342 | :type 'symbol |
| 2278 | :group 'python | 2343 | :group 'python) |
| 2279 | :safe 'symbolp) | ||
| 2280 | 2344 | ||
| 2281 | (defcustom python-fill-decorator-function 'python-fill-decorator | 2345 | (defcustom python-fill-decorator-function 'python-fill-decorator |
| 2282 | "Function to fill decorators. | 2346 | "Function to fill decorators. |
| 2283 | This is the function used by `python-fill-paragraph-function' to | 2347 | This is the function used by `python-fill-paragraph' to |
| 2284 | fill decorators." | 2348 | fill decorators." |
| 2285 | :type 'symbol | 2349 | :type 'symbol |
| 2286 | :group 'python | 2350 | :group 'python) |
| 2287 | :safe 'symbolp) | ||
| 2288 | 2351 | ||
| 2289 | (defcustom python-fill-paren-function 'python-fill-paren | 2352 | (defcustom python-fill-paren-function 'python-fill-paren |
| 2290 | "Function to fill parens. | 2353 | "Function to fill parens. |
| 2291 | This is the function used by `python-fill-paragraph-function' to | 2354 | This is the function used by `python-fill-paragraph' to |
| 2292 | fill parens." | 2355 | fill parens." |
| 2293 | :type 'symbol | 2356 | :type 'symbol |
| 2357 | :group 'python) | ||
| 2358 | |||
| 2359 | (defcustom python-fill-docstring-style 'pep-257 | ||
| 2360 | "Style used to fill docstrings. | ||
| 2361 | This affects `python-fill-string' behavior with regards to | ||
| 2362 | triple quotes positioning. | ||
| 2363 | |||
| 2364 | Possible values are DJANGO, ONETWO, PEP-257, PEP-257-NN, | ||
| 2365 | SYMMETRIC, and NIL. A value of NIL won't care about quotes | ||
| 2366 | position and will treat docstrings a normal string, any other | ||
| 2367 | value may result in one of the following docstring styles: | ||
| 2368 | |||
| 2369 | DJANGO: | ||
| 2370 | |||
| 2371 | \"\"\" | ||
| 2372 | Process foo, return bar. | ||
| 2373 | \"\"\" | ||
| 2374 | |||
| 2375 | \"\"\" | ||
| 2376 | Process foo, return bar. | ||
| 2377 | |||
| 2378 | If processing fails throw ProcessingError. | ||
| 2379 | \"\"\" | ||
| 2380 | |||
| 2381 | ONETWO: | ||
| 2382 | |||
| 2383 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2384 | |||
| 2385 | \"\"\" | ||
| 2386 | Process foo, return bar. | ||
| 2387 | |||
| 2388 | If processing fails throw ProcessingError. | ||
| 2389 | |||
| 2390 | \"\"\" | ||
| 2391 | |||
| 2392 | PEP-257: | ||
| 2393 | |||
| 2394 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2395 | |||
| 2396 | \"\"\"Process foo, return bar. | ||
| 2397 | |||
| 2398 | If processing fails throw ProcessingError. | ||
| 2399 | |||
| 2400 | \"\"\" | ||
| 2401 | |||
| 2402 | PEP-257-NN: | ||
| 2403 | |||
| 2404 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2405 | |||
| 2406 | \"\"\"Process foo, return bar. | ||
| 2407 | |||
| 2408 | If processing fails throw ProcessingError. | ||
| 2409 | \"\"\" | ||
| 2410 | |||
| 2411 | SYMMETRIC: | ||
| 2412 | |||
| 2413 | \"\"\"Process foo, return bar.\"\"\" | ||
| 2414 | |||
| 2415 | \"\"\" | ||
| 2416 | Process foo, return bar. | ||
| 2417 | |||
| 2418 | If processing fails throw ProcessingError. | ||
| 2419 | \"\"\"" | ||
| 2420 | :type '(choice | ||
| 2421 | (const :tag "Don't format docstrings" nil) | ||
| 2422 | (const :tag "Django's coding standards style." django) | ||
| 2423 | (const :tag "One newline and start and Two at end style." onetwo) | ||
| 2424 | (const :tag "PEP-257 with 2 newlines at end of string." pep-257) | ||
| 2425 | (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn) | ||
| 2426 | (const :tag "Symmetric style." symmetric)) | ||
| 2294 | :group 'python | 2427 | :group 'python |
| 2295 | :safe 'symbolp) | 2428 | :safe (lambda (val) |
| 2429 | (memq val '(django onetwo pep-257 pep-257-nn symmetric nil)))) | ||
| 2296 | 2430 | ||
| 2297 | (defun python-fill-paragraph-function (&optional justify) | 2431 | (defun python-fill-paragraph (&optional justify) |
| 2298 | "`fill-paragraph-function' handling multi-line strings and possibly comments. | 2432 | "`fill-paragraph-function' handling multi-line strings and possibly comments. |
| 2299 | If any of the current line is in or at the end of a multi-line string, | 2433 | If any of the current line is in or at the end of a multi-line string, |
| 2300 | fill the string or the paragraph of it that point is in, preserving | 2434 | fill the string or the paragraph of it that point is in, preserving |
| @@ -2302,18 +2436,18 @@ the string's indentation. | |||
| 2302 | Optional argument JUSTIFY defines if the paragraph should be justified." | 2436 | Optional argument JUSTIFY defines if the paragraph should be justified." |
| 2303 | (interactive "P") | 2437 | (interactive "P") |
| 2304 | (save-excursion | 2438 | (save-excursion |
| 2305 | (back-to-indentation) | ||
| 2306 | (cond | 2439 | (cond |
| 2307 | ;; Comments | 2440 | ;; Comments |
| 2308 | ((funcall python-fill-comment-function justify)) | 2441 | ((python-syntax-context 'comment) |
| 2442 | (funcall python-fill-comment-function justify)) | ||
| 2309 | ;; Strings/Docstrings | 2443 | ;; Strings/Docstrings |
| 2310 | ((save-excursion (skip-chars-forward "\"'uUrR") | 2444 | ((save-excursion (or (python-syntax-context 'string) |
| 2311 | (python-syntax-context 'string)) | 2445 | (equal (string-to-syntax "|") |
| 2446 | (syntax-after (point))))) | ||
| 2312 | (funcall python-fill-string-function justify)) | 2447 | (funcall python-fill-string-function justify)) |
| 2313 | ;; Decorators | 2448 | ;; Decorators |
| 2314 | ((equal (char-after (save-excursion | 2449 | ((equal (char-after (save-excursion |
| 2315 | (back-to-indentation) | 2450 | (python-nav-beginning-of-statement))) ?@) |
| 2316 | (point-marker))) ?@) | ||
| 2317 | (funcall python-fill-decorator-function justify)) | 2451 | (funcall python-fill-decorator-function justify)) |
| 2318 | ;; Parens | 2452 | ;; Parens |
| 2319 | ((or (python-syntax-context 'paren) | 2453 | ((or (python-syntax-context 'paren) |
| @@ -2325,58 +2459,87 @@ Optional argument JUSTIFY defines if the paragraph should be justified." | |||
| 2325 | (t t)))) | 2459 | (t t)))) |
| 2326 | 2460 | ||
| 2327 | (defun python-fill-comment (&optional justify) | 2461 | (defun python-fill-comment (&optional justify) |
| 2328 | "Comment fill function for `python-fill-paragraph-function'. | 2462 | "Comment fill function for `python-fill-paragraph'. |
| 2329 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2463 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2330 | (fill-comment-paragraph justify)) | 2464 | (fill-comment-paragraph justify)) |
| 2331 | 2465 | ||
| 2332 | (defun python-fill-string (&optional justify) | 2466 | (defun python-fill-string (&optional justify) |
| 2333 | "String fill function for `python-fill-paragraph-function'. | 2467 | "String fill function for `python-fill-paragraph'. |
| 2334 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2468 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2335 | (let ((marker (point-marker)) | 2469 | (let* ((marker (point-marker)) |
| 2336 | (string-start-marker | 2470 | (str-start-pos |
| 2337 | (progn | 2471 | (let ((m (make-marker))) |
| 2338 | (skip-chars-forward "\"'uUrR") | 2472 | (setf (marker-position m) |
| 2339 | (goto-char (python-syntax-context 'string)) | 2473 | (or (python-syntax-context 'string) |
| 2340 | (skip-chars-forward "\"'uUrR") | 2474 | (and (equal (string-to-syntax "|") |
| 2341 | (point-marker))) | 2475 | (syntax-after (point))) |
| 2342 | (reg-start (line-beginning-position)) | 2476 | (point)))) m)) |
| 2343 | (string-end-marker | 2477 | (num-quotes (python-syntax-count-quotes |
| 2344 | (progn | 2478 | (char-after str-start-pos) str-start-pos)) |
| 2345 | (while (python-syntax-context 'string) | 2479 | (str-end-pos |
| 2346 | (goto-char (1+ (point-marker)))) | 2480 | (save-excursion |
| 2347 | (skip-chars-backward "\"'") | 2481 | (goto-char (+ str-start-pos num-quotes)) |
| 2348 | (point-marker))) | 2482 | (or (re-search-forward (rx (syntax string-delimiter)) nil t) |
| 2349 | (reg-end (line-end-position)) | 2483 | (goto-char (point-max))) |
| 2350 | (fill-paragraph-function)) | 2484 | (point-marker))) |
| 2485 | (multi-line-p | ||
| 2486 | ;; Docstring styles may vary for oneliners and multi-liners. | ||
| 2487 | (> (count-matches "\n" str-start-pos str-end-pos) 0)) | ||
| 2488 | (delimiters-style | ||
| 2489 | (case python-fill-docstring-style | ||
| 2490 | ;; delimiters-style is a cons cell with the form | ||
| 2491 | ;; (START-NEWLINES . END-NEWLINES). When any of the sexps | ||
| 2492 | ;; is NIL means to not add any newlines for start or end | ||
| 2493 | ;; of docstring. See `python-fill-docstring-style' for a | ||
| 2494 | ;; graphic idea of each style. | ||
| 2495 | (django (cons 1 1)) | ||
| 2496 | (onetwo (and multi-line-p (cons 1 2))) | ||
| 2497 | (pep-257 (and multi-line-p (cons nil 2))) | ||
| 2498 | (pep-257-nn (and multi-line-p (cons nil 1))) | ||
| 2499 | (symmetric (and multi-line-p (cons 1 1))))) | ||
| 2500 | (docstring-p (save-excursion | ||
| 2501 | ;; Consider docstrings those strings which | ||
| 2502 | ;; start on a line by themselves. | ||
| 2503 | (python-nav-beginning-of-statement) | ||
| 2504 | (and (= (point) str-start-pos)))) | ||
| 2505 | (fill-paragraph-function)) | ||
| 2351 | (save-restriction | 2506 | (save-restriction |
| 2352 | (narrow-to-region reg-start reg-end) | 2507 | (narrow-to-region str-start-pos str-end-pos) |
| 2353 | (save-excursion | 2508 | (fill-paragraph justify)) |
| 2354 | (goto-char string-start-marker) | 2509 | (save-excursion |
| 2355 | (delete-region (point-marker) (progn | 2510 | (when (and docstring-p python-fill-docstring-style) |
| 2356 | (skip-syntax-forward "> ") | 2511 | ;; Add the number of newlines indicated by the selected style |
| 2357 | (point-marker))) | 2512 | ;; at the start of the docstring. |
| 2358 | (goto-char string-end-marker) | 2513 | (goto-char (+ str-start-pos num-quotes)) |
| 2359 | (delete-region (point-marker) (progn | 2514 | (delete-region (point) (progn |
| 2360 | (skip-syntax-backward "> ") | 2515 | (skip-syntax-forward "> ") |
| 2361 | (point-marker))) | 2516 | (point))) |
| 2362 | (save-excursion | 2517 | (and (car delimiters-style) |
| 2363 | (goto-char marker) | 2518 | (or (newline (car delimiters-style)) t) |
| 2364 | (fill-paragraph justify)) | 2519 | ;; Indent only if a newline is added. |
| 2365 | ;; If there is a newline in the docstring lets put triple | 2520 | (indent-according-to-mode)) |
| 2366 | ;; quote in it's own line to follow pep 8 | 2521 | ;; Add the number of newlines indicated by the selected style |
| 2367 | (when (save-excursion | 2522 | ;; at the end of the docstring. |
| 2368 | (re-search-backward "\n" string-start-marker t)) | 2523 | (goto-char (if (not (= str-end-pos (point-max))) |
| 2369 | (newline) | 2524 | (- str-end-pos num-quotes) |
| 2370 | (newline-and-indent)) | 2525 | str-end-pos)) |
| 2371 | (fill-paragraph justify)))) t) | 2526 | (delete-region (point) (progn |
| 2527 | (skip-syntax-backward "> ") | ||
| 2528 | (point))) | ||
| 2529 | (and (cdr delimiters-style) | ||
| 2530 | ;; Add newlines only if string ends. | ||
| 2531 | (not (= str-end-pos (point-max))) | ||
| 2532 | (or (newline (cdr delimiters-style)) t) | ||
| 2533 | ;; Again indent only if a newline is added. | ||
| 2534 | (indent-according-to-mode))))) t) | ||
| 2372 | 2535 | ||
| 2373 | (defun python-fill-decorator (&optional justify) | 2536 | (defun python-fill-decorator (&optional justify) |
| 2374 | "Decorator fill function for `python-fill-paragraph-function'. | 2537 | "Decorator fill function for `python-fill-paragraph'. |
| 2375 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2538 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2376 | t) | 2539 | t) |
| 2377 | 2540 | ||
| 2378 | (defun python-fill-paren (&optional justify) | 2541 | (defun python-fill-paren (&optional justify) |
| 2379 | "Paren fill function for `python-fill-paragraph-function'. | 2542 | "Paren fill function for `python-fill-paragraph'. |
| 2380 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." | 2543 | JUSTIFY should be used (if applicable) as in `fill-paragraph'." |
| 2381 | (save-restriction | 2544 | (save-restriction |
| 2382 | (narrow-to-region (progn | 2545 | (narrow-to-region (progn |
| @@ -2766,12 +2929,43 @@ parent defun name." | |||
| 2766 | ".") ".") | 2929 | ".") ".") |
| 2767 | name))))))) | 2930 | name))))))) |
| 2768 | 2931 | ||
| 2769 | (defsubst python-info-beginning-of-block-statement-p () | 2932 | (defun python-info-statement-starts-block-p () |
| 2770 | "Return non-nil if current statement opens a block." | 2933 | "Return non-nil if current statement opens a block." |
| 2771 | (save-excursion | 2934 | (save-excursion |
| 2772 | (python-nav-beginning-of-statement) | 2935 | (python-nav-beginning-of-statement) |
| 2773 | (looking-at (python-rx block-start)))) | 2936 | (looking-at (python-rx block-start)))) |
| 2774 | 2937 | ||
| 2938 | (defun python-info-statement-ends-block-p () | ||
| 2939 | "Return non-nil if point is at end of block." | ||
| 2940 | (let ((end-of-block-pos (save-excursion | ||
| 2941 | (python-nav-end-of-block))) | ||
| 2942 | (end-of-statement-pos (save-excursion | ||
| 2943 | (python-nav-end-of-statement)))) | ||
| 2944 | (and end-of-block-pos end-of-statement-pos | ||
| 2945 | (= end-of-block-pos end-of-statement-pos)))) | ||
| 2946 | |||
| 2947 | (defun python-info-beginning-of-statement-p () | ||
| 2948 | "Return non-nil if point is at beginning of statement." | ||
| 2949 | (= (point) (save-excursion | ||
| 2950 | (python-nav-beginning-of-statement) | ||
| 2951 | (point)))) | ||
| 2952 | |||
| 2953 | (defun python-info-end-of-statement-p () | ||
| 2954 | "Return non-nil if point is at end of statement." | ||
| 2955 | (= (point) (save-excursion | ||
| 2956 | (python-nav-end-of-statement) | ||
| 2957 | (point)))) | ||
| 2958 | |||
| 2959 | (defun python-info-beginning-of-block-p () | ||
| 2960 | "Return non-nil if point is at beginning of block." | ||
| 2961 | (and (python-info-beginning-of-statement-p) | ||
| 2962 | (python-info-statement-starts-block-p))) | ||
| 2963 | |||
| 2964 | (defun python-info-end-of-block-p () | ||
| 2965 | "Return non-nil if point is at end of block." | ||
| 2966 | (and (python-info-end-of-statement-p) | ||
| 2967 | (python-info-statement-ends-block-p))) | ||
| 2968 | |||
| 2775 | (defun python-info-closing-block () | 2969 | (defun python-info-closing-block () |
| 2776 | "Return the point of the block the current line closes." | 2970 | "Return the point of the block the current line closes." |
| 2777 | (let ((closing-word (save-excursion | 2971 | (let ((closing-word (save-excursion |
| @@ -2996,7 +3190,7 @@ if that value is non-nil." | |||
| 2996 | 3190 | ||
| 2997 | (set (make-local-variable 'paragraph-start) "\\s-*$") | 3191 | (set (make-local-variable 'paragraph-start) "\\s-*$") |
| 2998 | (set (make-local-variable 'fill-paragraph-function) | 3192 | (set (make-local-variable 'fill-paragraph-function) |
| 2999 | 'python-fill-paragraph-function) | 3193 | 'python-fill-paragraph) |
| 3000 | 3194 | ||
| 3001 | (set (make-local-variable 'beginning-of-defun-function) | 3195 | (set (make-local-variable 'beginning-of-defun-function) |
| 3002 | #'python-beginning-of-defun-function) | 3196 | #'python-beginning-of-defun-function) |