在各种 IDE 中,键入左花括号会导致出现一对匹配的大括号字符。通常,大括号以某种上下文相关的方式插入。在字符串文字中,大括号之间没有插入换行符。在字符串文字之外,有一个换行符,并且内容会立即缩进。
{
_cursor_
}
当我继续在光标处键入时,所有新代码都会正确缩进。
但是,在 Emacs 中,默认情况下在我的 cc 模式(csharp 模式、java 模式等)下,开 curl 运行 self-insert-命令,该命令仅插入不带缩进的开大括号。闭合 curl 运行 c-electric-brace,它仅缩进闭合 curl ,而不是完整范围。结果是,当我在 curl 范围内键入时,缩进完全错误,并且我必须在 curl 范围关闭时手动重新缩进。
有没有一种简单的方法可以让 Emacs 表现得像我用过的流行 IDE 一样?我已经写了一些 Emacs Lisp 来做,但它不是很通用,我想知道我是否遗漏了一些东西。
我知道 skeletal-pair-insert-maybe 函数。它插入匹配的任意对:大括号、括号、引号、尖括号、方括号。但该函数不会执行任何上下文相关的缩进,也不会给我空白换行符。有没有办法让它缩进或者...是否有另一个函数我应该绑定(bind)到 open-curly 以获得我想要的东西?
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
)
)
)
最佳答案
我接受了 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 模式 Hook 函数中,我将开 curl “{”绑定(bind)到 cheeso-insert-open-brace,如下所示:
(local-set-key (kbd "{") 'cheeso-insert-open-brace)
结果是,当我有这样的事情时:
for(;;)
然后输入一个开放的 curl ,我得到这个:
for(;;)
{
_cursor_
}
如果我有这样的初始化程序:
byte[] x =
我输入一个开放的卷发,我得到这个:
byte[] x = { _cursor_ };
关于c# - cc 模式下的智能电动支架(C#、Java 等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/848624/