aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2012-09-24 14:54:46 -0300
committerFabián Ezequiel Gallina2012-09-24 14:54:46 -0300
commit8fb8b88f2d1ac6dd0feb3c590614257f8fad0fee (patch)
tree90e49390c13f521e6f9c802e9b33ff2b1a46db8c /lisp/progmodes/python.el
parent267b82ff2374a43cb38617a648c5bfa58ef2b039 (diff)
downloademacs-8fb8b88f2d1ac6dd0feb3c590614257f8fad0fee.tar.gz
emacs-8fb8b88f2d1ac6dd0feb3c590614257f8fad0fee.zip
Enhancements for triple-quote string syntax.
* progmodes/python.el (python-quote-syntax): Remove. (python-syntax-propertize-function): New value. (python-syntax-count-quotes, python-syntax-stringify): New functions.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el106
1 files changed, 61 insertions, 45 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 8b8002b84b7..cc835ca79ac 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -497,52 +497,68 @@ The type returned can be `comment', `string' or `paren'."
497 (1 font-lock-variable-name-face nil nil)))) 497 (1 font-lock-variable-name-face nil nil))))
498 498
499(defconst python-syntax-propertize-function 499(defconst python-syntax-propertize-function
500 ;; Make outer chars of matching triple-quote sequences into generic
501 ;; string delimiters. Fixme: Is there a better way?
502 ;; First avoid a sequence preceded by an odd number of backslashes.
503 (syntax-propertize-rules 500 (syntax-propertize-rules
504 (;; ¡Backrefs don't work in syntax-propertize-rules! 501 ((rx
505 (concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix. 502 ;; Match even number of backslashes.
506 "\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)") 503 (or (not (any ?\\ ?\' ?\")) point) (* ?\\ ?\\)
507 (3 (ignore (python-quote-syntax)))))) 504 ;; Match single or triple quotes of any kind.
508 505 (group (or "\"" "\"\"\"" "'" "'''")))
509(defun python-quote-syntax () 506 (1 (ignore (python-syntax-stringify))))
510 "Put `syntax-table' property correctly on triple quote. 507 ((rx
511Used for syntactic keywords. N is the match number (1, 2 or 3)." 508 ;; Match odd number of backslashes.
512 ;; Given a triple quote, we have to check the context to know 509 (or (not (any ?\\)) point) ?\\ (* ?\\ ?\\)
513 ;; whether this is an opening or closing triple or whether it's 510 ;; Followed by even number of equal quotes.
514 ;; quoted anyhow, and should be ignored. (For that we need to do 511 (group (or "\"\"" "\"\"\"\"" "''" "''''")))
515 ;; the same job as `syntax-ppss' to be correct and it seems to be OK 512 (1 (ignore (python-syntax-stringify))))))
516 ;; to use it here despite initial worries.) We also have to sort 513
517 ;; out a possible prefix -- well, we don't _have_ to, but I think it 514(defsubst python-syntax-count-quotes (quote-char &optional point limit)
518 ;; should be treated as part of the string. 515 "Count number of quotes around point (max is 3).
519 516QUOTE-CHAR is the quote char to count. Optional argument POINT is
520 ;; Test cases: 517the point where scan starts (defaults to current point) and LIMIT
521 ;; ur"""ar""" x='"' # """ 518is used to limit the scan."
522 ;; x = ''' """ ' a 519 (let ((i 0))
523 ;; ''' 520 (while (and (< i 3)
524 ;; x '"""' x """ \"""" x 521 (or (not limit) (< (+ point i) limit))
525 (save-excursion 522 (eq (char-after (+ point i)) quote-char))
526 (goto-char (match-beginning 0)) 523 (incf i))
527 (let ((syntax (save-match-data (syntax-ppss)))) 524 i))
528 (cond 525
529 ((eq t (nth 3 syntax)) ; after unclosed fence 526(defun python-syntax-stringify ()
530 ;; Consider property for the last char if in a fenced string. 527 "Put `syntax-table' property correctly on single/triple quotes."
531 (goto-char (nth 8 syntax)) ; fence position 528 (let* ((num-quotes
532 (skip-chars-forward "uUrR") ; skip any prefix 529 (let ((n (length (match-string-no-properties 1))))
533 ;; Is it a matching sequence? 530 ;; This corrects the quote count when matching odd number
534 (if (eq (char-after) (char-after (match-beginning 2))) 531 ;; of backslashes followed by even number of quotes.
535 (put-text-property (match-beginning 3) (match-end 3) 532 (or (and (= 1 (logand n 1)) n) (1- n))))
536 'syntax-table (string-to-syntax "|")))) 533 (ppss (prog2
537 ((match-end 1) 534 (backward-char num-quotes)
538 ;; Consider property for initial char, accounting for prefixes. 535 (syntax-ppss)
539 (put-text-property (match-beginning 1) (match-end 1) 536 (forward-char num-quotes)))
540 'syntax-table (string-to-syntax "|"))) 537 (string-start (and (not (nth 4 ppss)) (nth 8 ppss)))
541 (t 538 (quote-starting-pos (- (point) num-quotes))
542 ;; Consider property for initial char, accounting for prefixes. 539 (quote-ending-pos (point))
543 (put-text-property (match-beginning 2) (match-end 2) 540 (num-closing-quotes
544 'syntax-table (string-to-syntax "|")))) 541 (and string-start
545 ))) 542 (python-syntax-count-quotes
543 (char-before) string-start quote-starting-pos))))
544 (cond ((and string-start (= num-closing-quotes 0))
545 ;; This set of quotes doesn't match the string starting
546 ;; kind. Do nothing.
547 nil)
548 ((not string-start)
549 ;; This set of quotes delimit the start of a string.
550 (put-text-property quote-starting-pos (1+ quote-starting-pos)
551 'syntax-table (string-to-syntax "|")))
552 ((= num-quotes num-closing-quotes)
553 ;; This set of quotes delimit the end of a string.
554 (put-text-property (1- quote-ending-pos) quote-ending-pos
555 'syntax-table (string-to-syntax "|")))
556 ((> num-quotes num-closing-quotes)
557 ;; This may only happen whenever a triple quote is closing
558 ;; a single quoted string. Add string delimiter syntax to
559 ;; all three quotes.
560 (put-text-property quote-starting-pos quote-ending-pos
561 'syntax-table (string-to-syntax "|"))))))
546 562
547(defvar python-mode-syntax-table 563(defvar python-mode-syntax-table
548 (let ((table (make-syntax-table))) 564 (let ((table (make-syntax-table)))