2012-02-02 22 views
7

Tôi đã bắt đầu viết kịch bản Emacs theo hướng dẫn được đưa ra tại http://www.emacswiki.org/emacs/EmacsScripts, mà về cơ bản nói rằng kịch bản của bạn nên bắt đầu với:Emacs Lisp: có thể cùng một regexp khớp với hai mẫu khác nhau với cùng số nhóm không?

:;exec emacs --script "$0" [email protected] 

Bây giờ tôi muốn tùy chỉnh auto-mode-interpreter-regexp' accordingly, to make Emacs scripts automatically loaded with emacs-lisp-mode'.

Bản gốc 'auto-mode-dịch-regexp' có nghĩa là để phù hợp với:

#! /bin/bash 
#! /usr/bin/env perl 

và như vậy, và do đó nó là một điều này:

"\\(?:#![ ]?\\([^  \n]*/bin/env[ ]\\)?\\([^ \n]+\\)\\)" 

tôi đã cố gắng thêm mới regexp là một giải pháp thay thế:

(setq auto-mode-interpreter-regexp 
    (concat ;; match "#! /bin/bash", "#! /usr/bin/env perl", etc. 
      "\\(?:#![ ]?\\([^  \n]*/bin/env[ ]\\)?\\([^ \n]+\\)\\)" 
      ;; or 
      "\\|" 
      ;; match ":;exec emacs " 
      "\\(?::;[ ]?\\(exec\\)[ ]+\\([^  \n]+\\)[ ]*\\)")) 

nhưng điều này, trong khi khớp với toàn bộ chuỗi, không nắm bắt được các bản con, ecially thứ hai là cần thiết để phát hiện các thông dịch viên. Do đó, tôi đã trộn lẫn regexp để đối sánh cả hai tiêu đề cùng một lúc:

(setq auto-mode-interpreter-regexp 
    (concat ;; match "#!" or ":;" 
      "\\(?:#!\\|:;\\)" 
      ;; optional spaces 
      "[ ]?" 
      ;; match "/bin/bash", "/usr/bin/env" or "exec" 
      "\\(\\[^ \n]*/bin/env[ ]\\|exec[ ]\\)?" 
      ;; match interpreter 
      "\\([^ \n]+\\)")) 

Tôi có thể làm tốt hơn không? Cảm ơn bạn.

Trả lời

1

Regexp in Emacs hỗ trợ sử dụng cấu trúc "nhóm được đánh số rõ ràng" để chỉ định số nhóm cho bất kỳ phụ trang nào. Xem Elisp Manual 34.3.1.3 Backslash Constructs in Regular Expressions.

Cú pháp là ‘(?num: ...)’, trong đó num là số nhóm được chọn.

+0

Ồ, vâng, tôi hoàn toàn quên mất điều đó. Tốt, huaiyuan! – Thomas

1

Các nhóm của một regexp được xác định bởi các dấu ngoặc đơn xuất hiện trong nó. Đó là lý do tại sao lần thứ hai trong số ba kết quả regexps của bạn không thể được sử dụng trong trường hợp này: "exec" và "emacs" được ghi lại theo nhóm 3 và 4 tương ứng, nhưng auto-mode-interpreter-regexp hy vọng tên của trình thông dịch kịch bản nằm trong nhóm 2.

(EDIT: những gì tôi đã viết ở trên là sai, ngoại trừ sự liên quan của nhóm 2 cho auto-mode-interpreter-regexp Xem câu trả lời Huaiyuan cho những hiểu biết..)

Từ các tài liệu của nói biến:

biểu thức chính quy phù hợp thông dịch viên, để xác định chế độ tập tin. Biểu thức chính quy được đối sánh với dòng đầu tiên của tệp là xác định chế độ của tệp trong 'chế độ tự động cài đặt'. Nếu nó khớp với, tệp được giả định là thông dịch viên được kết hợp bởi nhóm thứ hai thứ hai của cụm từ thông dụng.

Tôi nghĩ giải pháp cuối cùng của bạn trông khá tốt. Hai ý kiến:

  1. Regexp gốc được gói trong \\(?:...\\). Điều này không ảnh hưởng đến kết quả phù hợp, nhưng nếu bạn sử dụng nó kết hợp với các regexps khác, nó có thể hữu ích trong trường hợp bạn thêm một toán tử postfix:

    (setq my-regexp (concat auto-mode-interpreter- regexp "?"))

  2. Regexp của bạn bây giờ cũng khớp với các nội dung như #!exec..., có thể không có vấn đề gì. Điều này phát sinh bởi vì bạn đã tính ra shebang, đó là điều đúng để làm như (match-string 1) là để phù hợp với các (/usr)/bin/env hoặc exec tương ứng, mà không bao gồm các shebang.

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