【问题标题】:How to define key-binding with arguments for defun in Emacs?如何在 Emacs 中使用 defun 的参数定义键绑定?
【发布时间】:2014-08-17 02:42:09
【问题描述】:

我有一个 defun 可以方便地为标记的表达式添加/删除括号。 (见最后代码)

作为 emacs Lisp 的新手,我只知道如何制作简单的键绑定,无需参数。

但是,我相信如果 defun 的键绑定可以使用两个可选参数来指定是否添加/删除 ()[]{},那么 defun 会更方便

我当前的(简单)键绑定如下,有没有一种简单的方法可以使它像描述的那样接受参数?

(global-set-key (kbd "C-M-( )") 'end-of-statement)

感谢任何建议或方向提示!

(代码:Istvan Chung)

(defun surround-with-parens ()
  (interactive)
  (save-excursion
    (goto-char (region-beginning))
    (insert "("))
  (goto-char (region-end))
  (insert ")"))

(defun delete-surrounded-parens ()
  (interactive)
  (let ((beginning (region-beginning))
        (end (region-end)))
    (cond ((not (eq (char-after beginning) ?\())
           (error "Character at region-begin is not an open-parenthesis"))
          ((not (eq (char-before end) ?\)))
           (error "Character at region-end is not a close-parenthesis"))
          ((save-excursion
             (goto-char beginning)
             (forward-sexp)
             (not (eq (point) end)))
           (error "Those parentheses are not matched"))
          (t (save-excursion
               (goto-char end)
               (delete-backward-char 1)
               (goto-char beginning)
               (delete-char 1))))))

【问题讨论】:

  • 一般问题:C-h f interactive RET。对于这个特定的用例,您可以使用现有的库,但我会把它留给其他人提出建议。
  • 听起来您需要 3 个命令,(){}[] 各一个。您将使用辅助函数定义它们。它是一个辅助函数,它接受一个参数来确定给定命令的类型。 (它可以只接受一个 char 或一个 char 对作为参数:(foo ?\( ?\))(foo ?{ ?}) 等等。您可以将这样的帮助程序用于任意数量的具有 paren 语法的字符对。
  • 您最终解决此问题的方式还取决于您将如何回答以下问题:您想坚持使用单个键绑定吗?如果是这样,请修改defuns 以插入不同类型的括号,具体取决于您在实际键绑定之前点击C-u 的次数。您是否希望能够完全控制插入的分隔符类型?修改defuns 以提示您每次插入/删除分隔符的类型。您是否更喜欢单独的键绑定而不是必须使用 C-u 或被提示?定义和绑定一些额外的函数。
  • 无论如何,键绑定不带参数,它们必须执行的命令。 :)
  • 感谢 cmets。看来这些确实是唯一的选择。

标签: emacs


【解决方案1】:

我认为问题是针对surround-with-parens,因为delete-surrounded-parens 最好只猜测它自己使用的括号。

我还假设您这样做是为了练习而不是实际解决问题。如果您在最近的 Emacsen 中启用 electric-pair-mode,则配置的对将像您的命令一样环绕任何活动区域。但这是一个很好的中级 emacs lisp 练习。

正如 cmets 所说,您有多种选择。

命令参数

一个命令可以接受参数,正如你所要求的。命令与其他 lisp 函数没有什么不同,只是它们有一个 interactive 规范。 interactive 规范告诉 Emacs 在使用键或通过 M-x 调用命令时如何运行命令。

简单的(interactive) 不会向函数传递任何参数。 (interactive "r") 将区域的开头和结尾作为两个参数传递。等等。您可以在C-h f interactive 中了解不同的选项。你甚至可以编写 lisp 代码来计算那里的参数。

您可以使用(interactive "cWrap with: ")。这将提示用户输入密钥,并将密钥传递给您的函数。例如,如果用户键入(,您的函数将接收 40 作为参数,即左括号的字符代码。 ?\( 也是 40,(make-string 1 40) 返回 "("。您必须创建一个地图来找出右括号。

这里的缺点是你需要按两个键:第一个调用命令,然后一个键指定要使用的括号。

多个键

您还可以将命令绑定到不同的键 - 例如,C-M-(C-M-[。然后,您可以使用this-single-command-keys 获取指定最后一个键事件的内容。可悲的是,将其转换回键序列可能有些棘手。例如。 C-M-( 返回[201326632]

多个命令

您也可以为每个括号类型定义一个命令,所有这些都简单地调用一个带参数的通用函数,并将这些命令绑定到键。

post-self-insert-hook

最后,您可以使用与electric-indent-mode相同的方法:在post-self-insert-hook中添加一个函数,然后根据char-before决定您要做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    相关资源
    最近更新 更多