2012-01-05 61 views
2

我在.emacs文件下面的代碼,你會期望它的工作原理:設置模式

;; Ruby 
(global-font-lock-mode 1) 
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t) 
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist)) 
(setq auto-mode-alist (cons '("\\.rsel$" . ruby-mode) auto-mode-alist)) 
(setq auto-mode-alist (cons '("\\.rhtml$" . html-mode) auto-mode-alist)) 
(setq auto-mode-alist (cons '("\\.erb$" . html-mode) auto-mode-alist)) 
(setq auto-mode-alist (cons '("\\.prawn$" . html-mode) auto-mode-alist)) 
(setq auto-mode-alist (cons '("Rakefile$" . ruby-mode) auto-mode-alist)) 

但是,我嘗試烘乾了一下失敗:

(defun set-mode-for-filename-patterns (mode filename-pattern-list) 
    (mapcar 
    (lambda (filename-pattern) 
     (setq 
     auto-mode-alist 
     (cons '(filename-pattern . mode) auto-mode-alist))) 
    filename-pattern-list)) 

;; Ruby 
(global-font-lock-mode 1) 
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t) 
(set-mode-for-filename-patterns 
    ruby-mode 
    '("\\.rb$" 
    "\\.rsel$" 
    "\\.rhtml$" 
    "\\.erb$" 
    "\\.prawn$" 
    "Rakefile$" 
    "Gemfile$")) 

...,出現以下錯誤:

Debugger entered--Lisp error: (void-variable ruby-mode) 
    (set-mode-for-filename-patterns ruby-mode (quote ("\\.rb$" "\\.rsel$" "\\.rhtml$" "\\.erb$" "\\.prawn$" "Rakefile$" "Gemfile$"))) 
    eval-buffer(#<buffer *load*> nil "/home/duncan/.emacs" nil t) ; Reading at buffer position 1768 
    load-with-code-conversion("/home/duncan/.emacs" "/home/duncan/.emacs" t t) 
    load("~/.emacs" t t) 
    #[nil "\205\264 

我有點困惑在這裏...特別是,我不知道下站在如何ruby-mode是無效的&所以不能傳遞給一個函數,但可以cons編成一對?

任何指針(heh)將不勝感激。

回答

4

形式:

(cons '("\\.rb$" . ruby-mode) ... 

ruby-mode是帶引號的列表的一部分。這意味着它被讀作符號名稱,而不是作爲變量進行評估。換句話說,Emacs將其視爲符號ruby-mode並接受它。

形式:

(set-mode-for-filename-patterns 
    ruby-mode 
    '("\\.rb$" 
    "\\.rsel$" 
    ... 

ruby-mode不是引用,因此讀取爲參數的函數。評估函數參數。這意味着Emacs讀取ruby-mode,將其識別爲符號,並嘗試對其進行評估。評估符號意味着尋找它指向的值,在這種情況下它不存在。

編輯:

您的功能仍然無法正常工作,還有另一個問題。您在set-mode-for-filename-patterns內使用了一個引用列表。因爲你是有效期爲filename-patternmode手動供應

(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist)) 

:這在你原來的代碼工作正常。在你的功能裏面,你需要這些符號評估,這在引用時不會發生!結果是,不是將您的列表中的每個不同的字符串添加到自動模式alist中,而是代之以符號filename-pattern

要解決這個問題,你需要認識到「(文件名模式。模式)是爲了產生與filename-patternmode一個cons單元。我們可以製作(cons文件名模式模式)。所以校正功能是:

(defun set-mode-for-filename-patterns (mode filename-pattern-list) 
    (mapcar 
    (lambda (filename-pattern) 
     (setq 
     auto-mode-alist 
     (cons (cons filename-pattern mode) auto-mode-alist))) 
    filename-pattern-list)) 

和校正的功能調用是:

(set-mode-for-filename-patterns 
    'ruby-mode 
    '("\\.rb$" 
    "\\.rsel$" 
    "\\.rhtml$" 
    "\\.erb$" 
    "\\.prawn$" 
    "Rakefile$" 
    "Gemfile$")) 
1

看看這裏:

(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist)) 
----------------------------^ 

這是一個quote這意味着您避免在未來 形式的評估,從而'("\\.rb$" . ruby-mode)相當於(cons '"hello" 'ruby-mode)

但是,當您調用函數set-mode-for-filename-patterns時,首先會計算參數 ,然後將其結果傳遞給 函數。這就是爲什麼評估(set-mode-for-filename-patterns ruby-mode ..)引發錯誤的原因,因爲emacs-lisp解釋器嘗試 來評估ruby-mode作爲變量,但ruby-mode在此上下文中沒有值 因此錯誤(void-variable ruby-mode)。你 想要的這裏,是通過符號ruby-mode所以你要引用它 喜歡,你可以一個值都設置爲ruby-mode模式let(set-mode-for-filename-patterns 'ruby-mode ...)

注意。

(let ((ruby-mode 'ruby-mode)) 
    (set-mode-for-filename-patterns ruby-mode ...)) 

這裏當參數形式(set-...)被評估它計算 ruby-mode並且能夠爲它找到一個值(這是符號 ruby-mode),然後將其傳遞給該函數。

1

我覺得set-mode-for-filename-patterns是一個有趣的功能。我將把它添加到我的配置中,但使用更優化的實現。

這裏的實現全部爲每個文件後綴的auto-mode-alist變量添加一項。 Emacs每次找到文件時都會搜索此列表。所以更短的auto-mode-alist,更快的Emacs將找到文件。

這個版本很可能是在啓動較慢,但速度更快查找文件時:

(defun set-mode-for-filename-patterns (mode filename-pattern-list) 
    (push (cons (regexp-opt filename-pattern-list) mode) 
     auto-mode-alist))` 

這將與同一呼叫工作:

(set-mode-for-filename-patterns 
    'ruby-mode 
    '("\\.rb$" 
    "\\.rsel$" 
    "\\.rhtml$" 
    "\\.erb$" 
    "\\.prawn$" 
    "Rakefile$" 
    "Gemfile$")) 

如果你看看auto-mode-alist值你」我們會發現許多內置模式都使用regexps來實現相同的性能。

順便說一句,我建議你只相信regexp-opt做正確的事情。它所做的正則表達式在眼睛(和大腦)上相當困難。

+0

傳遞給'regexp-opt'參數列表的成員本身不能是正則表達式。另見http://stackoverflow.com/questions/11027783/how-can-i-cons-a-list-of-pairs-on-to-auto-mode-alist/11030085#11030085 – phils 2012-06-25 03:12:29