匹配emacs lisp中关联列表中的键

时间:2010-03-07 02:58:16

标签: emacs elisp

我在emacs中使用折叠模式,并且正在尝试根据模式设置插入适当折叠标记(开始或结束)的功能。到目前为止我已经

(defun insert-folding-mode-mark ()
  (interactive)
  (let ((st "##{{{")
        (en "##}}}") 
        string-to-insert)
    (save-excursion
      (setq string-to-insert
            (let ((here (point))
                  sp ep)
              (setq sp (search-backward st))
              (goto-char here)
              (setq ep (search-backward en))
              (if (< sp ep) st en))))
    (insert string-to-insert)))

这会在(点)插入“## {{{”,除非“## {{{”在它之前,在这种情况下它会插入“##}}}”。 我想将第一个(let)赋值替换为用

之类的东西来确定开始和结束标记的东西
(let* ((match (assoc (intern mode-name) folding-mode-marks-alist))
       (st (nth 1 match))
       (en (nth 2 match)))

[is(intern)意味着以这种方式调用?]我的折叠模式标记alist的截断版本看起来像

((ess-mode "##{{{" "##}}}")
 (tex-mode "%{{{" "%}}}")
 (python-mode "# {{{" "# }}}")
 (emacs-lisp-mode ";;{{{" ";;}}}")
 (TeX-mode "%{{{" "%}}}")
 (LaTeX-mode "%{{{" "%}}}"))

虽然从各种模式返回的模式名称是{“Emacs-Lisp”,“ESS [S]”,“PDFLaTeX”,“Python”,...}。好像我可能想要使用(downcase),(concat x“-mode”)等对字符串进行部分匹配,但是想知道在emacs lisp中是否有一种惯用的方式来做这种与键的匹配一个alist,或者我只需要一个单独的代码块,用(mapcar 'car folding-mode-marks-alist)提取密钥并将每个符号转换为字符串(如何?)来进行匹配?

非常感谢!

3 个答案:

答案 0 :(得分:5)

Emacs Lisp有一个destructuring-bind工具,在这里可能会有所帮助。同时利用通过变量major-mode命名当前主模式的符号这一事实,您可以编写如下内容:

(destructuring-bind (st en) (cdr (assoc major-mode folding-mode-marks-alist))
  ; do stuff
  )

请注意,如果(assoc major-mode folding-mode-marks-alist)返回nil,这将无效,因此最好通过调用某些能够返回合理默认值的自定义函数来替换它。

答案 1 :(得分:3)

除了major-modemode-name更合适之外,如果光标和缓冲区的开头之间没有折叠标记,则上面列出的函数insert-folding-mode-mark会抛出错误。这是一个没有那个怪癖的修订版:

(require 'cl)

(defun insert-folding-mode-mark ()
  (interactive)
  (flet ((fn (s) (save-excursion (or (search-backward s () t) 0))))
    (destructuring-bind (mode st en)
        (or (assoc major-mode folding-mode-marks-alist) '(nil "" ""))
      (insert (if (<= (fn st) (fn en)) st en)))))

编辑:修复评论中指出的问题。

答案 2 :(得分:0)

您可能有兴趣知道有comment-startcomment-end个变量,这些变量应该已包含基于主模式所需的信息。像

这样的东西
(search-backward (concat comment-start "{{{"))
...
(insert comment-start "{{{" comment-end)

应该足够了。当然,对于lisp模式comment-start";"所以你可能想要做你正在做的事情来获得";;"但是对于其他模式可以回到comment-start。你也可以(setq comment-start ";;")虽然我不完全确定lisp模式有什么不同。