aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2015-04-05 23:58:13 -0300
committerFabián Ezequiel Gallina2015-04-05 23:58:13 -0300
commitdeea36f0ece7b1b14afe2a833b6a0f66d59f4459 (patch)
treee3e41e0a5a03b0ea83b293c0c65835be038d56d4 /lisp/progmodes/python.el
parent7514b24b6a512d85b762c603e9e0107d2c8a52f1 (diff)
downloademacs-deea36f0ece7b1b14afe2a833b6a0f66d59f4459.tar.gz
emacs-deea36f0ece7b1b14afe2a833b6a0f66d59f4459.zip
python.el: Enhance docstring detection following PEP-257.
* lisp/progmodes/python.el (python-docstring-at-p): Remove function. (python-info-assignment-statement-p): New function. (python-info-assignment-continuation-line-p): Use it. (python-info-docstring-p): New function. (python-font-lock-syntactic-face-function) (python-fill-string): Use it. * test/automated/python-tests.el (python-info-assignment-statement-p-1) (python-info-assignment-statement-p-2) (python-info-assignment-statement-p-3, python-info-docstring-p-1) (python-info-docstring-p-2, python-info-docstring-p-3) (python-info-docstring-p-4, python-info-docstring-p-5) (python-info-docstring-p-6): New tests.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el96
1 files changed, 69 insertions, 27 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 67b44aa1bbe..f402ad83cca 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -482,19 +482,10 @@ The type returned can be `comment', `string' or `paren'."
482 'python-info-ppss-comment-or-string-p 482 'python-info-ppss-comment-or-string-p
483 #'python-syntax-comment-or-string-p "24.3") 483 #'python-syntax-comment-or-string-p "24.3")
484 484
485(defun python-docstring-at-p (pos)
486 "Check to see if there is a docstring at POS."
487 (save-excursion
488 (goto-char pos)
489 (if (looking-at-p "'''\\|\"\"\"")
490 (progn
491 (python-nav-backward-statement)
492 (looking-at "\\`\\|class \\|def "))
493 nil)))
494
495(defun python-font-lock-syntactic-face-function (state) 485(defun python-font-lock-syntactic-face-function (state)
486 "Return syntactic face given STATE."
496 (if (nth 3 state) 487 (if (nth 3 state)
497 (if (python-docstring-at-p (nth 8 state)) 488 (if (python-info-docstring-p state)
498 font-lock-doc-face 489 font-lock-doc-face
499 font-lock-string-face) 490 font-lock-string-face)
500 font-lock-comment-face)) 491 font-lock-comment-face))
@@ -3587,17 +3578,12 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
3587 (`pep-257 (and multi-line-p (cons nil 2))) 3578 (`pep-257 (and multi-line-p (cons nil 2)))
3588 (`pep-257-nn (and multi-line-p (cons nil 1))) 3579 (`pep-257-nn (and multi-line-p (cons nil 1)))
3589 (`symmetric (and multi-line-p (cons 1 1))))) 3580 (`symmetric (and multi-line-p (cons 1 1)))))
3590 (docstring-p (save-excursion
3591 ;; Consider docstrings those strings which
3592 ;; start on a line by themselves.
3593 (python-nav-beginning-of-statement)
3594 (and (= (point) str-start-pos))))
3595 (fill-paragraph-function)) 3581 (fill-paragraph-function))
3596 (save-restriction 3582 (save-restriction
3597 (narrow-to-region str-start-pos str-end-pos) 3583 (narrow-to-region str-start-pos str-end-pos)
3598 (fill-paragraph justify)) 3584 (fill-paragraph justify))
3599 (save-excursion 3585 (save-excursion
3600 (when (and docstring-p python-fill-docstring-style) 3586 (when (and (python-info-docstring-p) python-fill-docstring-style)
3601 ;; Add the number of newlines indicated by the selected style 3587 ;; Add the number of newlines indicated by the selected style
3602 ;; at the start of the docstring. 3588 ;; at the start of the docstring.
3603 (goto-char (+ str-start-pos num-quotes)) 3589 (goto-char (+ str-start-pos num-quotes))
@@ -4423,23 +4409,40 @@ where the continued line ends."
4423 (when (looking-at (python-rx block-start)) 4409 (when (looking-at (python-rx block-start))
4424 (point-marker))))) 4410 (point-marker)))))
4425 4411
4412(defun python-info-assignment-statement-p (&optional current-line-only)
4413 "Check if current line is an assignment.
4414With argument CURRENT-LINE-ONLY is non-nil, don't follow any
4415continuations, just check the if current line is an assignment."
4416 (save-excursion
4417 (let ((found nil))
4418 (if current-line-only
4419 (back-to-indentation)
4420 (python-nav-beginning-of-statement))
4421 (while (and
4422 (re-search-forward (python-rx not-simple-operator
4423 assignment-operator
4424 (group not-simple-operator))
4425 (line-end-position) t)
4426 (not found))
4427 (save-excursion
4428 ;; The assignment operator should not be inside a string.
4429 (backward-char (length (match-string-no-properties 1)))
4430 (setq found (not (python-syntax-context-type)))))
4431 (when found
4432 (skip-syntax-forward " ")
4433 (point-marker)))))
4434
4435;; TODO: rename to clarify this is only for the first continuation
4436;; line or remove it and move its body to `python-indent-context'.
4426(defun python-info-assignment-continuation-line-p () 4437(defun python-info-assignment-continuation-line-p ()
4427 "Check if current line is a continuation of an assignment. 4438 "Check if current line is the first continuation of an assignment.
4428When current line is continuation of another with an assignment 4439When current line is continuation of another with an assignment
4429return the point of the first non-blank character after the 4440return the point of the first non-blank character after the
4430operator." 4441operator."
4431 (save-excursion 4442 (save-excursion
4432 (when (python-info-continuation-line-p) 4443 (when (python-info-continuation-line-p)
4433 (forward-line -1) 4444 (forward-line -1)
4434 (back-to-indentation) 4445 (python-info-assignment-statement-p t))))
4435 (when (and (not (looking-at (python-rx block-start)))
4436 (and (re-search-forward (python-rx not-simple-operator
4437 assignment-operator
4438 not-simple-operator)
4439 (line-end-position) t)
4440 (not (python-syntax-context-type))))
4441 (skip-syntax-forward "\s")
4442 (point-marker)))))
4443 4446
4444(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) 4447(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss)
4445 "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." 4448 "Check if point is at `beginning-of-defun' using SYNTAX-PPSS."
@@ -4464,6 +4467,45 @@ operator."
4464 (* whitespace) line-end)) 4467 (* whitespace) line-end))
4465 (string-equal "" (match-string-no-properties 1)))) 4468 (string-equal "" (match-string-no-properties 1))))
4466 4469
4470(defun python-info-docstring-p (&optional syntax-ppss)
4471 "Return non-nil if point is in a docstring.
4472When optional argument SYNTAX-PPSS is given, use that instead of
4473point's current `syntax-ppss'."
4474 ;;; https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring
4475 (save-excursion
4476 (when (and syntax-ppss (python-syntax-context 'string syntax-ppss))
4477 (goto-char (nth 8 syntax-ppss)))
4478 (python-nav-beginning-of-statement)
4479 (let ((counter 1)
4480 (indentation (current-indentation))
4481 (backward-sexp-point)
4482 (re (concat "[uU]?[rR]?"
4483 (python-rx string-delimiter))))
4484 (when (and
4485 (not (python-info-assignment-statement-p))
4486 (looking-at-p re)
4487 ;; Allow up to two consecutive docstrings only.
4488 (>=
4489 2
4490 (progn
4491 (while (save-excursion
4492 (python-nav-backward-sexp)
4493 (setq backward-sexp-point (point))
4494 (and (= indentation (current-indentation))
4495 (looking-at-p
4496 (concat "[uU]?[rR]?"
4497 (python-rx string-delimiter)))))
4498 ;; Previous sexp was a string, restore point.
4499 (goto-char backward-sexp-point)
4500 (cl-incf counter))
4501 counter)))
4502 (python-util-forward-comment -1)
4503 (python-nav-beginning-of-statement)
4504 (cond ((bobp))
4505 ((python-info-assignment-statement-p) t)
4506 ((python-info-looking-at-beginning-of-defun))
4507 (t nil))))))
4508
4467(defun python-info-encoding-from-cookie () 4509(defun python-info-encoding-from-cookie ()
4468 "Detect current buffer's encoding from its coding cookie. 4510 "Detect current buffer's encoding from its coding cookie.
4469Returns the encoding as a symbol." 4511Returns the encoding as a symbol."