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

标签 c# java emacs

在各种 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/

相关文章:

Emacs - 如何在导航时避免回溯光标移动

javascript - 添加/删除 CSS 类属性以尊重不基于 Div id 的类

c# - 无法在 Azure DocumentDB 中进行分页

java - Jsoup如何返回页面内脚本生成的电子邮件ID

java - Elasticsearch 单元测试

emacs - 如何更改 emacs 中的空白颜色?

emacs - 要使用哪些 "safe"Emacs 用户键绑定(bind)命名空间?

c# - 如何在WP7中将字符串转换为UTF-8字符串格式

c# - 意外的字符串总和

java - Android 12 启动画面 API - 增加启动画面持续时间