2012-02-26 59 views
12

Một số nền tảng, tôi cảm thấy thoải mái với Emacs Lisp, và đã viết rất nhiều dòng của nó. Tuy nhiên tôi chưa bao giờ viết một chế độ chính, vì vậy tôi khá mới với cách cơ chế khóa phông chữ hoạt động.emacs: là có một ví dụ rõ ràng về đa dòng chữ-khóa?

Đối với dự án hiện tại của tôi, tôi muốn thêm javascript nội tuyến và css làm nổi bật vào html-mode. Hiện tại, tôi làm điều này với chế độ MMM, nhưng nó cồng kềnh và tôi không sử dụng các tính năng khác của nó, vì vậy tôi chỉ muốn tạo một chế độ nhỏ hoặc thậm chí chỉ là một hack mà tôi có thể thêm vào sgml-mode-hook vào làm nổi bật.

Tôi đã tìm thấy trang này section của hướng dẫn sử dụng, điều này rất thiếu ví dụ và mã emacswiki page mã bị hỏng này.

Ai đó có thể cho tôi xem ví dụ rõ ràng về cách thực hiện điều này không?

EDIT: Tôi nên làm rõ rằng tôi không muốn xem khóa phông chữ cụ thể theo chế độ trong khối javascript/css. Yêu cầu duy nhất là tôi có thể thấy các khối bằng cách áp dụng một khuôn mặt khác cho họ.

Trả lời

6

Trong ví dụ bên dưới, tôi sử dụng hình thức "neo" của từ khóa khóa phông chữ, nó cho phép bạn tìm kiếm nhiều hơn dòng hiện tại. "Bí quyết" là móc "trước" thực hiện hai việc: 1) nó cho phép bạn định vị điểm để bắt đầu tìm kiếm và 2) nó cho phép bạn giới hạn tìm kiếm bằng cách trả về vị trí kết thúc. Trong ví dụ bên dưới, tôi đã sử dụng thuộc tính thứ hai.

Lưu ý rằng đây chỉ là bằng chứng khái niệm. Bạn sẽ cần phải đảm bảo rằng biến số font-lock-multiline và từ khóa phông chữ được áp dụng cho bộ đệm chính xác.

(defun my-end-of-paragraph-position (&rest foo) 
    "Return position of next empty line." 
    (save-excursion 
    (while (not (or (eobp)    ; Stop at end of buffer. 
        (and (bolp)  ; Or at an empty line. 
         (eolp)))) 
     (forward-line)) 
    (point))) 

(setq font-lock-multiline t) 

(font-lock-add-keywords nil 
         '(("^FOO" 
          (0 font-lock-keyword-face) ;; Face for FOO 
          ("BAR" 
          (my-end-of-paragraph-position) 
          nil 
          (0 font-lock-variable-name-face))))) 

Dưới đây, hai dòng đầu tiên của BAR sẽ được đánh dấu, nhưng không phải là lần cuối:

FOO BAR BAR BAR BAR 
BAR BAR BAR BAR 

BAR BAR BAR BAR 
+1

Trong [thread] này (http://lists.gnu.org/archive/html/help-gnu-emacs/2004-09/msg00534.html), Stefan Monnier nói rằng phông chữ-khóa-nhiều dòng là thích hợp cho những thứ thường là một dòng, nhưng đôi khi nhiều dòng. Bình luận? –

+0

Vâng, Stefan Monnier là tài liệu tham khảo dứt khoát khi nói đến bất cứ điều gì liên quan đến font-lock, do đó, bất kỳ lời khuyên nào từ anh ta cũng đáng được theo dõi. Sử dụng hệ thống cú pháp, như ông gợi ý, là một cách để làm điều đó. Cách khác là sử dụng "hàm so khớp" thay vì hàm regexp, có thể khớp với toàn bộ khối. Bạn sẽ thấy câu trả lời của tôi như là một câu trả lời trực tiếp cho câu hỏi (cung cấp một ví dụ về tính năng khóa nhiều dòng) và có thể không phải là câu trả lời về cách tốt nhất để hoàn thành bất kỳ poster ban đầu nào được hỏi. – Lindydancer

3

Đó là lẽ không phải là ví dụ tốt nhất có thể, nhưng bạn có thể nhìn vào cách haml-mode đã giải quyết vấn đề làm nổi bật cú pháp trong các vùng submode. Đây là số blog post với mô tả cấp cao.

Lưu ý rằng hiện tại haml-mode có một số vấn đề với tương thích với Emacs 24, nhưng một vài nhánh đã sửa lỗi cho điều này.

Về khóa phông chữ nhiều dòng, tôi nghĩ bạn có thể đang đặt câu hỏi sai. Nhưng về cơ bản, điều này giải quyết được vấn đề phải làm gì nếu người dùng đã thực hiện chỉnh sửa ở giữa hoặc phần cuối của cấu trúc cú pháp đa dòng. Ban đầu, font-lock bắt đầu refontifying bộ đệm từ vị trí của điểm. Hai mặc định font-lock-extend-region-functions, font-lock-extend-region-wholelinesfont-lock-extend-region-multiline, di chuyển phần bắt đầu của khu vực tái cấu trúc đến đầu dòng và sau đó có thể ở đâu đó xa hơn, tùy thuộc vào thuộc tính font-lock-multiline. Nếu bạn cần nó di chuyển xa hơn, bạn có thể thêm chức năng khác vào font-lock-region-functions hoặc đảm bảo quay lại theo chương trình trong khi phân tích cú pháp các cấu trúc nhất định, bên trong font-lock-region-function hoặc syntax-propertize-function.

Một ví dụ về cách tiếp cận thứ hai sẽ là heredoc của Ruby và ruby-syntax-propertize-heredoc trong thân cây Emac. Nó được gọi từ hai nơi trong ruby-syntax-propertize-function. Lần đầu tiên để xử lý các trường hợp khi chúng tôi đã được bên trong một heredoc literal, và sau đó cho bất kỳ heredocs tiếp theo.

4

Tôi sẽ phác thảo chế độ chính đơn giản để làm nổi bật các khối <style> (CSS) và <script> (JavaScript, v.v ...). Để có được khóa phông chữ đa phương thức hoạt động tốt, trước tiên bạn cần bật nó bằng cách đặt font-lock-multiline đến t và viết hàm để thêm font-lock-extend-region-functions. Sau đó, bạn cần phải ghi các đối sánh nhiều dòng — một trong hai biểu thức hoặc hàm thông thường — và thêm chúng vào font-lock-defaults.

Dưới đây là một định nghĩa chế độ chính cơ bản mà tên font khóa danh sách từ khóa (ở đây, test-font-lock-keywords), cho phép khóa phông chữ multiline và thêm các chức năng mở rộng khu vực test-font-lock-extend-region.

chức năng mở rộng
(define-derived-mode test-mode html-mode "Test" 
    "Major mode for highlighting JavaScript and CSS blocks." 
    ;; Basic font lock 
    (set (make-local-variable 'font-lock-defaults) 
     '(test-font-lock-keywords)) 
    ;; Multiline font lock 
    (set (make-local-variable 'font-lock-multiline) t) 
    (add-hook 'font-lock-extend-region-functions 
      'test-font-lock-extend-region)) 

Vùng nên tìm một cái gì đó như thế này:

(defun test-font-lock-extend-region() 
    "Extend the search region to include an entire block of text." 
    ;; Avoid compiler warnings about these global variables from font-lock.el. 
    ;; See the documentation for variable `font-lock-extend-region-functions'. 
    (eval-when-compile (defvar font-lock-beg) (defvar font-lock-end)) 
    (save-excursion 
    (goto-char font-lock-beg) 
    (let ((found (or (re-search-backward "\n\n" nil t) (point-min)))) 
     (goto-char font-lock-end) 
     (when (re-search-forward "\n\n" nil t) 
     (beginning-of-line) 
     (setq font-lock-end (point))) 
     (setq font-lock-beg found)))) 

chức năng này xem xét các biến toàn cục font-lock-begfont-lock-end, có chứa thời gian bắt đầu và vị trí kết thúc của khu vực tìm kiếm, và mở rộng vùng chứa toàn bộ khối văn bản (được phân tách bằng các dòng trống hoặc "\n\n").

Hiện tại, Emacs sẽ tìm kiếm các kết quả phù hợp ở các khu vực lớn hơn, chúng tôi cần thiết lập danh sách test-font-lock-keywords. Có hai cách hợp lý để đi về các cấu trúc đa kết hợp: cụm từ thông dụng sẽ khớp với các dòng và hàm phù hợp. Tôi sẽ đưa ra ví dụ về cả hai. danh sách từ khoá này chứa một biểu hiện thường xuyên cho phù hợp với <style> khối và chức năng cho phù hợp với <script> khối:

(defvar test-font-lock-keywords 
    (list 
    (cons test-style-block-regexp 'font-lock-string-face) 
    (cons 'test-match-script-blocks '((0 font-lock-keyword-face))) 
    ) 
    "Font lock keywords for inline JavaScript and CSS blocks.") 

Các mục đầu tiên trong danh sách này là đơn giản: một biểu thức chính quy và một khuôn mặt để làm nổi bật các trận đấu đó thường xuyên biểu hiện. Thứ hai có vẻ phức tạp hơn một chút, nhưng có thể được khái quát hóa để chỉ định các khuôn mặt khác nhau cho các nhóm khác nhau được xác định trong dữ liệu đối sánh được chỉ định bởi hàm. Ở đây, chúng tôi chỉ đánh dấu nhóm không (toàn bộ kết quả phù hợp) bằng cách sử dụng font-lock-keyword-face. (Các tài liệu có liên quan cho những quẹt là trong phần Search-based fontification của hướng dẫn Emacs.)

Một biểu thức chính quy cơ bản cho phù hợp với <style> khối sẽ là:

(defconst test-style-block-regexp 
    "<style>\\(.\\|\n\\)*</style>" 
    "Regular expression for matching inline CSS blocks.") 

Lưu ý rằng chúng ta phải đặt \n trong nhóm bên trong vì . không khớp với dòng mới.

Các chức năng phù hợp, mặt khác, cần phải tìm kiếm các <script> khối đầu tiên trong khu vực từ điểm đến duy nhất cho luận, last:

(defun test-match-script-blocks (last) 
    "Match JavaScript blocks from the point to LAST." 
    (cond ((search-forward "<script" last t) 
     (let ((beg (match-beginning 0))) 
      (cond ((search-forward-regexp "</script>" last t) 
        (set-match-data (list beg (point))) 
        t) 
       (t nil)))) 
     (t nil))) 

Chức năng này đặt ra các dữ liệu phù hợp , là danh sách có dạng begin-0 end-0 begin-1 end-1 ... cho phần đầu và cuối của nhóm số, nhóm đầu tiên, v.v. Ở đây, chúng tôi chỉ đưa ra giới hạn trên toàn bộ khối đã được đối sánh, nhưng bạn có thể làm điều gì đó hơn phức tạp, chẳng hạn như đặt các khuôn mặt khác nhau cho thẻ và nội dung .

Nếu bạn kết hợp tất cả mã này vào một tệp và chạy M-x test-mode, nó sẽ hoạt động để làm nổi bật hai loại này khối. Trong khi tôi tin rằng điều này thực hiện công việc, nếu có thêm cách hiệu quả hoặc thích hợp để thực hiện việc đó, tôi cũng tò mò muốn biết cũng biết.

Các vấn đề liên quan