在各种IDE中,键入开放卷曲会导致匹配的一对大括号字符出现。通常,大括号以某种上下文敏感的方式插入。在字符串文字中,在括号之间没有插入插入的换行符。在字符串文字之外,有一个换行符,并且事物会立即缩进。
{
_cursor_
}
当我继续键入光标时,所有新代码都正确缩进。
在Emacs中,默认情况下,在我的cc模式(csharp-mode,java-mode等)中,open-curly运行self-insert-command,它只插入没有缩进的open大括号。近距离卷曲运行c-electric-brace,它只收缩近卷曲,而不是整个范围。结果是当我在卷曲范围内键入时,缩进是完全错误的,并且我必须在它关闭时手动重新缩进卷曲范围。
有没有一种简单的方法可以让Emacs像我用过的流行IDE一样?我已经编写了一些Emacs Lisp,但它不是很通用,我想知道我是不是在搞什么。
我知道骨架对插入可能的功能。它插入匹配的无论:括号,parens,引号,尖括号,方括号。但是该函数不执行任何上下文相关的缩进,并且不会给我空白的换行符。有没有办法让它缩进或...是否有另一个函数我应该绑定到开放卷曲来得到我想要的?
PS:我的Emacs Lisp看起来像这样:
; The default binding for "open curly" was skeleton-pair-insert-maybe. It
; inserts a pair of braces and then does not insert a newline, and does not
; indent. I want the braces to get newlines and appropriate indenting. I
; think there is a way to get this to happen appropriately just within emacs,
; but I could not figure out how to do it. So I wrote this alternative. The
; key thing is to determine if the point is within a string. In cc-mode, this
; is at least sometimes done by looking at the font face. Then, if not in a
; literal string, do the appropriate magic. This seems to work.
(defun cheeso-insert-open-brace ()
"if point is not within a quoted string literal, insert an open brace, two newlines, and a close brace; indent everything and leave point on the empty line. If point is within a string literal, just insert a pair or braces, and leave point between them."
(interactive)
(if
; are we inside a string?
(c-got-face-at (point) c-literal-faces)
; if so, then just insert a pair of braces and put the point between them
(progn
(self-insert-command 1)
(insert "}")
(backward-char)
)
; not inside a literal string.
; therefore, insert paired braces with an intervening newline, and indent everything appropriately.
(progn
(self-insert-command 1)
(c-indent-command)
(newline)
(insert "}")
(c-indent-command)
(previous-line)
(newline-and-indent)
; point ends up on an empty line, within the braces, properly indented
)
)
)
答案 0 :(得分:2)
我接受了kastauyra的答案,但仍然使用我自己的自定义elisp来做我想要的,这是适当插入一组匹配的括号。我发布的原始elisp代码失败了几个边缘情况。这是我现在使用的更新的elisp代码。
(defun cheeso-looking-back-at-regexp (regexp)
"calls backward-sexp and then checks for the regexp. Returns t if it is found, else nil"
(interactive "s")
(save-excursion
(backward-sexp)
(looking-at regexp)
)
)
(defun cheeso-looking-back-at-equals-or-array-init ()
"returns t if an equals or [] is immediate preceding. else nil."
(interactive)
(cheeso-looking-back-at-regexp "\\(\\w+\\b *=\\|[[]]+\\)")
)
(defun cheeso-prior-sexp-same-statement-same-line ()
"returns t if the prior sexp is on the same line. else nil"
(interactive)
(save-excursion
(let ((curline (line-number-at-pos))
(curpoint (point))
(aftline (progn
(backward-sexp)
(line-number-at-pos))) )
(= curline aftline)
)
)
)
(defun cheeso-insert-open-brace ()
"if point is not within a quoted string literal, insert an open brace, two newlines, and a close brace; indent everything and leave point on the empty line. If point is within a string literal, just insert a pair or braces, and leave point between them."
(interactive)
(cond
;; are we inside a string literan?
((c-got-face-at (point) c-literal-faces)
;; if so, then just insert a pair of braces and put the point between them
(self-insert-command 1)
(insert "}")
(backward-char)
)
;; was the last non-space an equals sign? or square brackets? Then it's an initializer.
((cheeso-looking-back-at-equals-or-array-init)
(self-insert-command 1)
;; all on the same line
(insert " };")
(backward-char 3)
)
;; else, it's a new scope.
;; therefore, insert paired braces with an intervening newline, and indent everything appropriately.
(t
(if (cheeso-prior-sexp-same-statement-same-line)
(newline-and-indent))
(self-insert-command 1)
(c-indent-line-or-region)
(end-of-line)
(newline)
(insert "}")
;;(c-indent-command) ;; not sure of the difference here
(c-indent-line-or-region)
(previous-line)
(end-of-line)
(newline-and-indent)
; point ends up on an empty line, within the braces, properly indented
)
)
)
在我的c-mode钩子函数中,我将开放式卷曲'{'绑定到cheeso-insert-open-brace,如下所示:
(local-set-key (kbd "{") 'cheeso-insert-open-brace)
结果是,当我有这样的事情时:
for(;;)
然后键入一个开卷曲,我明白了:
for(;;)
{
_cursor_
}
如果我有这样的初始化程序:
byte[] x =
我按开放式卷曲,我明白了:
byte[] x = { _cursor_ };
答案 1 :(得分:1)
这个.emacs摘录(我必须在EmacsWiki前一段时间找到它)会做你需要的:
;; Enter indents the new line
(defun my-make-CR-do-indent ()
(define-key c-mode-base-map "\C-m" 'c-context-line-break))
(add-hook 'c-initialization-hook 'my-make-CR-do-indent)
像这样工作:
int main(void)
{
{
{
{
我无处按空格或标签进入。