【问题标题】:matching keys in association lists in emacs lispemacs lisp中关联列表中的匹配键
【发布时间】:2010-03-07 02:58:15
【问题描述】:

我在 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)))

[是(实习生)应该以这种方式调用吗?] 我的折叠模式标记列表的截断版本看起来像

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

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

非常感谢!

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    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,这将不起作用,因此最好将其替换为调用一些能够返回合理默认值的自定义函数。

    【讨论】:

    • 不客气。另外,我想我可能会在我的下一轮 Emacs 定制中将你原来的功能合并到我的配置中,所以感谢分享!
    【解决方案2】:

    除了这里的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)))))
    

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

    【讨论】:

    • 谢谢 - 你的结构,特别是 flet 的使用,很漂亮。但是...通过返回(点),函数无法区分第一行有起始标记和根本没有标记,因此当缓冲区以标记开头时失败:P
    • 简直太棒了。我已经为 nil 添加了额外的测试,但是使用从 'or' 运算符返回的最后一个值非常棒。
    【解决方案3】:

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

    (search-backward (concat comment-start "{{{"))
    ...
    (insert comment-start "{{{" comment-end)
    

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

    【讨论】:

    • 谢谢 - 这是我的第一个想法,但正如您从标记上方提供的示例 fold-mode-marks-alist 中看到的那样,需要重复 1 或 2 次注释开始,有时会有在那个和三重大括号之间有空格,等等......这就是为什么我想对 alist 的键进行实际搜索。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多