如何让Emacs自动插入闭合括号?

9

我刚开始使用emacs,有一个功能我非常需要,但搜索了一下没有结果。希望有其他人已经实现了这个功能,因为我暂时不想学习elisp。

void foo()<cursor>

我希望键入"{"会引发这种情况。
void foo(){
    <cursor>
}

我希望这只在cc-mode中发生,并且仅在不在字符串/注释等情况下的行末发生。
我首先想到的是将“{”重新绑定为始终执行此操作(我可以自己弄清楚如何做到这一点),但很难使它仅在正确的时间发生。
如果有任何提示,将不胜感激。

我认为这是与https://dev59.com/bHNA5IYBdhLWcg3wSrua重复的问题。 - Laurynas Biveinis
我看了那个问题,但它只是关于添加右括号/大括号/等的。 我想让它换两行,缩进并将光标重新定位到空行。 - Bwmat
7个回答

9
在最新版本的emacs中,你可以使用以下命令:
electric-pair-mode is an interactive compiled Lisp function.

(electric-pair-mode &optional ARG)

Automatically pair-up parens when inserting an open paren.

这已经集成在Emacs 24.1中了(实际上是CVS)。

5
这将完成它:
(defun my-c-mode-insert-lcurly ()
  (interactive)
  (insert "{")
  (let ((pps (syntax-ppss)))
    (when (and (eolp) (not (or (nth 3 pps) (nth 4 pps)))) ;; EOL and not in string or comment
      (c-indent-line)
      (insert "\n\n}")
      (c-indent-line)
      (forward-line -1)
      (c-indent-line))))

(define-key c-mode-base-map "{" 'my-c-mode-insert-lcurly)

4

在 Emacs 24 或更新版本中打开 electric-pair-mode。

(electric-pair-mode 1)

3
我强烈推荐您尝试优秀的autopair小模式 - 它不仅可以简单地插入大括号,还可以使Emacs在这个领域更像IDE。我想将它与cc-mode中的电动括号设置相结合,将会给您带来更多或者更少您所寻求的行为。

2

尝试使用yasnippet(或在Emacs Wiki页面yasnippet)。有许多Emacs包支持此类操作,但是yasnippet目前似乎具有动力并且非常可扩展。看看这些视频。


这似乎不是理想的,我需要按tab键才能展开它,如果"{"前面没有空格,它就不起作用。 - Bwmat
你可能可以修改模板以去除空格。修改/创建模板非常容易。 - Matt Harrison

1

如果您希望保留空函数体的选项,那么您会想让闭合大括号保持在同一行。如果是这种情况,那么您可以尝试这种替代方案:

  1. Rely on the packages mentioned in the previous replies to automatically add the closing brace.
  2. When you want to add statements to the function body, you press the Return key (while the automatically added closing brace is still under the cursor). The 'Return' key is bound as follows:

    ;; automatic first line in function                                             
    (defun my-c-mode-insert-funline ()
      (interactive)
      (newline-and-indent)
      (when (looking-at "}")
        (newline-and-indent)
        (forward-line -1)
        (c-indent-line)))
    (global-set-key (kbd "RET") 'my-c-mode-insert-funline)
    

1

你需要深入了解emacs-lisp才能完全按照你的要求做到这一点,因为YASnippet会为你做一些好事,但不完全是你所要求的。

我认为最简单的方法是将一个函数绑定到cc-mode键映射中的RET键上。

该函数应检查前一个字符是否为{,如果是,则执行所需的RETRETTAB}UpTAB,以使光标到达您想要的位置并插入闭合}

您可以通过让它检查平衡的闭合}来使该功能更加健壮,但这将更加复杂,我建议先试试没有这个额外的抛光功能。

如果您愿意,我可以为您编写函数和键映射绑定,但由于您要求提供如何完成此操作的想法,因此如果您需要更多帮助,我将留给您自己来寻求。

或者,我发现autopair.el已经很好地为我完成了这个任务,而我自己处理换行符 ;)


这正是我所想的。在Lisp函数内部,有没有一种简单的方法可以检查我是否处于注释/字符串中以及是否到达行尾?我知道cc-mode在内部执行此操作,如果我可以直接使用它,那将非常方便。 - Bwmat
你可以使用thing-at-point来确定你所处的上下文。 - ocodo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接