インデントされたブロックの前にコードを追加または削除するときに、elispコードを自動的に再インデントする


18

次のようなelispコードがあるとします。

(+ 2 3▮(+ 3
          4))

シンボルを追加または削除したときに、カーソルの後にsexpを自動的に再インデントする方法はありますか?

を押した後SPC 4 SPC、私は自動的に取得します:

(+ 2 3 4 ▮(+ 3
             4))

私は呼び出すことで、このマニュアルを行うことができますmark-sexpが続きますindent-region。これを行うより良い方法はありますか?


便利なデフォルトのキーバインドはないと思いますが、自分で簡単に作成できます。
shosti 14

私は知っていますが、これを行うためのより良い方法があるのか​​具体的に疑問に思っています。例えば、どのようにelectric-indent-modeはるかに優れたマッピングより<return>newline-and-indent
マチェイGoszczycki

回答:


14

mark-sexp+の代わりにindent-region、を押すことができますC-M-q。これはを呼び出しますindent-pp-sexp。自動ではありませんが、2つのコマンドを呼び出さなければならないよりも少し優れています。

または、使用している場合はをparedit-mode押しM-qます。これにより、現在の関数定義全体が再インデントされます。


1
(add-hook 'post-self-insert-hook 'indent-pp-sexp)驚くほどうまく機能します。
マチェイゴシュチッキ14

いいね。モードによってはコストがかかる場合がありますが、それでも素晴らしいアプローチです。
ドミトリー14

Smartparensユーザーの場合、で現在の定義を再インデントできますM-x sp-indent-defun。これをにバインドしC-M-qます。
ラドンロズバラ

15

積極的なインデントモード

何人かの人々がそれを求めたので、私はこの答えをパッケージに変え ました

Melpaが構成されている場合は、次のコマンドでインストールできます。

M-x package-install RET aggressive-indent

すべてのオプションについてはReadmeを参照してください。ただし、有効にする最も簡単な方法は次のとおりです。

(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)

古い答え

以下は、elispバッファーでのみ自動インデントを行います。(入力するだけでなく)ものを消去したりヤンクしたりするときにも機能するという利点があります。他のモードにも簡単に追加できます。

この関数は、ポイントが現在内部にあるs-expressionをインデントします。必要に応じてキーにバインドできますが、最初に以下を参照してください。

(require 'cl-lib)

(defun endless/indent-defun ()
  "Indent current defun.
Do nothing if mark is active (to avoid deactivating it), or if
buffer is not modified (to avoid creating accidental
modifications)."
  (interactive)
  (ignore-errors
    (unless (or (region-active-p)
                buffer-read-only
                (null (buffer-modified-p)))
      (let ((l (save-excursion (beginning-of-defun 1) (point)))
            (r (save-excursion (end-of-defun 1) (point))))
        (cl-letf (((symbol-function 'message) #'ignore))
          (indent-region l r))))))

このフックは、elispバッファーでのみ、何かを入力した後にこの関数が実行されるようにします。これにより、すべてが常にインデントされます。

(add-hook
 'emacs-lisp-mode-hook
 (lambda ()
   (add-hook 'post-command-hook
             #'endless/indent-defun nil 'local)))

それを試してみてください!それは非常にうまく機能します。

また、コメントでの@holocronweaverの提案に従って、Cライクな言語に対して次のようなものを使用できます。

(define-key c++-mode-map ";"
  (lambda () (interactive)
    (insert ";")
    (endless/indent-defun)))

これが自動インデントメッセージを沈黙させ、セミコロンで行を終了する言語をより適切に処理する場合、優れているでしょう。
holocronweaver 14

@holocronweaver確かに、私はそれを試すことができます。どのメジャーモードにインデントメッセージがありますか?そして、セミコロンの問題は何ですか?
マラバルバ

Emacsトランクで試したすべてのモードで、elispを含むインデントメッセージが生成されました。セミコロンは多くの言語で行を終了するため、セミコロンを入力するまで、次の行は現在の行の一部であるかのようにジャンプします。
holocronweaver 14

@holocronweaverメッセージを黙らせた。それを指摘してくれてありがとう。
マラバルバ14

修正してくれてありがとう!セミコロンの問題の1つの解決策は、セミコロンが入力されたときにcモード言語でのみインデントすることです。
holocronweaver 14

3

私は既存のソリューションを知りませんが、あなたはpost-self-insert-hookこれを自分で達成するために使用できます:

(defun my-indent-next-sexp ()
  (interactive)
  (mark-sexp)
  (indent-region))

(add-hook 'post-self-insert-hook 'my-indent-next-sexp)

しかし、潜在的なパフォーマンスの問題を心配します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.