首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过Emacs Lisp中的函数设置模式

通过Emacs Lisp中的函数设置模式
EN

Stack Overflow用户
提问于 2012-01-05 21:48:29
回答 3查看 539关注 0票数 2

我的.emacs文件中有以下代码,其工作方式与您预期的一样:

代码语言:javascript
复制
;; 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))

然而,我试图把它弄干的尝试却失败了:

代码语言:javascript
复制
(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$"))

..。有以下错误:

代码语言:javascript
复制
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编辑成一对吗?

任何指点(呵呵)都将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-05 22:39:16

形式如下:

代码语言:javascript
复制
(cons '("\\.rb$" . ruby-mode) ...

ruby-mode是引用列表的一部分。这意味着它是作为符号名读取的,而不是作为变量计算的。换句话说,Emacs将其视为ruby-mode符号,并接受它的原样。

形式如下:

代码语言:javascript
复制
(set-mode-for-filename-patterns 
   ruby-mode
   '("\\.rb$"
     "\\.rsel$"
     ...

ruby-mode不被引用,因此被读取为函数的参数。计算函数参数。这意味着Emacs读取ruby-mode,将其识别为符号,并试图对其进行计算。计算符号意味着寻找它所指向的值,在这种情况下,这个值并不存在。

编辑:

你的功能仍然不起作用,还有另外一个问题。您在set-mode-for-filename-patterns中使用了一个引用的列表。这在您的原始代码中运行得很好:

代码语言:javascript
复制
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))

因为您实际上是手动为filename-patternmode提供值的。在您的函数中,您需要对这些符号进行评估,这在引用时不会发生!其结果是,与其将列表中的每个不同的字符串添加到自动模式列表中,相反,您将得到符号filename-pattern

要解决这个问题,您需要识别‘(文件名-模式)。模式)用于生成一个具有filename-patternmode值的cons单元格。我们可以用(反文件名-模式模式)来生产。因此,修正后的职能是:

代码语言:javascript
复制
(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))

修正后的函数调用是:

代码语言:javascript
复制
(set-mode-for-filename-patterns 
  'ruby-mode
  '("\\.rb$"
    "\\.rsel$"
    "\\.rhtml$"
    "\\.erb$" 
    "\\.prawn$"
    "Rakefile$"
    "Gemfile$"))
票数 4
EN

Stack Overflow用户

发布于 2012-01-05 22:35:28

看这里:

代码语言:javascript
复制
(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解释器试图将ruby-mode计算为变量,但是ruby-mode在这个上下文中没有值,因此出现了(void-variable ruby-mode)错误。您想要的是传递符号ruby-mode,所以您必须引用如下(set-mode-for-filename-patterns 'ruby-mode ...)

请注意,可以使用ruby-mode将值设置为let模式。

代码语言:javascript
复制
(let ((ruby-mode 'ruby-mode))
  (set-mode-for-filename-patterns ruby-mode ...))

在这里,当计算表单(set-...)的参数时,它会计算ruby-mode并为它找到一个值(即符号ruby-mode),然后将它传递给函数。

票数 1
EN

Stack Overflow用户

发布于 2012-06-25 01:43:36

我认为set-mode-for-filename-patterns是一个有趣的函数。我将把它添加到我的配置中,但是使用一个更优化的实现。

这里的实现都为每个文件后缀向auto-mode-alist变量添加了一个项。Emacs每次找到文件时都会搜索这个列表。因此,auto-mode-alist越短,Emacs找到文件的速度就越快。

此版本在启动时可能更慢,但在找到文件时更快:

代码语言:javascript
复制
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
  (push (cons (regexp-opt filename-pattern-list) mode)
        auto-mode-alist))`

这将适用于相同的调用:

代码语言:javascript
复制
(set-mode-for-filename-patterns 
   'ruby-mode
   '("\\.rb$"
     "\\.rsel$"
     "\\.rhtml$"
     "\\.erb$" 
     "\\.prawn$"
     "Rakefile$"
     "Gemfile$"))

如果您查看auto-mode-alist的值,您将看到许多内置模式出于相同的性能原因使用regexp。

顺便说一句,我建议你相信regexp-opt会做正确的事情。它所产生的效应对眼睛(和大脑)来说是相当困难的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8750323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档