2014-05-24 46 views
1

我對Lisp和Emacs都是全新的。在Emacs中,例如在Java中進行編碼時,我希望能夠鍵入「{」,然後點擊「ENTER」,並且爲嵌套在大括號中的任何內容準備好下一行。舉例來說,如果我有以下行:(ELisp)使用大括號自動嵌套下一行返回

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中進行編碼。

回答

1

這是偉大的,你想添加這個功能,Emacs的自己,但沒有必要在這裏重新發明輪子。 Emacs已經有了一個用於自動縮進的命令;它被稱爲newline-and-indent。它默認綁定到CJ,但可以將其重新綁定到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中定義,默認情況下不可用,這就是爲什麼你有至requirecc-mode,然後才能修改java-mode-map


注意newline-and-indent根據主要模式縮進。也就是說,如果你是例如在java-mode並按RET在一些隨機位置,這是沒有意義的W/R/T Java語法,它不會在新行的開始插入額外的空白。

要閱讀所有有了解newline-and-indent

C-H˚Fnewline-and-indentRET

+0

這不回答我的問題。我想知道爲什麼我得到這個錯誤。當「RET」出現在「{」後面時,我也需要自動嵌套。簡而言之,我希望Emacs完全按照Sublime或Eclipse自動嵌套的方式進行操作。 –

+3

您試圖在第一個鍵本身調用命令時綁定一系列鍵。那就是:你將'{'設置爲''insert-pair-brace',這個'{'會在你進入'return'之前調用。 @itsjeyd是對的:你想通過''newline-and-indent'實現自動縮進。 (另請參閱另一個答案中的emacswiki鏈接。)如果僅在打開大括號之後死鎖設置了自動縮進,則可以將返回鍵綁定到測試前大括號的函數,如下所示:'(if( char-equal(char-before)?{)(newline-and-indent)(newline))' – Dan

+1

@丹恩謝謝;)我可能應該提到'newline-and-indent' * indents根據主要模式*,也就是說,它會自動根據當前的上下文來做正確的事情...... – itsjeyd

1

我有我一直在使用了一段時間這在我的emacs配置類似的東西。它調用'newline-and-indent兩次,然後將點移動一行,然後正確縮進。這裏是我的配置文件做到這一點的代碼片段:

;; 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以外,我沒有使用它。

+0

真棒解決方案。它的確如你所說,但我沒有得到你指定的地方,如果在大括號之間,我可以做什麼,我希望它也爲括號做同樣的事情? – divmermarlav

+0

順便說一句我正在使用它全局改變'c-indent-line-or-region'到'indent-according-to-mode'並且它似乎沒有任何缺陷 – divmermarlav

+1

ohh,多麼愚蠢的問題。對於任何感興趣的人:只要將'(if(char-equal?)char-at-point)'改爲'(if(或(char-equal?)char-at-point)點))' – divmermarlav