diff options
| author | Fabián Ezequiel Gallina | 2012-09-24 14:54:46 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2012-09-24 14:54:46 -0300 |
| commit | 8fb8b88f2d1ac6dd0feb3c590614257f8fad0fee (patch) | |
| tree | 90e49390c13f521e6f9c802e9b33ff2b1a46db8c /lisp/progmodes/python.el | |
| parent | 267b82ff2374a43cb38617a648c5bfa58ef2b039 (diff) | |
| download | emacs-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.el | 106 |
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 |
| 511 | Used 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 | 516 | QUOTE-CHAR is the quote char to count. Optional argument POINT is | |
| 520 | ;; Test cases: | 517 | the point where scan starts (defaults to current point) and LIMIT |
| 521 | ;; ur"""ar""" x='"' # """ | 518 | is 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))) |