2009-05-11 6 views
2

さまざまなIDEでは、開いたかっこを入力すると、一致するブレース文字のペアが表示されます。通常、中カッコは状況に応じて挿入されます。文字列リテラル内では、中括弧の間に改行文字が挿入されていません。文字列リテラルの外側には改行があり、物事はすぐにインデントされます。ccモードのスマート電気ブレース(C#、Javaなど)

{ 
    _cursor_ 
} 

カーソルを入力し続けると、新しいコードはすべて正しくインデントされます。

私のccモード(csharp-mode、java-modeなど)では、デフォルトでEmacsでは、開いた中かっこが自動的に挿入され、インデントのない中かっこを挿入します。クローズド・カーリーは、c-e​​lectric-braceを実行します。これは、クローズド・カーリーのみをインデントし、フル・スコープではありません。結果は、中括弧内でキーイングしている間、インデントはすべて間違っています。中括弧が閉じると、手動で中括弧を再インデントしなければなりません。

私が使っている人気のあるIDEのようにEmacsを動作させる簡単な方法はありますか?私はいくつかのEmacs Lispを書いていますが、それはあまり一般的ではなく、私が何かを手掛けているかどうかを知りたいのです。

私はskeleton-pair-insert-maybe関数について知っています。これは、の一致するペアを挿入します。:中括弧、括弧、引用符、山括弧、角括弧しかし、この関数は文脈依存の字下げを行わず、空白の改行を私に与えません。それをインデントする方法がありますか...私が望むものを得るために開いた中にバインドする必要がある別の関数がありますか?

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

答えて

1

これは抜粋をの.emacs(私はいくつかの時間前EmacsWikiにそれを発見している必要があります)何が必要でしょう。

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

私はスペースやタブを押して入力する必要がありませんでした。

2

私はkastauyraの回答を受け入れましたが、私が望むことをやるために私自身のカスタムelispと一緒に行きました。私が投稿した元のelispコードは、いくつかのエッジケースで失敗しました。これは私が今使っている最新のelispコードです。

 (local-set-key (kbd "{") 'cheeso-insert-open-brace) 

結果、私が持っているとき、次のとおりです。

(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するオープンカーリーをバインドこのような何か:

for(;;) 

とオープンカーリーで、キー、私はこれを取得:

for(;;) 
{ 
    _cursor_ 
} 
私はこのような初期化子がある場合

:オープン縮れで

byte[] x = 

とIキーを、私はこれを取得:このため

byte[] x = { _cursor_ }; 
+0

感謝を。ちょうどsidenote、bsdのようなインデントスタイルを使用したくない場合は、代わりに同じように最初のブレースを保持してください。 (if(cheeso-prior-sexp-same-statement-same-line ) (改行とインデント)) cheeso-insert-open-brace関数です。 – sluukkonen

+0

このような小さなジェスチャーを達成するためには、これはたくさんのコードのように見えます。私はこれにもっと洗練された解決策があるのだろうかと思います。 – polyglot

+0

私は同意します。私はそれが私が欲しかったことをするために書かなければならなかったコードの量に失望しました。しかし、これまでのところ誰も簡単な方法を提案していません。 – Cheeso

関連する問題