Tại sao chèn một đánh dấu ngắt dòng mới với chức năng cú pháp phù hợp?


6

Tôi đang cố gắng viết một chế độ chính làm nổi bật các chuỗi ba trích dẫn. Đây là một ví dụ có thể tái tạo tối thiểu:

(defconst demo-triple-quoted-string-regex
  (rx "\"\"\""
      ;; After the delimiter, we're a sequence of
      ;; non-backslashes or blackslashes paired with something.
      (*? (or (not (any "\\"))
              (seq "\\" anything)))
      "\"\"\""))

(defun demo-stringify-triple-quote ()
  "Put `syntax-table' property on triple-quoted strings."
  (let* ((string-literal (match-string 0))
         (string-start-pos (- (point) (length string-literal)))
         (string-end-pos (point)))
    (unless (nth 4 (syntax-ppss)) ;; not inside comment
      (put-text-property string-start-pos string-end-pos
                         'syntax-table (string-to-syntax "|")))))

(defconst demo-syntax-propertize-function
  (syntax-propertize-rules
   (demo-triple-quoted-string-regex
    (0 (ignore (demo-stringify-triple-quote))))))

(define-derived-mode demo-mode prog-mode "Demo"
  "Major mode showing stack overflow question."
  (set (make-local-variable 'font-lock-defaults) '(()))
  (set (make-local-variable 'syntax-propertize-function)
       demo-syntax-propertize-function))

Tuy nhiên, điều này dẫn đến hành vi thực sự kỳ quái khi sửa đổi bộ đệm. Đây là nội dung bộ đệm của tôi:

dodgy when we put a newline after babel

"""
a
"
babel

"""

x = 1

M-x demo-mode làm nổi bật chính xác:

bản demo trước

nhưng nhấn enter đột nhiên cho ra điều này:

bản demo sau

Tôi đang làm gì sai?


Tôi không có giải pháp nhưng tôi nhận thấy vấn đề tương tự với việc tiếp tục in nghiêng và in đậm trên các dòng kết thúc ở chế độ org.
Người dùng Emacs

1
Vấn đề đầu tiên là bạn đặt cú pháp trên tất cả các ký tự của chuỗi, trong khi nó chỉ nên được thực hiện cho các ký tự hàng rào đầu tiên và cuối cùng. Bạn có thể xác minh rằng Emacs coi mọi cặp chuỗi được cho là của bạn là một chuỗi sex, tức là một chuỗi, thông qua forward-sexp.
trị

1
Vấn đề thứ hai là bạn không thể thực sự khớp chuỗi theo cách bạn tưởng tượng. Điều này sẽ chỉ hoạt động, nếu tìm kiếm được đảm bảo bắt đầu bên ngoài bất kỳ chuỗi nào đã có trong bộ đệm. Sau khi tất cả các cặp bạn khớp: Một bộ ba bắt đầu một chuỗi khi và chỉ khi nó đi trước một số chẵn ba lần khác. May mắn syntax-ppsstheo dõi điều này. Hãy xem làm thế nào nó được thực hiện trong python.el.
trị

@politza Tôi rất kinh ngạc về kỹ năng elisp của bạn! Cám ơn rất nhiều :). Sửa chữa của bạn là đủ để tôi làm cho mã của tôi hoạt động (xem câu trả lời bên dưới), vì vậy bây giờ tôi có thể sửa lỗi chế độ julia đưa tôi vào vấn đề này.
Wilfred Hughes

Câu trả lời:


3

Cảm ơn Politza và bước qua python-syntax-stringifyvới edebug, tôi đã làm việc này. Những thay đổi là:

  • | chỉ nên được áp dụng cho ký tự đầu tiên và cuối cùng trong chuỗi ba trích dẫn.
  • (Vì phân tích cú pháp là tăng dần?) Không thể tìm kiếm toàn bộ chuỗi. Thay vào đó, tìm kiếm một dấu phân cách và xem liệu bạn có trong chuỗi trích dẫn ba hay không.

Mã làm việc:

(defconst demo-triple-quoted-string-regex
  (rx "\"\"\""))

(defun demo-stringify-triple-quote ()
  "Put `syntax-table' property on triple-quoted strings."
  (let* ((string-end-pos (point))
         (string-start-pos (- string-end-pos 3))
         (ppss (prog2
                   (backward-char 3)
                   (syntax-ppss)
                 (forward-char 3))))
    (unless (nth 4 (syntax-ppss)) ;; not inside comment
      (if (nth 8 (syntax-ppss))
          ;; We're in a string, so this must be the closing triple-quote.
          ;; Put | on the last " character.
          (put-text-property (1- string-end-pos) string-end-pos
                             'syntax-table (string-to-syntax "|"))
        ;; We're not in a string, so this is the opening triple-quote.
        ;; Put | on the first " character.
        (put-text-property string-start-pos (1+ string-start-pos)
                           'syntax-table (string-to-syntax "|"))))))

(defconst demo-syntax-propertize-function
  (syntax-propertize-rules
   (demo-triple-quoted-string-regex
    (0 (ignore (demo-stringify-triple-quote))))))

(define-derived-mode demo-mode prog-mode "Demo"
  "Major mode showing stack overflow question."
  (set (make-local-variable 'font-lock-defaults) '(()))
  (set (make-local-variable 'syntax-propertize-function)
       demo-syntax-propertize-function))

Tại sao bạn tính toán ppsstrong let*và sau đó không bao giờ sử dụng giá trị đó?
Michael Norrish
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.