Prática recomendada do Evil Mode? [fechadas]

104

Tenho usado o Vim como meu editor principal por anos e tentei o Emacs várias vezes durante esse tempo. Então eu descobri o Mal e decidi que ele atende minha demanda por movimentos rápidos bem o suficiente para que eu possa finalmente passar para o Emacs.

Então, para todos os usuários do Mal, como você o integra com as funções normais do Emacs? Você encontrou algum conflito entre este modo e outros? Quais são as suas experiências / dicas que valem a pena compartilhar neste tópico?

Daniel Duan
fonte

Respostas:

71

Eu usei um vim altamente customizado, e agora uso um emacs ainda mais customizado. Acho que você encontrará todas as instâncias de mapeamento de teclado em meu arquivo de configuração de mapeamento de teclado https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

Tenha em mente que estou religando coisas que usuários reais do emacs considerariam heresia, então YMMV se você quiser aprender emacs "reais" (eu realmente não quero).

Uma coisa que eu recomendaria a qualquer ex-vimmer é isto

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

de modo que esc realmente encerra praticamente qualquer coisa (como prompts pendentes no minibuffer)

Matt Briggs
fonte
7
A definição de minibuffer-keyboard-quit pode ser encontrada aqui: github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell
1
@Adam, desculpe por isso>.> Eu tenho um monte de coisas instaladas, às vezes eu uso uma função que eu acho que está embutida, mas na verdade está vindo de outro lugar
Matt Briggs
3
Acho que isso não funciona para mim. Eu uso o Emacs 24.4 mais recente, alguém tem a mesma experiência?
Dzung Nguyen
1
O link está quebrado. Acredito que este seja o novo: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather
1
@SeanLeather Resposta atualizada para um link ativo.
Christopher Bottoms,
34

Como alguém que veio do emacs, experimentou o vim e percebeu que havia um grande número de coisas a ganhar, fiz muitos experimentos quando comecei a usar o mal. Embora o seguinte seja controverso, eu queria manter as chaves do emacs que são usadas mais universalmente no terminal, firefox, cocoa, etc ..., mas não queria perder as capacidades de edição do vim. Acabei decidindo religar as seguintes chaves em meu .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)))))

Infelizmente, eles se sobrepõem às operações do vim "mover uma tela para cima ou para baixo". No entanto, fiquei confortável usando o seguinte:

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

Além disso, se você estiver vindo do vim e quiser um caminho rápido do modo de inserção para o modo normal usando "jk" (ou qualquer outra combinação de 2 toques), a melhor maneira é copiar o texto de http://www.emacswiki.org/ emacs / download / key-chord.el e cole em seu ~ / .emacs.d / key-chord.el. Em seguida, adicione o seguinte ao seu .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)

Além disso, se você está vindo do vim e acha que copiar para a área de transferência no emacs não é bom, provavelmente você está certo. No entanto, você pode achar o seguinte útil após executar 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)

Obviamente, você terá que decidir por si mesmo se alguma dessas mudanças controversas vale a pena, mas talvez essas mudanças básicas o inspirem.

Para algumas outras implementações de função realmente interessantes, como excluir e colar, excluir sem copiar para a área de transferência, movimento 4x / 16x eficiente, uso de contagens para especificação de registro de colagem, configurações de guia que realmente funcionam para c / c ++ e mais, você pode verificar o .emacs completo, init.el, my-keymaps.el e my-functions.el versons no meu git em https://github.com/Russell91/emacs

RussellStewart
fonte
2
tudo isso é ótimo, eu adicionei alguns no wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince
Eu entendo sua vontade de reutilizar seus hábitos do emacs. Para trabalhar no Firefox, eu recomendo fortemente tentar o addon Vimperator, que traz muitas funcionalidades semelhantes ao vim para sua navegação. No entanto, ele está usando comandos de movimento do vim por padrão (como é o caso de lesscommand e outros).
Jan Vlcinsky
Da mesma forma que você, eu não gosto da ligação do mal no modo de inserção de estado, então eu apenas religo "i" no mapa do estado normal para 'estado do mal emacs.
user49117
Em vez de substituir o teclado de evil, eu o removo, então ele volta para a configuração de teclado do emacs normal, exemplo(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien
30

Eu também costumava ser um usuário Viper / Vimpulse, com uma grande quantidade de configurações. Então eu encontrei o modo Evil.

Quais são as suas experiências / dicas que valem a pena compartilhar neste tópico?

Esta é toda a minha configuração de modo maligno e funciona muito bem para mim:

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

Você encontrou algum conflito entre este modo e outros?

Não, em contraste com o Viper / Vimpulse que estava causando problemas em vários modos.

Kenny Meyer
fonte
Estou recebendo este erro: progn: O valor do símbolo como variável é nulo: estado Onde o estado está definido?
justingordon
Você pode tentarevil-emacs-state
Kenny Meyer
2
Você pode esclarecer onde você colocou isso?
justingordon,
1
Isso é fantástico, eu procurei exatamente isso. Muitos votos positivos!
jplindstrom
1
Dê uma olhada neste github.com/edwtjo/evil-org-mode
avendael
17

Comecei a usar o Evil há um mês; antes disso, tentei usar o viper / vimpulse sem muito sucesso. Para ser honesto, o vimpulse é muito bom, mas usá-lo com vários modos era um pouco problemático (por exemplo, modo de compilação onde o vimpulse sempre ficava louco) deixando o emacs em algum modo entre o vi-emacs-alguma coisa.

Quando mudei para o Mal, finalmente comecei a explorar todo o poder do Emacs e, acredite, não me arrependo. Evil funciona bem em todos os modos que usei (principalmente edição, compilação, scratch e eshell) e até mesmo ler info / man / help está funcionando sem problemas.

Exceto que, eu só achei a troca de buffer estranha como costumava fazer: b <0-9> em vez disso: b-TAB-then-complete-name ou: bn. Observe, entretanto, que os desenvolvedores do Mal tentam (em alguns casos) reduzir as funcionalidades duplicadas, então:! (para o comando exec shell), você deve usar o M- !.

Se você achar que deseja adicionar / redefinir alguns comandos ex personalizados, apenas abra evil-maps.el e edite-o (tente isso no vim!).

Evil ainda é um projeto jovem, mas promissor e estou esperando o dia em que substituirá o Viper na distribuição oficial do Emacs.

dennis
fonte
4
Isso significa que não é possível adicionar / redefinir comandos no vim?
John Tyree
1
@JohnTyree Os comandos definidos pelo usuário devem começar com uma letra maiúscula no Vim, enquanto todos os comandos integrados começam com uma letra minúscula.
Austin Taylor
10

Eu gosto de salvar o buffer quando eu sair do insert-mode: (editado: não peça para salvar quando não houver nenhum arquivo associado para este buffer, como em um scratch ou um buffer magit)

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

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

para mais possibilidades: veja http://wikemacs.org/index.php/Evil

Comentários bem-vindos para melhorias!

Ehvince
fonte
Obrigado. BTW, seu link está quebrado.
Amos
Obrigado também. Wikemacs vai voltar. O site está em manutenção, espero que não por muito tempo novamente.
Ehvince
9
  1. Eu uso o líder do mal e uso ", xm" para substituir "Mx", então raramente pressiono a tecla Alt. Há também general.el que oferece suporte a várias chaves de líder.

  2. evil-matchit , pressione "%" para pular entre o par de tags.

  3. comentarista nerd do mal , pressione "9, ci" para comentar / descomentar 9 linhas

  4. evite usar a tecla ESC, você pode pressionar "kj" ao invés.

  5. Tenha fé no software livre! Nada é impossível com o Mal que combina o poder do Vim e do Emacs. Por exemplo, muitas pessoas assumem que as combinações de teclas Evil conflitam com os plug-ins existentes do Emacs sem uma re-vinculação pesada. Isso está errado na verdade

Chen Bin
fonte
0

Vindo do lado do emacs, prefiro muito mais o M-. para ir para definição, mas a função executada M-.difere entre os modos. Eu poderia sobrescrevê-lo da maneira regular com (define-key evil-normal-state-map (kbd "M-.") 'foo)where fooverifica o modo principal atual e executa a função apropriada, mas parece que exigiria muita codificação. Uma solução mais geral é esta:

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

Fora isso, gosto dos plug - ins evil-surround (embora ache que smartparens é uma solução mais completa) e evil-leader .

Eu costumava usar o acorde para mapear jk para ESC como aprendi a fazer no vim, mas ele insistia em tratar kj como o mesmo que jk, então, em vez disso, estou usando o seguinte:

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

eu uso (setq evil-move-cursor-back nil) que não é muito vimmy (embora aparentemente você possa fazer seu vimrc fazer isso também), mas nunca me acostumei com o cursor voltando depois de sair do insert.

Dica prática: use evil-local-mode-hookpara coisas como o modo mal-surround de carregamento lento, não ajudará a esclarecer evil-mode-hook. Portanto, se você instalar o evil e evil-surround com o pacote de instalação, você pode fazer com que ele comece ao M-x evil-modefazer

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

(Claro, se você sempre executa o evil-mode e sempre tem o evil instalado, não há necessidade desse material de carregamento automático, mas eu prefiro que meu .emacs seja geral o suficiente para que eu possa usá-lo em máquinas com emacsen antigo ou sem nenhum pacotes elpa instalados.)

desferir
fonte