cc模式下的智能电动支架(C#、Java等)

cc模式下的智能电动支架(C#、Java等),c#,java,emacs,C#,Java,Emacs,在各种IDE中,键入开放卷曲会导致出现一对匹配的大括号字符。通常,大括号是以某种上下文相关的方式插入的。在字符串文字中,大括号之间没有插入新行。在字符串文本之外,有一个换行符,并且立即缩进 { _cursor_ } 当我继续在光标处键入时,所有新代码都正确缩进 不过,在Emacs中,默认情况下在我的cc模式(csharp模式、java模式等)下,open curly运行self insert命令,该命令只插入没有缩进的大括号。close curly运行c-electric-brace,

在各种IDE中,键入开放卷曲会导致出现一对匹配的大括号字符。通常,大括号是以某种上下文相关的方式插入的。在字符串文字中,大括号之间没有插入新行。在字符串文本之外,有一个换行符,并且立即缩进

{
    _cursor_
}
当我继续在光标处键入时,所有新代码都正确缩进

不过,在Emacs中,默认情况下在我的cc模式(csharp模式、java模式等)下,open curly运行self insert命令,该命令只插入没有缩进的大括号。close curly运行c-electric-brace,它只缩进close curly,而不是整个范围。结果是,当我在卷曲范围内键入时,缩进完全错误,当卷曲范围关闭时,我必须手动重新缩进

有没有一种简单的方法可以让Emacs像我使用过的流行IDE一样工作?我已经写了一些Emacs Lisp来做,但它不是很一般,我想知道我是否误解了什么

我知道骨架对插入功能。它插入任何匹配的对:大括号、括号、引号、尖括号、方括号。但是这个函数不会做任何上下文敏感的缩进,也不会给我空白的换行符。有没有办法让它缩进或。。。是否还有其他函数需要绑定到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
      )
    )
  )
for(;;)
byte[] x =
这个.emacs摘录(我一定是很久以前在网上找到的)将满足您的需要:

;; 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)
{
  {
    {
      {

在任何地方,我都不需要按空格键或tab键来输入。我接受了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模式钩子函数中,我将开放卷曲“{”绑定到cheeso insert开放大括号,如下所示:

     (local-set-key (kbd "{") 'cheeso-insert-open-brace)
结果是,当我有这样的东西时:

; 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
      )
    )
  )
for(;;)
byte[] x =
然后输入一个开放式卷发,我得到:

for(;;)
{
   _cursor_
}
byte[] x = { _cursor_ };
如果我有这样一个初始值设定项:

; 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
      )
    )
  )
for(;;)
byte[] x =
我输入一个开放式卷发,我得到:

for(;;)
{
   _cursor_
}
byte[] x = { _cursor_ };

谢谢。如果您不想使用类似bsd的缩进样式,而是将第一个大括号保持在相同的位置,只需删除(if(cheeso-prior-sexp-same-statement-same-line)(换行和缩进))从cheeso insert open brace函数中。我不得不说,这看起来像是许多代码来完成这样一个小动作;我想知道是否有更优雅的解决方案。我同意;我对我必须编写的代码量感到失望。但是,到目前为止,还没有人提出一种更简单的方法来完成它。ps:this代码和其他C#-有帮助的elisp现在可以在中使用,您可以下载、提出bug、贡献等等。