Emacs (ELisp)使用大括号返回自动嵌套下一行

Emacs (ELisp)使用大括号返回自动嵌套下一行,emacs,formatting,elisp,key-bindings,auto-indent,Emacs,Formatting,Elisp,Key Bindings,Auto Indent,我对Lisp和Emacs都是新手。例如,在Emacs中,当用Java编写代码时,我希望能够键入“{”,然后点击“ENTER”,并让下一行准备好嵌套在大括号中的任何内容。例如,如果我有以下行: public void method() 我输入“{”,然后点击回车键,我会得到: public void method() { // indentation applied, no additional tabbing necessary } 我已经能够成对插入,例如,在大括号之间键入“{”将

我对Lisp和Emacs都是新手。例如,在Emacs中,当用Java编写代码时,我希望能够键入“{”,然后点击“ENTER”,并让下一行准备好嵌套在大括号中的任何内容。例如,如果我有以下行:

public void method()
我输入“{”,然后点击回车键,我会得到:

public void method() {
    // indentation applied, no additional tabbing necessary
}
我已经能够成对插入,例如,在大括号之间键入“{”将光标置于“{}”中

;; insert by pairs (parens, quotes, brackets, braces)
(defun insert-pair (leftChar rightChar)
  (if (region-active-p)
      (let (
        (p1 (region-beginning))
        (p2 (region-end))
        )
    (goto-char p2)
    (insert rightChar)
    (goto-char p1)
    (insert leftChar)
    (goto-char (+ p2 2))
    )
(progn
  (insert leftChar rightChar)
  (backward-char 1) ) )
  )
(defun insert-pair-brace () (interactive) (insert-pair "{" "}") )
(global-set-key (kbd "{") 'insert-pair-brace)
为了获得上面描述的自动嵌套,我添加了以下行:

;; automatically nest next line
(defun auto-nest ()
  (insert "\n\n")
  (backward-char 1)
  (insert "\t")
)
(defun auto-nest-brace () (interactive) (auto-nest) )
(global-set-key (kbd "{ RET") 'auto-nest-brace)
但是,当我启动Emacs时,我收到以下消息:

error: Key sequence { RET starts with non-prefix key {

我做错了什么,我能做些什么来修复它?我不想使用不同的组合键来实现这一点。有很多文本编辑器中,这种自动嵌套是标准的,在ELisp中编写代码应该很容易。

您想要一个自动对(或备选方案)的组合吗加上自动缩进。查看前一页上的emacswiki:

关于后者:

您自己尝试将此功能添加到Emacs是件好事,但不需要在这里重新发明轮子。Emacs已经有一个用于自动缩进的命令;它被称为
换行和缩进
。默认情况下,它绑定到C-j,但您可以将其重新绑定到RET

  • 全球:

    (global-set-key (kbd "RET") 'newline-and-indent)
    
  • 仅针对特定模式:

    (require 'cc-mode)
    (define-key java-mode-map (kbd "RET") 'newline-and-indent)
    
    java模式映射
    是在
    cc mode.el中定义的,默认情况下不可用,这就是为什么在修改
    java模式映射
    之前必须
    要求
    cc mode


  • 请注意,
    换行和缩进
    根据主模式缩进。也就是说,如果您处于
    java模式
    中,并在一些随机位置按RET键,而这些位置不具有java语法的意义,则不会在新行的开头插入额外的空格

    阅读所有关于新行和缩进的知识


    C-h f
    换行和缩进
    RET

    我在emacs配置中使用了一些类似的东西,我已经使用了一段时间。它调用了两次“换行和缩进”
    ,然后在正确缩进之前将点上移一行。下面是从我的配置文件中执行此操作的代码片段:

    ;; auto indent on opening brace
    (require 'cc-mode)
    (defun av/auto-indent-method ()
      "Automatically indent a method by adding two newlines.
    Puts point in the middle line as well as indent it by correct amount."
      (interactive)
      (newline-and-indent)
      (newline-and-indent)
      (forward-line -1)
      (c-indent-line-or-region))
    
    (defun av/auto-indent-method-maybe ()
      "Check if point is at a closing brace then auto indent."
      (interactive)
      (let ((char-at-point (char-after (point))))
        (if (char-equal ?} char-at-point)
            (av/auto-indent-method)
          (newline-and-indent))))
    
    (define-key java-mode-map (kbd "RET") 'av/auto-indent-method-maybe)
    

    正如您所看到的,非常简单。希望它能为您工作。除了java之外,我没有在任何其他模式中使用过它。

    这并不能回答我的问题。我想知道为什么会出现此错误。我还需要只有在“{”之后出现“RET”时才进行自动嵌套简言之,我希望Emacs完全按照升华或Eclipse自动嵌套的方式来执行。当第一个键本身调用命令时,您正在尝试绑定一系列键。也就是说:您将
    {
    设置为
    'insert-pair-brake
    ,这
    {
    将在您到达
    返回之前调用
    @itsjeyd是对的:您希望通过
    的newline-and-indent
    自动缩进(另一个答案中的emacswiki链接)如果只在开始大括号后自动缩进,则可以将返回键绑定到测试前面大括号的函数:
    (If(char equal(char before)?{)(换行和缩进)(换行))
    @Dan谢谢;)我可能应该提到,
    换行和缩进
    根据主模式缩进,也就是说,它将根据point的当前上下文自动执行正确的操作…@Occam's blade请查看我的更新答案。此外,Dan关于您看到的错误原因是正确的^^…这就是我所看到的ing for。我会马上实现。谢谢!很棒的解决方案。它按照你说的做,但我不知道你在哪里指定这是有效的如果在大括号之间,我该怎么做我希望它对括号也做同样的事情?顺便说一句,我正在全局使用它,将
    c-indent-line-or-region
    更改为
    根据模式缩进
    ,并且t似乎工作正常。这是一个多么愚蠢的问题。对任何感兴趣的人来说:只需将
    (if(char equal?}char at point)
    更改为
    (if(or(char equal?}char at point)(char equal?}char at point))