悪モードのベストプラクティス?[閉まっている]


104

私は何年もの間Vimを私の主要なエディターとして使用しており、その間にEmacsを何度か試しました。それから私はを発見し、それが私が最終的にEmacsに移ることができるように十分に迅速な動きへの私の要求を満たすと決めました。

それで、あなたのすべての邪悪なユーザーにとって、それを通常のEmacs機能とどのように統合しますか?このモードと他のモードとの間に競合が発生しましたか?このトピックについて共有する価値のある経験/ヒントは何ですか?

回答:


71

私は高度にカスタマイズされたvimを使用し、さらにカスタマイズされたemacsを使用しています。キーマッピングのすべてのインスタンスは、キーマッピング構成ファイルhttps://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.elにあると思います

覚えておいてください、私は本当のemacsユーザーが異端だと考えるものを再バインドしているので、「本当の」emacsを学びたいのであればYMMVです(私は本当にしません)。

私がどんな元ビマーにもお勧めしたいのはこれです

;;; esc quits
(defun minibuffer-keyboard-quit ()
  "Abort recursive edit.
In Delete Selection mode, if the mark is active, just deactivate it;
then it takes a second \\[keyboard-quit] to abort the minibuffer."
  (interactive)
  (if (and delete-selection-mode transient-mark-mode mark-active)
      (setq deactivate-mark  t)
    (when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
    (abort-recursive-edit)))
(define-key evil-normal-state-map [escape] 'keyboard-quit)
(define-key evil-visual-state-map [escape] 'keyboard-quit)
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)

escが実際にほとんどすべてを終了するようにする(ミニバッファーの保留中のプロンプトなど)


7
minibuffer-keyboard-quitの定義は、ここにあります:github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell

1
@Adam申し訳ありません>。>多くのものがインストールされています。組み込みだと思われる関数を使用することがありますが、実際には別の場所から来ています
Matt Briggs

3
これではうまくいかないことがわかりました。私は最新のEmacs 24.4を使用していますが、誰かが同じことを経験していますか?
Dzung Nguyen 2014

1
リンクが壊れています。これは新しいものだと思います:github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather

1
@SeanLeather有効なリンクに対する更新された回答。
クリストファーボトムズ2016

34

emacsからやって来てvimを試してみて、得られることがたくさんあることに気付いた私は、最初にevilを使い始めたときに多くの実験を行いました。以下は議論の余地がありますが、ターミナル、Firefox、ココアなどでより一般的に使用されるemacsキーを保持したかったのですが、vim編集機能を失いたくありませんでした。.emacsで次のキーを再バインドすることにしました。

(define-key evil-normal-state-map "\C-e" 'evil-end-of-line)
(define-key evil-insert-state-map "\C-e" 'end-of-line)
(define-key evil-visual-state-map "\C-e" 'evil-end-of-line)
(define-key evil-motion-state-map "\C-e" 'evil-end-of-line)
(define-key evil-normal-state-map "\C-f" 'evil-forward-char)
(define-key evil-insert-state-map "\C-f" 'evil-forward-char)
(define-key evil-insert-state-map "\C-f" 'evil-forward-char)
(define-key evil-normal-state-map "\C-b" 'evil-backward-char)
(define-key evil-insert-state-map "\C-b" 'evil-backward-char)
(define-key evil-visual-state-map "\C-b" 'evil-backward-char)
(define-key evil-normal-state-map "\C-d" 'evil-delete-char)
(define-key evil-insert-state-map "\C-d" 'evil-delete-char)
(define-key evil-visual-state-map "\C-d" 'evil-delete-char)
(define-key evil-normal-state-map "\C-n" 'evil-next-line)
(define-key evil-insert-state-map "\C-n" 'evil-next-line)
(define-key evil-visual-state-map "\C-n" 'evil-next-line)
(define-key evil-normal-state-map "\C-p" 'evil-previous-line)
(define-key evil-insert-state-map "\C-p" 'evil-previous-line)
(define-key evil-visual-state-map "\C-p" 'evil-previous-line)
(define-key evil-normal-state-map "\C-w" 'evil-delete)
(define-key evil-insert-state-map "\C-w" 'evil-delete)
(define-key evil-visual-state-map "\C-w" 'evil-delete)
(define-key evil-normal-state-map "\C-y" 'yank)
(define-key evil-insert-state-map "\C-y" 'yank)
(define-key evil-visual-state-map "\C-y" 'yank)
(define-key evil-normal-state-map "\C-k" 'kill-line)
(define-key evil-insert-state-map "\C-k" 'kill-line)
(define-key evil-visual-state-map "\C-k" 'kill-line)
(define-key evil-normal-state-map "Q" 'call-last-kbd-macro)
(define-key evil-visual-state-map "Q" 'call-last-kbd-macro)
(define-key evil-normal-state-map (kbd "TAB") 'evil-undefine)

(defun evil-undefine ()
 (interactive)
 (let (evil-mode-map-alist)
   (call-interactively (key-binding (this-command-keys)))))

残念ながら、これらはvimの「1画面上または下に移動」操作と重複しています。ただし、代わりに以下を使用することに慣れました。

(define-key evil-normal-state-map (kbd "DEL") (lambda ()
                    (interactive)
                    (previous-line 10)
                    (evil-scroll-line-up 10)
                    ))

(define-key evil-normal-state-map (kbd "=") (lambda ()
                      (interactive)
                      (next-line 10)
                      (evil-scroll-line-down 10)
                      ))

また、vimから来て、「jk」(または他の2ストロークの組み合わせ)を使用して挿入から通常モードへのクイックパスが必要な場合は、http: //www.emacswiki.org/からテキストをコピーするのが最善の方法です。 emacs / download / key-chord.elを〜/ .emacs.d / key-chord.elに貼り付けます。次に、以下を.emacsに追加します。

;load a file named key-chord.el from some directory in the load-path (e.g. "~/.emacs.d")
(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "jk" 'evil-normal-state)

また、vimから来ていて、emacsでのクリップボードへのコピーが良くないと思うなら、おそらく正しいでしょう。ただし、sudo apt-get install xselを実行すると、次の情報が役立つ場合があります。

(defun copy-to-clipboard ()
  (interactive)
  (if (display-graphic-p)
      (progn
        (message "Yanked region to x-clipboard!")
        (call-interactively 'clipboard-kill-ring-save)
        )
    (if (region-active-p)
        (progn
          (shell-command-on-region (region-beginning) (region-end) "xsel -i -b")
          (message "Yanked region to clipboard!")
          (deactivate-mark))
      (message "No region active; can't yank to clipboard!")))
  )

(evil-define-command paste-from-clipboard()
  (if (display-graphic-p)
      (progn
        (clipboard-yank)
        (message "graphics active")
        )
    (insert (shell-command-to-string "xsel -o -b"))
    )
  )

(global-set-key [f8] 'copy-to-clipboard)
(global-set-key [f9] 'paste-from-clipboard)

明らかに、これらの議論の余地のある変更のどれかが価値があるかどうかを自分で決定する必要がありますが、おそらくこれらの基本的な変更があなたに刺激を与えるでしょう。

削除と貼り付け、クリップボードへのコピーなしの削除、効率的な4x / 16xの移動、貼り付けレジスター指定のカウントの使用、実際にc / c ++で機能するタブ設定など、他のいくつかの本当にクールな関数実装については、確認できますhttps://github.com/Russell91/emacsにある私のgitの完全な.emacs、init.el、my-keymaps.el、およびmy-functions.elバージョンを出力します。


2
これはすべて素晴らしいです。wikemacsに
Ehvince

emacsからあなたの習慣を再利用するあなたの意志を理解しました。Firefoxでの作業には、Vimperatorアドオンを試してみることを強くお勧めします。これは、ブラウジングに多くのvimのような機能をもたらします。ただし、デフォルトではvim移動コマンドを使用しています(lessコマンドなどの場合と同様)。
Jan Vlcinsky 2013年

あなたと同じように、私はinsert-state-modeでのevilバインディングが好きではないので、normal-state-mapの "i"を 'evil-emacs-stateに再バインドします。
user49117

のキーボードを上書きするのではなく、evil削除して、通常のemacsのキーボード設定にフォールバックします。例(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien

30

私はまた、Viper / Vimpulseのユーザーであり、膨大な設定を行っていました。それから私は悪モードを見つけました。

このトピックについて共有する価値のある経験/ヒントは何ですか?

これは私の悪モード設定全体であり、私にとってはうまくいきます:

(require 'evil)
(evil-mode 1)

;; Remap org-mode meta keys for convenience
(mapcar (lambda (state)
    (evil-declare-key state org-mode-map
      (kbd "M-l") 'org-metaright
      (kbd "M-h") 'org-metaleft
      (kbd "M-k") 'org-metaup
      (kbd "M-j") 'org-metadown
      (kbd "M-L") 'org-shiftmetaright
      (kbd "M-H") 'org-shiftmetaleft
      (kbd "M-K") 'org-shiftmetaup
      (kbd "M-J") 'org-shiftmetadown))
  '(normal insert))

このモードと他のモードとの間に競合が発生しましたか?

いいえ、いくつかのモードで問題を引き起こしていたViper / Vimpulseとは対照的です。


このエラーが発生します:progn:変数としてのシンボルの値はvoid:state状態はどこで定義されていますか?
justingordon 2012年

あなたが試すことができますevil-emacs-state
ケニーマイヤー

2
それをどこに置くか明確にできますか?
justingordon 2012年

1
これは素晴らしいです、私はまさにこれを探しました。豊富な賛成投票!
jplindstrom 2012


17

1か月前にEvilを使い始めました。それ以前は、viper / vimpulseを使用しようとしましたが、ほとんど成功しませんでした。正直に言うと、vimpulseは非常に便利ですが、さまざまなモードでvimpulseを使用するのは少し面倒でした(たとえば、vimpulseが常にクレイジーになるコンパイルモード)。

Evilに切り替えたとき、ようやくEmacsの全機能を探索し始めました。そして、私を後悔していませんでした。Evilは、私が使用したすべてのモード(主に編集、コンパイル、スクラッチ、eshell)でうまく機能し、info / man / helpを読んでも問題なく機能しています。

それ以外は、:b-TAB-then-complete-nameまたは:bnの代わりに:b <0-9>を使用していたため、バッファスイッチングが奇妙であることがわかりました。ただし、悪の開発者は重複した機能を(場合によっては)削減しようとするため、代わりに:!(シェルコマンドを実行するには)、ネイティブM-!を使用する必要があります。

カスタムexコマンドを追加/再定義したい場合は、evil-maps.elを開いて編集します(vimで試してください)。

Evilはまだ若くて有望なプロジェクトであり、公式のEmacsディストリビューションでviperが置き換えられる日を待っています。


4
これはvimでコマンドを追加/再定義することが不可能であることを意味するはずですか?
John Tyree 2013年

1
@JohnTyreeユーザー定義のコマンドは、Vimでは大文字で始める必要がありますが、組み込みコマンドはすべて小文字で始まります。
オースティンテイラー

10

insert-mode:を終了するときにバッファーを保存したい(編集済み:このバッファーに関連付けられているファイルがない場合、スクラッチまたはmagitバッファー内などに保存を要求しない)

(defun my-save ()
  (if (buffer-file-name)
    (evil-save))
)

   (add-hook 'evil-insert-state-exit-hook 'my-save)

その他の可能性については、http://wikemacs.org/index.php/Evilを参照してください

コメントは改善を歓迎します!


ありがとう。ところで、あなたのリンクは壊れています。
Amos

どうもありがとう。Wikemacsが戻ってきます。サイトはメンテナンス中です。うまくいけば、再び長くなりません。
Ehvince 2016年

9
  1. 私が使用して悪のリーダー、 『MX』を交換するので、私はめったにプレスAltキーを使用し、「XM」を。複数のリーダーキーをサポートするgeneral.elもあります。

  2. evil-matchit、「%」を押してタグのペア間をジャンプします。

  3. evil-nerd-commenter、「9、ci」を押して9行をコメント/コメント解除

  4. ESCキーの使用を避け、代わりに「kj」を押します。

  5. フリーソフトウェアを信頼してください!VimとEmacsの力を組み合わせたEvilでは不可能はありません。たとえば、多くの人は、悪質なキーバインディングが既存のプラグインEmacsと頻繁に再バインドせずに競合すると想定しています。それは実際には間違っています


0

emacs側から来て、私はM-を非常に好みます。定義通りですが、実行される機能M-.はモードによって異なります。(define-key evil-normal-state-map (kbd "M-.") 'foo)where fooが現在のメジャーモードをチェックして適切な関数を実行するという通常の方法でオーバーライドすることもできますが、ハードコーディングが大量に必要になるようです。より一般的な解決策はこれです:

(defun evil-emacs-key-binding (key)
  (evil-execute-in-emacs-state)
  (key-binding key))

(defmacro evil-revert-key-binding (state-map key)
  `(define-key ,state-map ,key (lambda ()
                                 (interactive)
                                 (call-interactively
                                  (evil-emacs-key-binding ,key)))))

(eval-after-load "evil-autoloads"
  '(add-hook 'evil-after-load-hook
        (lambda ()
          (evil-revert-key-binding evil-normal-state-map (kbd "M-."))
          ;; and so on
        )))

それ以外は、evil-surroundプラグイン(smartparensがより完全なソリューションだと思いますが)とevil-leaderが好きですです。

vimで行う方法を学んだように、キーコードを使用してjkをESCにマップしていましたが、kjをjkと同じように扱うことを主張していたため、代わりに以下を使用しています。

(defun evil-escape-if-next-char (trigger)
  "Watches the next letter. If `trigger', then switch to normal mode,
otherwise keep the previously inserted key and forward unpressed
key to `unread-command-events'."
  (self-insert-command 1)
  (let ((next-key (read-event)))
    (if (eq trigger next-key)
        (progn
          (delete-char -1)
          (evil-normal-state))
      (setq unread-command-events (cons next-key unread-command-events)))))

(defun evil-escape-if-next-char-is-k (arg)
  (interactive "p")
  (if (= arg 1)
      (evil-escape-if-next-char ?k)
    (self-insert-command arg)))

(eval-after-load "evil-autoloads"
  '(add-hook 'evil-after-load-hook
             (lambda ()
               ;; … other stuff …
               (define-key evil-insert-state-map (kbd "j") 'evil-escape-if-next-char-is-k))))

私が使う (setq evil-move-cursor-back nil)はそれほどvimmyではないものいます(ただし、vimrcにそれを実行させることもできますが)、挿入の終了後にカーソルが戻ることに慣れていません。

実用的なヒント:evil-local-mode-hookevil-surround-modeの遅延読み込みのようなものに使用しますevil-mode-hook。それをプレーンに配置しても役に立ちません。あなたはパッケージをインストールして悪と悪サラウンドをインストールするのであれば、あなたはあなたが行うときに起動することができますM-x evil-mode実行して

(eval-after-load "evil-surround-autoloads"
  '(add-hook 'evil-local-mode-hook #'evil-surround-mode))

(もちろん、常にevil-modeを実行し、常にevilをインストールしている場合は、autoloadの要素は必要ありませんが、.emacsは、古いemacsenがインストールされているマシンまたはインストールされていないマシンで使用できるように十分に一般的であることを好みますelpaパッケージがインストールされています。)

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