Emacs (ELisp)使用大括号返回自动嵌套下一行
我对Lisp和Emacs都是新手。例如,在Emacs中,当用Java编写代码时,我希望能够键入“{”,然后点击“ENTER”,并让下一行准备好嵌套在大括号中的任何内容。例如,如果我有以下行: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 } 我已经能够成对插入,例如,在大括号之间键入“{”将
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))