Best practice per la modalità male? [chiuso]


104

Uso Vim come mio editor principale da anni e ho provato Emacs diverse volte durante quel periodo. Poi ho scoperto Evil e ho deciso che soddisfa la mia richiesta di movimenti rapidi abbastanza bene da poter finalmente passare a Emacs.

Quindi, a tutti voi utenti Evil, come lo integrate con le normali funzioni di Emacs? Hai riscontrato conflitti tra questa modalità e altre? Quali sono le tue esperienze / suggerimenti da condividere su questo argomento?

Risposte:


71

Ho usato un vim altamente personalizzato, e ora uso un emacs ancora più personalizzato. Penso che troverai ogni istanza di keymapping nel mio file di configurazione del keymapping https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

Tieni a mente che sto riassociando cose che i veri utenti di emacs considererebbero eresia, quindi YMMV se vuoi imparare il "vero" emacs (davvero non lo faccio).

Una cosa che consiglierei a qualsiasi ex vimmer è questa

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

in modo che esc effettivamente chiuda praticamente qualsiasi cosa (come i prompt in sospeso nel minibuffer)


7
La definizione di minibuffer-keyboard-quit può essere trovata qui: github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell

1
@Adam mi dispiace per questo>.> Ho un sacco di cose installate, a volte utilizzo una funzione che penso sia incorporata, ma in realtà proviene da qualche altra parte
Matt Briggs

3
Trovo che questo non funzioni per me. Uso l'ultima versione di Emacs 24.4, qualcuno ha la stessa esperienza?
Dzung Nguyen

1
Il collegamento è interrotto. Credo che questo sia il nuovo: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather,

1
@SeanLeather Risposta aggiornata a un collegamento funzionante.
Christopher Bottoms,

34

Come qualcuno che proveniva da emacs, ha provato vim e si è reso conto che c'era un numero enorme di cose da guadagnare, ho fatto molti esperimenti quando ho iniziato a usare il male. Mentre i seguenti sono controversi, volevo mantenere le chiavi emacs che sono usate più universalmente in terminale, firefox, cocoa, ecc ..., ma non volevo perdere le capacità di modifica di vim. Ho deciso di riassociare le seguenti chiavi nel mio .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)))))

Sfortunatamente, queste si sovrappongono alle operazioni di vim "sposta uno schermo in alto o in basso". Tuttavia, mi sono sentito a mio agio nell'usare quanto segue:

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

Inoltre, se vieni da vim e desideri un percorso rapido dall'inserimento alla modalità normale usando "jk" (o qualsiasi altra combinazione a 2 tratti), il modo migliore è copiare il testo da http://www.emacswiki.org/ emacs / download / key-chord.el e incollalo nel tuo ~ / .emacs.d / key-chord.el. Quindi aggiungi quanto segue al tuo .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)

Inoltre, se vieni da vim e pensi che la copia negli appunti in emacs non sia buona, probabilmente hai ragione. Tuttavia, potresti trovare utile quanto segue dopo aver eseguito 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)

Ovviamente, dovrai decidere da solo se valga la pena qualcuno di questi cambiamenti controversi, ma forse questi cambiamenti di base ti ispireranno.

Per alcune altre implementazioni di funzioni davvero interessanti, come elimina e incolla, elimina senza copiare negli appunti, efficiente movimento 4x / 16x, uso dei conteggi per la specifica del registro di incolla, impostazioni di tabulazione che funzionano effettivamente per c / c ++ e altro, puoi controllare le versioni complete .emacs, init.el, my-keymaps.el e my-functions.el sul mio git su https://github.com/Russell91/emacs


2
tutto questo è fantastico, ne ho aggiunti alcuni in wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince

Capisco la tua volontà di riutilizzare le tue abitudini da emacs. Per lavorare in Firefox, consiglio vivamente di provare l'addon di Vimperator, che offre molte funzionalità simili a vim alla tua navigazione. Tuttavia, utilizza i comandi di movimento di vim per impostazione predefinita (come nel caso di lesscommand e altri).
Jan Vlcinsky

Come te, non mi piace il binding malvagio in modalità insert-state, quindi mi limito a riassociare "i" in normal-state-map a 'evil-emacs-state.
user49117

Invece di sovrascrivere la tastiera di evil, la rimuovo, quindi torna all'impostazione della tastiera del normale emacs, esempio(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien

30

Ero anche un utente di Viper / Vimpulse, con un'enorme quantità di configurazione. Poi ho trovato la modalità Evil.

Quali sono le tue esperienze / suggerimenti da condividere su questo argomento?

Questa è tutta la mia configurazione in modalità malvagia e funziona alla grande per me:

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

Hai riscontrato conflitti tra questa modalità e altre?

No, a differenza di Viper / Vimpulse che causava problemi in diverse modalità.


Ricevo questo errore: progn: il valore del simbolo come variabile è vuoto: state Dove è definito lo stato?
justingordon

Puoi provareevil-emacs-state
Kenny Meyer

2
Puoi chiarire dove lo metti?
justingordon

1
È fantastico, ho cercato esattamente questo. Voti in abbondanza!
jplindstrom

1
Dai

17

Ho iniziato a usare Evil un mese fa; prima, ho provato a usare viper / vimpulse senza molto successo. Ad essere onesti, vimpulse è abbastanza carino, ma usarlo con varie modalità è stato un po 'problematico (es. Modalità compilation in cui vimpulse impazziva) lasciando emacs in qualche modalità tra vi-emacs-something.

Quando sono passato a Evil, ho finalmente iniziato a esplorare il pieno potere di Emacs e, credimi, non me ne sono pentito. Evil funziona bene in tutte le modalità che ho usato (principalmente editing, compilation, scratch ed eshell) e anche la lettura di info / man / help funziona senza problemi.

Tranne quello, ho trovato solo il buffering strano come facevo: b <0-9> invece: b-TAB-then-complete-name o: bn. Si noti tuttavia che gli sviluppatori di Evil cercano (in alcuni casi) di ridurre le funzionalità duplicate, quindi invece:! (per eseguire il comando di shell), dovresti usare M- !.

Se senti la necessità di aggiungere / ridefinire alcuni comandi ex personalizzati, apri il file evil-maps.el e modificalo (provalo in vim!).

Evil è ancora un progetto giovane ma promettente e sto aspettando il giorno in cui sostituirà Viper nella distribuzione ufficiale di Emacs.


4
Questo dovrebbe implicare che non è possibile aggiungere / ridefinire comandi in vim?
John Tyree

1
@JohnTyree I comandi definiti dall'utente devono iniziare con una lettera maiuscola in Vim, mentre tutti i comandi incorporati iniziano con una lettera minuscola.
Austin Taylor,

10

Mi piace salvare il buffer quando esco da insert-mode: (modificato: non chiedere di salvare quando non ci sono file associati per questo buffer, come quando si è in uno scratch o in un buffer magit)

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

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

per ulteriori possibilità: vedere http://wikemacs.org/index.php/Evil

Commenti benvenuti per miglioramenti!


Grazie. BTW, il tuo collegamento è interrotto.
Amos

Grazie anche Wikemacs tornerà. Il sito è in manutenzione, si spera non ancora per troppo tempo.
Ehvince

9
  1. Uso evil-leader e uso ", xm" per sostituire "Mx", quindi premo raramente il tasto Alt. C'è anche general.el che supporta più chiavi leader.

  2. evil-matchit , premi "%" per passare da una coppia di tag.

  3. evil-nerd-commenter , premere "9, ci" per commentare / decommentare 9 righe

  4. evita di usare il tasto ESC, puoi invece premere "kj" .

  5. Abbi fiducia nel software libero! Niente è impossibile con Evil che unisce il potere di Vim ed Emacs. Ad esempio, molte persone presumono che le scorciatoie da tastiera Evil siano in conflitto con i plugin esistenti Emacs senza un pesante re-binding. In realtà è sbagliato


0

Venendo dal lato emacs, preferisco di gran lunga M-. essere go-to-definition, ma la funzione che viene eseguita M-.differisce tra le modalità. Potrei sovrascriverlo in modo normale con (define-key evil-normal-state-map (kbd "M-.") 'foo)dove foocontrolla la modalità principale corrente ed esegue la funzione appropriata, ma sembra che richiederebbe molto hardcoding. Una soluzione più generale è questa:

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

Oltre a questo, mi piacciono i plugin evil-surround (anche se ritengo che smartparens sia una soluzione più completa) e evil-leader .

Usavo il key-chord per mappare jk su ESC come ho imparato a fare in vim, ma insisteva nel trattare kj come lo stesso di jk, quindi invece sto usando quanto segue:

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

Io uso (setq evil-move-cursor-back nil) che non è molto vimmy (anche se apparentemente puoi fare in modo che anche il tuo vimrc lo faccia), semplicemente non mi sono mai abituato al cursore che torna indietro dopo essere uscito da insert.

Suggerimento pratico: usalo evil-local-mode-hookper cose come il caricamento lento della modalità surround malvagia, non aiuterà a metterla in chiaro evil-mode-hook. Quindi se installi evil e evil-surround con l'installazione del pacchetto, puoi farlo partire quando lo fai M-x evil-modefacendo

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

(Ovviamente, se esegui sempre la modalità malefica e hai sempre installato il male, non c'è bisogno di quella roba di caricamento automatico, ma preferisco che il mio .emac sia abbastanza generico da poterlo usare su macchine con vecchio emacsen o senza averne pacchetti elpa installati.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.