【问题标题】:(ELisp) automatically nesting next line using brace return(ELisp) 使用大括号返回自动嵌套下一行
【发布时间】:2014-05-24 02:24:55
【问题描述】:

我对 Lisp 和 Emacs 都是全新的。例如,在 Emacs 中,在使用 Java 编码时,我希望能够键入“{”然后点击“ENTER”并让下一行为大括号中嵌套的任何内容做好准备。例如,如果我有以下行:

public void method()

然后我输入“{”然后按回车我应该得到这个:

public void method() {
    // indentation applied, no additional tabbing necessary
}

我已经能够成对插入,例如,键入“{”会得到“{}”,而我的光标位于大括号之间。我通过将这些行添加到 emacs 初始化文件来做到这一点:

;; 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 中编写代码应该很容易。

【问题讨论】:

    标签: emacs formatting elisp key-bindings auto-indent


    【解决方案1】:

    我的 emacs 配置中有类似的东西,我已经使用了一段时间。它调用'newline-and-indent 两次,然后在正确缩进之前将点向上移动一行。这是我的配置文件中的 sn-p 代码:

    ;; 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之外的任何其他模式下使用过它。

    【讨论】:

    • 很棒的解决方案。它按照你说的做,但我不知道你在哪里指定如果在大括号之间有效,我该怎么办我希望它也对括号做同样的事情?
    • 顺便说一句,我在全球范围内使用它,将c-indent-line-or-region 更改为indent-according-to-mode,它似乎可以正常工作
    • 哦,多么愚蠢的问题。对于任何感兴趣的人:只需将 (if (char-equal ?} char-at-point) 更改为 (if (or (char-equal ?} char-at-point) (char-equal ?) char-at-point))
    【解决方案2】:

    很高兴您自己尝试将此功能添加到 Emacs,但无需在此处重新发明轮子。 Emacs 已经有一个用于自动缩进的命令;它被称为newline-and-indent。默认绑定到C-j,但是你可以重新绑定到RET

    1. 全局:

      (global-set-key (kbd "RET") 'newline-and-indent)
      
    2. 仅适用于特定模式:

      (require 'cc-mode)
      (define-key java-mode-map (kbd "RET") 'newline-and-indent)
      

      java-mode-mapcc-mode.el 中定义,默认不可用,这就是为什么你必须先require cc-mode 才能修改java-mode-map


    注意newline-and-indent 根据主要模式缩进。也就是说,如果你是例如在java-mode 中并在某个随机位置按 RET,该位置对 Java 语法没有意义,它不会在新行的开头插入额外的空格。

    阅读有关newline-and-indent的所有信息

    C-h f newline-and-indent RET

    【讨论】:

    • 这不能回答我的问题。我想知道为什么我会收到这个错误。仅当“RET”跟随“{”时,我还需要自动嵌套。简而言之,我希望 Emacs 完全按照 Sublime 或 Eclipse 自动嵌套的方式执行此操作。
    • 当第一个键本身调用命令时,您正在尝试绑定一系列键。也就是说:您将{ 设置为'insert-pair-brace{ 将在您到达return 之前调用它。 @itsjeyd 是对的:您希望通过 'newline-and-indent 自动缩进。 (另请参阅另一个答案中的 emacswiki 链接。)如果您只在左大括号后才自动缩进,您可以将返回键绑定到一个测试前大括号的函数:(if (char-equal (char-before) ?{) (newline-and-indent) (newline))
    • @Dan 谢谢 ;) 我可能应该提到newline-and-indent 根据主要模式缩进,即它会根据当前上下文自动执行正确的操作点...
    • @Occam'sBlade 请查看我的更新答案。另外,Dan 对您所看到的错误原因是正确的^^...
    • 这就是我想要的。我会马上实施。谢谢!
    【解决方案3】:

    您需要自动对(或替代)加上自动缩进的组合。查看前者的 emacswiki:http://www.emacswiki.org/emacs/AutoPairs

    关于后者: http://www.emacswiki.org/emacs/AutoIndentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 2013-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多