2012-01-05 59 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