Evil: kombinace editačních příkazů Vimu a síly Emacsu

28. 8. 2018
Doba čtení: 26 minut

Sdílet

V článku se seznámíme s modulem Evil určeným pro editor Emacs. Díky tomuto modulu je možné v Emacsu používat editační příkazy a režimy (stavy) neméně slavného editoru Vim, takže uživatelé mohou využít výhody obou světů.

Obsah

1. Evil: kombinace editačních příkazů Vimu a síly Emacsu

2. Proč by měl být Emacs zajímavý i pro Vimaře?

3. Emacs není jediný editor s emulací Vimu

4. Instalace balíčku Evil do Emacsu

5. Povolení režimu Evil, přepínání režimů Emacs/Vim

6. Základní editační příkazy

7. Práce s registry (registers)

8. Použití značek (marks)

9. Uživatelská makra

10. Další přizpůsobení Emacsu pro skalní Vimaře

11. Modifikace funkce klávesy Y

12. Balíček evil-numbers

13. Instalace a konfigurace balíčku evil-numbers

14. Ostatní užitečná nastavení

15. Mapování kláves ve Vimu

16. Mapování kláves v Emacsu

17. Evil a Elisp

18. Využití funkcí evil-*

19. Obsah navazujícího článku – projekt Spacemacs

20. Odkazy na Internetu

1. Evil: kombinace editačních příkazů Vimu a síly Emacsu

V dnešním článku se seznámíme s pluginem určeným pro slavný textový editor Emacs. Tento plugin se jmenuje Evil a umožňuje ovládat Emacs pomocí klávesových zkratek emulujících (a to velmi důkladně) další slavný textový editor Vim. Díky tomuto pluginu je tak umožněna synergie schopností Vimu s univerzálností Emacsu. Se samotným Emacsem jsme se na Rootu již setkali, a to dokonce několikrát. Především vyšly dva seriály [1] [2] věnované použití Emacsu, poměrně podrobně jsme si popsali i historii vzniku tohoto textového editoru a taktéž jsme si ukázali schopnosti Emacsu při ladění nativních aplikací (samotné ladění je prováděno GNU Debuggerem, Emacs zde slouží především jako inteligentní front end). Prozatím poslední článek se věnoval režimu interaktivního porovnávání souborů.

Obrázek 1: Spuštění textového editoru Emacs se zobrazením hypertextového souboru s nápovědou.

I přesto, že v současnosti existuje poměrně velké množství programátorských textových editorů postavených na moderních technologiích (jmenujme například Atom, Sublime Text 2, Light Table či projekt Kakoune), stále mnoho uživatelů – ať již se jedná o programátory, administrátory, testery atd. – používá dnes již klasické editory Vim a Emacs. Ostatně není se čemu divit, protože jak ve Vimu, tak i v Emacsu lze s texty pracovat velmi efektivně a navíc je možné si mnohé úlohy plně zautomatizovat, například prostým opakováním příkazu, použitím uživatelských maker, mapováním kláves či dokonce vytvořením složitějších skriptů/pluginů.

Obrázek 2: GNU Emacs přepnutý do takzvaného ediff režimu.

Důležité upozornění: v současnosti se používá několik typů textových editorů, v jejichž názvu objevíme slovo Emacs. Jedná se například o MicroEMACS a jeho varianty, z nichž jedna je používána a udržována Linusem Torvaldsem. Dnes se ovšem zaměříme na popis možností GNU Emacsu, i když popisovaný režim by měl být funkční i v XEmacsu (pokud ho ještě někdo používá namísto GNU Emacsu). Všechny popisované funkce je samozřejmě možné použít jak tehdy, když je GNU Emacs spuštěn s plnohodnotným grafickým uživatelským rozhraním, tak i v případě, že používáte GNU Emacs spuštěný v terminálu, například s využitím balíčku emacs-nox (nox = no X).

Obrázek 3: Pokud vám grafické uživatelské rozhraní u textových editorů z nějakého důvodu nevyhovuje a dáváte přednost použití terminálu, je možné Emacs startovat s volbou -nw nebo –no-window-system. Pokud se Emacs spouští z textové konzole, samozřejmě se přepne do čistě textového rozhraní.

2. Proč by měl být Emacs zajímavý i pro Vimaře?

Pokud tento článek čte dlouholetý příznivce Vimu, asi si klade otázku, zda mu použití Emacsu skutečně může přinést nějaké výhody a jestli má smysl si Emacs + Evil vyzkoušet. Samozřejmě jsou požadavky uživatelů různé, ale vyzkoušení Evilu může být přínosné, zejména ve chvíli, kdy se použije ještě nějaký další plugin měnící Emacs v integrované vývojové prostředí (navíc je vždy vhodné znát možnosti „nepřítele“ :-). Vim je samozřejmě taktéž rozšiřitelný díky existenci Vim Scriptu, ovšem například integrace dynamicky typovaných jazyků je v Emacsu (podle mých zkušeností) lepší. Díky tomu, že je tento programátorský editor relativně snadno rozšiřitelný s využitím skriptů a modulů naprogramovaných v jazyce Lisp, přesněji řečeno v jeho dialektu nazvaném Emacs Lisp (též Elisp), existuje v současnosti poměrně velké množství propracovaných modulů, které z Emacsu vytváří sofistikované integrované vývojové prostředí (IDE), jež se navíc v případě potřeby dokáže přizpůsobit mnoha programovacím jazykům (překladačům, ale i interpretrům).

Jen pro upřesnění: všech cca 1400 článků, které jsem pro Root napsal, bylo vytvořeno ve Vimu. První články ještě ve starodávném Vimu 5, poměrně dlouho jsem používal Vim 6 a dnes používám Vim 7 (starší notebook) a samozřejmě Vim 8.

Obrázek 4: Porovnání tří variant zdrojového kódu v ediff režimu.

Textový editor Emacs je možné v závislosti na tom, jaký typ souboru je právě otevřený, přepínat mezi různými režimy, přičemž v každém režimu mohou být použity jiné klávesové zkratky, zobrazena odlišná okna (nejenom klasická okna s editovaným textem) apod. Příkladem může být režim ladění programů s využitím GNU Debuggeru. O propojení debuggeru s Emacsem se stará knihovna GUD neboli Grand Unified Debugger, s níž se můžete seznámit v článku Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim. Zapomenout nesmíme ani na slavný Org-mode nabízející možnosti plánovače úloh, tvorbu strukturovaných dokumentů, přípravu programů schůzek, práci s tabulkami (v čistě textových dokumentech). Ostatně znám několik lidí (neprogramátorů), kteří přešli na Emacs právě kvůli existenci Org-mode.

Obrázek 5: Podpora ladění přímo z prostředí Emacsu – inicializace knihovny GUD a připojení Emacsu ke GNU Debuggeru.

3. Emacs není jediný editor s emulací Vimu

Ve skutečnosti není textový editor Emacs jedinou aplikací, pro kterou byl vytvořen plugin emulující možnosti Vimu. Například pro textový editor Atom existuje zásuvný modul pojmenovaný atom-vim-mode-plus. Na stránkách serveru mojefedora.cz [1] [2] jste se mohli se seznámit s projektem Vrapper přidávajícím klávesové zkratky Vimu do integrovaného vývojového prostředí Eclipse a emulace Vimu je dokonce dostupná o pro Libre Office díky pluginu vibreoffice (ten ovšem podporuje jen ty nejzákladnější příkazy, ze všech zmíněných pluginů je v nejhorším stavu).

Obrázek 6: Integrované vývojové prostředí Eclipse s nainstalovaným pluginem Vrapper.

Poznámka: mimochodem, výše zmíněný editor Kakoune je modální, takže Vi a jeho deriváty (především tedy Vim) nejsou jedinými v současnosti používanými modálními editory.

4. Instalace balíčku Evil do Emacsu

Existuje několik způsobů instalace pluginu Evil (příslušný balíček se jmenuje jednouše evil). Nejjednodušší je instalace ve chvíli, kdy máte v Emacsu povolen repositář balíčků MELPA (ten obsahuje přibližně 3900 balíčků!). Po zadání příkazu:

M-x list-packages

je možné zjistit, jestli je MELPA povolena a zda je tedy balíček evil přímo k dispozici:

Poznámka: uživatelé Emacsu používají označení M-x pro klávesovou zkratku Alt+X, my dnes tento způsob zápisu taktéž budeme dodržovat.

Obrázek 7: V případě, že repositář MELPA není povolen, budou dostupné pouze balíčky z výchozího repositáře ELPA (Emacs Lisp Package Archive).

Pokud balíček evil nebyl nalezen, je nutné MELPu povolit, například těmito řádky přidanými do souboru .emacs umístěného v domovském adresáři:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

Po opětovném načtení editoru zkuste znovu zadat příkaz:

M-x list-packages

Tentokrát by se měl objevit mj. i balíček nazvaný evil (pozor na to, že prvotní načtení všech 3900 balíčků může chvíli trvat):

Obrázek 8: V případě, že je repositář MELPA povolen, měl by se v seznamu balíčků objevit i plugin evil.

Plugin evil nainstalujeme běžným způsobem:

Obrázek 9: Výběr pluginu evil pro instalaci.

5. Povolení režimu Evil, přepínání režimů Emacs/Vim

V případě, že budete chtít, aby Emacs implicitně pracovat v režimu emulace editoru Vim, přidejte si do souboru .emacs umístěného v domovském adresáři následující dvojici řádků:

(require 'evil)
(evil-mode 1)

Přepínání mezi originálním ovládáním Emacsu a emulací Vimu se dá provést i dalšími způsoby. Například je možné použít klávesovou zkratku C-z (neboli Ctrl+Z), což ovšem nemusí fungovat v textové konzoli. Taktéž je možné zavolat příkaz evil-mode, a to následujícím způsobem:

M-x evil-mode

Tento příkaz přepíná mezi původním režimem Emacsu a Vimem popř. i opačným směrem. Ovšem pokud se editor nachází v režimu emulace Vimu, můžeme namísto hledání Alt+X použít i „vimovský způsob“:

:evil-mode
Poznámka: ve skutečnosti se totiž po zadání dvojtečky může zadat libovolný příkaz Emacsu, což sice koliduje s Vimovskými příkazy (například neexistuje :map), ovšem na druhou stranu stále máme přístup ke všem možnostem, které nám tento nejenom textový editor nabízí.

Obrázek 10: Přepnutí do režimu Evil zadáním příkazu M-x evil-mode.

6. Základní editační příkazy

Poznámka: v této kapitole i v dalších kapitolách se setkáme s jedním problémem – různou terminologií používanou ve Vimu a v Emacsu. Týká se to převážně termínů režim (mode) a stav (status). Ve Vimu se totiž používá termín režim (mode) pro rozlišení mezi zadáváním základních editačních příkazů (normal mode), vkládáním příkazů na příkazovou řádku (command mode), vkládáním nového textu (insert mode) atd. – viz následující obrázek. V Emacsu je však slovo režim/mode použito pro jiné účely (například samotný plugin Evil přináší nový evil-mode, blíže viz například Major-Modes), takže se namísto toho pro označení režimu Vi/Vimu používá slovo stav/state (normal state, insert state, …).

Obrázek 11: Režimy Vimu a způsob přechodu mezi nimi.

Ihned po povolení režimu evil (evil mode) se textový editor Emacs přepne do normálního stavu (normal state), tj. je možné zadávat prakticky všechny editační příkazy, které znáte z Vimu (emulace je skutečně na velmi dobré úrovni). Podporovány jsou samozřejmě i všechny operátory Vimu, dokonce včetně ROT13:

Operátor Význam Stručný popis
c change změna textu (delete a následný přechod do vkládacího režimu)
d delete vymazání textu
y yank kopie textu do registru
! filter filtrace přes externí příkaz
> shift right posun textu doprava o shiftwidth
< shift left posun textu doleva o shiftwidth
g~ swap case změna malých písmen na velké a naopak
gu lowercase změna na malá písmena (mínusky)
gU Uppercase změna na velká písmena (verzálky)
gq format zformátování textu
g? ROT13 rotace ASCII znaků o 13 pozic dopředu (režim modulo)
= indent změna zarovnání textu

Pro přepnutí do stavu vkládání se používají běžné příkazy a, A, i, I, o, O, c, R (stav přepisu) atd. Aktuálně nastavený stav je zobrazen na stavovém řádku každého bufferu. Jedná se o zápis [N], [V], [I], [R] atd. Při zapnutí stavu psaní nového textu se navíc objeví zpráva „– INSERT –“, podobně jako v samotném Vimu.

Klávesová zkratka C-SPC (neboli Ctrl+Space), která v Emacsu slouží pro nastavení značky, dostala poněkud odlišný význam – zapíná režim vizuálního výběru bloku. Je to vlastně logické, protože typické editační operace v Emacsu probíhají mezi pozicí kurzoru a nastavenou značkou (tzv. region) a ve Vimu pro vizuálně vybraný blok (tj. mezi začátkem bloku a pozicí kurzoru).

7. Práce s registry (registers)

Užitečným a často používaným nástrojem nabízeným textovým editorem Vim i režimem Evil jsou takzvané registry. Jedná se o proměnné pojmenované jedním znakem, které v první řadě slouží pro kopii či přenos editovaných textů pomocí příkazů c (change), s (substitute), d (delete), y (yank) a p (paste), což vlastně znamená, že registry lze využít ve funkci pojmenovaných schránek (clipboard). Podobně jako v případě dále zmíněných značek, existují registry naplňované uživatelem a registry, jejichž obsah je měněn textovým editorem automaticky při provádění různých operací. Jména a význam některých důležitých registrů můžete najít v následující tabulce:

Registr Význam
a-z registry, které je možné přímo měnit uživatelem
0 použitý při příkazu yank (kopie textu)
1–9 registry naplňované automaticky příkazy d a c (delete, change)
% není ve výchozím nastavení přímo použit
: registr obsahující poslední příkaz, vhodné při vyvolání tohoto příkazu jako makra
= není ve výchozím nastavení přímo použit
/ registr obsahující posledně vyhledávaný řetězec (resp. text odpovídající regulárnímu výrazu)
" implicitní registr pro operace c, d, s nebo y
implicitní registr pro operace, které mění menší část textu, než je jeden textový řádek

Obrázek 12: Zobrazení registrů (registers, resp. přesněji řečeno evil-registers).

8. Použití značek (marks)

Další užitečnou věcí, kterou ve Vimu a samozřejmě i v Evilu najdeme, jsou takzvané značky (marks). Nejedná se však o značky vytvářené externími nástroji a ukládané většinou do souboru pojmenovaného tags, ale o interní seznam pozic kurzoru (jakési „špendlíky“ zapíchnuté do důležitých míst) v souboru, na které se lze během editace vrátit, nebo na něž se lze odkazovat. Podobnou funkcionalitu nabízí i mnohé další programátorské textové editory, ovšem u nich se většinou jedná o maximálně deset značek, zatímco ve Vimu může být značek mnohem více, protože každé značce je přiřazeno jednopísmenné označení.

Obrázek 13: Zobrazení značek (marks, resp. přesněji řečeno evil-marks).

V rámci jednoho souboru lze lokálně používat značky pojmenované malými písmeny az, zatímco značky pojmenované velkými písmeny A až Z si „pamatují“ i jméno souboru, v němž jsou definovány, tudíž se jedná o značky globální. Speciální význam mají značky se jmény 0 až 9 (naplňované většinou při ukončování Vimu) a taktéž v některých případech velmi užitečná značka ". Významy některých jmen značek (ve skutečnosti jich je ještě mnohem více) jsou vypsány v následující tabulce:

Jméno značky Definice značky Význam
a-z manuálně značky lokální v rámci souboru
A-Z manuálně značky globální, ke značce je připojeno i jméno souboru
" automaticky pozice kurzoru při zavření bloku
^ automaticky pozice kurzoru, na níž se kurzor naposledy nacházel ve vkládacím režimu

Práce se značkami je v mnoha ohledech velmi jednoduchá, ostatně všechny důležité příkazy najdete v následující tabulce:

Příkaz Význam
:marks výpis všech právě aktivních značek
:marks značka výpis vybrané značky
ma – mz definice lokální značky a-z
mA – mZ definice globální značky A-Z
'a – 'z skok na řádek, kde je značka definovaná (jedná se o příkaz pohybu kurzoru!)
'A – 'Z skok na soubor a řádek, kde je značka definovaná
`a – `z skok na přesné místo, kde je značka definovaná (jedná se o příkaz pohybu kurzoru!)
'A – 'Z skok na přesné místo (řádek i sloupec), kde je značka definovaná

9. Uživatelská makra

Ve Vimu je možné definovat uživatelská makra, jejichž definice se uloží do zvoleného pracovního registru (definice makra obsahuje sekvenci stisknutých kláves, takže zde s výhodou využijeme především operátory zkombinované s příkazy pro pohyb v textu). Pro záznam makra se používá klávesová zkratka q[registr], například qa. Vim v tomto případě na stavový řádek vypíše slovo recording. V Emacsu je tomu nepatrně jinak, protože se namísto toho napíše zpráva:

Defining kbd macro...

Ukončení záznamu makra je provedeno pouze klávesou q. Ve Vimu se po zadání tohoto příkazu makro uloží do pracovního registru a slovo recording ze stavového řádku zmizí. Emacs (samozřejmě přepnutý do režimu evil) pracuje podobně, pouze navíc na stavový řádek vypíše zprávu:

Keyboard macro defined

Uživatelská makra lze přeložit do maker běžných v Emacsu. Postup je následující:

Makro vytvoříme běžným způsobem, tj. například qagU3wq pro převod tří slov na velká písmena. Následně zadáme příkaz:

:name-last-kbd-macro

a doplníme vhodné jméno makra, například „upcase3words“.

V posledním kroku si můžeme makro vypsat popř. vložit do souborů init.el či .emacs:

:insert-kbd-macro

Měl by se vypsat tento text:

(fset 'upcase3words
   "gU3w")

10. Další přizpůsobení Emacsu pro skalní Vimaře

Výchozí konfigurace používaná balíčkem Evil samozřejmě nemusí vyhovovat všem uživatelům. V navazujících kapitolách se zmíním o některých nastaveních, která osobně považuji za užitečná, i když se chování Evil-u bude odlišovat od standardního chování Vimu (přesněji řečeno od chování Vimu s nastavením nocompatible, tj. Vimu ve chvíli, kdy se nesnaží být zpětně kompatibilní s textovým editorem Vi). Podobná nastavení mám ovšem provedena i v klasickém Vimu, takže se oba textové editory budou z tohoto pohledu chovat velmi podobným způsobem.

11. Modifikace funkce klávesy Y

První nastavení se týká příkazu Y. Standardní chování tohoto příkazu totiž znamená: vlož celý řádek (popř. větší množství řádků při zadání čísla) do nějakého registru (při nezadání registru se použije registr pojmenovaný "). To ovšem logicky koliduje s dalšími operátory, zejména Change a Delete. Tyto operátory totiž existují v kombinacích umožňujících jejich aplikaci buď na celý řádek (více řádků) nebo od pozice kurzoru do konce řádku:

Operace Operátor Celý řádek Do konce řádku
Změna c cc C
Smazání d dd D
Kopie y yy/Y  

Logičtější by bylo následující chování:

Operace Operátor Celý řádek Do konce řádku
Změna c cc C
Smazání d dd D
Kopie y yy Y

Ve skutečnosti lze takového chování dosáhnout snadno, a to následujícím příkazem, který si můžeme přidat do souboru .emacs:

(setq evil-want-Y-yank-to-eol t)

12. Balíček evil-numbers

Jednou z užitečných vlastností textového editoru Vim je možnost používat (v normálním režimu) klávesové zkratky Ctrl+A a Ctrl+X pro zvýšení popř. pro snížení číselné hodnoty, která je zapsána na pozici kurzoru nebo kdekoli ZA pozicí kurzoru. Chování těchto klávesových zkratek je intuitivní a může se hodit například při tvorbě různých tabulek, seznamů apod.:

  • Po stisku Ctrl+A nebo Ctrl+X Vim zjistí, kde se (napravo od kurzoru) nachází číselná hodnota.
  • Následně se detekuje typ hodnoty (decimální číslo bez prefixu, hexadecimální číslo s prefixem 0×, osmičková hodnota s prefixem 0).
  • Tato hodnota se zvýší nebo sníží o jedničku. Popř. pokud je před klávesovou zkratkou Ctrl+A nebo Ctrl+X použit počet opakování, bude se přičítat nebo odečítat uživatelem zadaná hodnota větší než 1.
Poznámka: někdy tyto zkratky používám pro pouhý doskok na nejbližší číselnou hodnotu: Ctrl+A, Ctrl+X (i když je příkaz typu f0 alespoň na US/GB klávesnici rychlejší).

Toto chování je samozřejmě možné doprogramovat i do Emacsu; popř. je možné použít vhodný balíček, který toto naprogramování již obsahuje. Tento balíček skutečně existuje a jmenuje se evil-numbers.

13. Instalace a konfigurace balíčku evil-numbers

Balíček evil-numbers se instaluje zcela totožným způsobem jako jakýkoli jiný balíček:

Obrázek 14: Správce balíčků MELPA již máme povolen, takže po zadání příkazu M-x list-packages uvidíme i balíček evil-numbers.

Po instalaci balíčku evil-numbers se zdánlivě nic nezměnilo, protože je nutné provést alespoň minimální konfiguraci. Ta spočívá v načtení balíčku, ideálně při startu Emacsu a dále v namapování funkcí evil-numbers/inc-at-pt a evil-numbers/dec-at-pt na vhodné klávesové zkratky. V mém případě je provedeno nastavení odpovídající Vimu, tj. namapování kláves Ctrl+A a Ctrl+X v normálním režimu na obě zmíněné funkce:

(define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
(define-key evil-normal-state-map (kbd "C-x") 'evil-numbers/dec-at-pt)

Obrázek 15: Nastavení si můžete jednoduše vyzkoušet ve scratch bufferu (viz klávesové zkratky, které naleznete v menu Lisp-Interaction).

Samozřejmě je možné klávesové zkratky uchovat i pro další spuštění Emacsu, například následujícími příkazy vloženými do souboru .emacs:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
 
(package-initialize)
 
(require 'evil)
(require 'evil-numbers)
 
(evil-mode 1)
(define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
(define-key evil-normal-state-map (kbd "C-x") 'evil-numbers/dec-at-pt)

14. Ostatní užitečná nastavení

Mezi další užitečná nastavení, která je možné provést typicky při startu a inicializaci Emacsu, patří:

(setq evil-move-beyond-eol t)

Při tomto nastavení je možné v normálním stavu přesunout textový kurzor ZA poslední znak na řádku. To může být užitečné například pro ty uživatele, kterým vadí odlišné chování některých příkazů nebo maker na konci řádku (navíc se jedná o chování odpovídající klasickému Emacsu). Výchozího chování odpovídajícího Vimu dosáhnete příkazem:

(setq evil-move-beyond-eol nil)

Nastavení:

(setq evil-backspace-join-lines t)

umožňuje, aby například klávesová zkratka C-w (Ctrl+W) ve stavu zápisu textu dokázala mazat slova i na předchozích řádcích. Toto chování (které vlastně vůbec nesouvisí s klávesou Backspace) vypnete opačným nastavením:

(setq evil-backspace-join-lines nil)

Další nastavení se týká příkazů f a t sloužících pro vyhledávání znaku a skok na tento znak. Je možné přepínat mezi vyhledáváním na jediném řádku, což odpovídá Vimu:

(setq evil-cross-line nil)

A vyhledáváním kdekoli (to ovšem může mít vliv na některá makra):

(setq evil-cross-line t)

Konečně poslední užitečná konfigurační volba:

(setq evil-symbol-word-search t)
(setq evil-symbol-word-search nil)

se používá pro přepínání mezi režimem vyhledávání slov nebo celých identifikátorů pomocí příkazů * a #, což má vliv především ve chvíli, kdy se pracuje se zdrojovými kódy. Podívejme se, jaký vliv má tato volba na vyhledávání:

Obrázek 16: Za identifikátor je nyní považován text s pomlčkami popř. dalšími speciálními znaky.

Obrázek 17: Za identifikátor je nyní považováno jen jedno slovo.

15. Mapování kláves ve Vimu

Jeden z poměrně velkých rozdílů mezi klasickým Vimem a kombinací Emacs+Evil spočívá v odlišném přístupu k mapování kláves. Připomeňme si, že ve Vimu je možné použít například následující příkazy, které do tohoto editoru přidají další klávesové zkratky:

<i>" uložení souboru při stisku klávesy F2</i>
<i>" (ukončující entita <cr> zajišťuje automatické spuštění</i>
<i>" příkazu bez nutnosti stlačovat Enter)</i>
:map <F2> :w<cr>
 
" zavolání externího příkazu make při stisku klávesy F9
:map <F9> :!make<cr>
 
" kompilace právě editovaného souboru při stisku klávesy F7
:map <F7> :!gcc -c %<cr>
 
" posun jednoho řádku doleva či doprava pomocí
" klávesových zkratek Tab a Shift+Tab
:map <Tab> >>
:map <S-Tab> <<
Poznámka: sice je to dosti neobvyklé, ale znak " se ve Vim Scriptu používá pro zápis komentáře.

Kromě vytváření nových příkazů je možné měnit i příkazy již existující. Například lze zjednodušit posun kurzoru nahoru a dolů v dlouhém textovém řádku (rozděleném na obrazovce na více řádků volbou :set wrap) pomocí těchto mapování:

:map k gk
:map j gj

Předchozí mapování klávesových zkratek pracovalo v normálním režimu (resp. stavu v Emacsu), ovšem v případě potřeby je možné přiřazovat význam klávesám v režimu vkládacím příkazem :imap:

" pohyb kurzoru ve vkládacím režimu
" na začátek a konec řádku
:imap <C-A>      <C-O>g0
:imap <C-E>      <C-O>g$
 
" nové příkazy určené pro
" mazání znaků ve vkládacím režimu
:imap <C-Y>      <C-O>dd
:imap <C-Q>      <C-O>D
:imap <C-T>      <C-O>dw
:imap <C-G>      <Del>

Podobným příkazem :vmap je možné vytvářet nové klávesové zkratky pro vizuální režim, tj. pro režim, v němž se vybírá textová oblast:

" posun vybraných řádků doleva či doprava pomocí
" klávesových zkratek Tab a Shift+Tab
" s obnovením výběru (výběr se tedy nezruší!)
:vmap <Tab> >gv
:vmap <S-Tab> <gv
Povšimněte si, že se v předchozích příkladech používá klávesová zkratka Ctrl+O zajišťující přepnutí z režimu vkládacího či přepisovacího do režimu normálního, ovšem pouze pro provedení jednoho příkazu.

16. Mapování kláves v Emacsu

V Emacsu se namísto různých variant příkazu :map používá LISpovská funkce nazvaná define-key. Nápovědu k této funkci získáme snadno:

C-h f define-key
define-key is a built-in function in ‘C source code’.
 
(define-key KEYMAP KEY DEF)
 
In KEYMAP, define key sequence KEY as DEF.
KEYMAP is a keymap.
 
KEY is a string or a vector of symbols and characters, representing a
sequence of keystrokes and events.  Non-ASCII characters with codes
above 127 (such as ISO Latin-1) can be represented by vectors.
Two types of vector have special meanings:
 [remap COMMAND] remaps any key binding for COMMAND.
 [t] creates a default definition, which applies to any event with no
    other definition in KEYMAP.

Důležitý je hned první parametr MAP, který (velmi zjednodušeně řečeno) určuje tabulku s převody klávesa:akce-provedená-editorem. Ve chvíli, kdy je aktivní režim Evil, se používají tyto tabulky:

Tabulka/mapa Význam
evil-normal-state-map klávesy funkční v normálním stavu (výchozí stav Vimu i Evilu)
evil-window-map klávesy funkční po stisku C-w
evil-motion-state-map všechny posuny kurzoru, včetně počitadla posunů (3w apod.)
evil-outer-text-objects-map výběr textového objektu (slovo, věta, odstavec, blok)
evil-visual-state-map stav vizuálního výběru bloku
evil-operator-state-map stav, ve kterém již byla vybrána operace (c, d, y) a čeká se na zápis operátoru
evil-insert-state-map stav zápisu textu (ve Vimu klasický insert mode)
evil-replace-state-ma stav přepisu textu (ve Vimu klasický replace mode)

Podívejme se nyní na jednoduchý příklad. Budeme chtít, aby se po stisku velkého Z prohodily dva sousední znaky v textu (na levém znaku je kurzor). Ve Vimu to je snadné:

:map Z xp

V Emacsu můžeme pro zhruba stejnou operaci zavolat funkci transpose-chars, takže mapování vytvoříme takto:

(define-key evil-normal-state-map "Z" 'transpose-chars)

Oba dva příkazy (Vimovský i Evilovský) budou funkční v normálním stavu.

Obrázek 18: Namapování funkce transpose-chars na klávesu Z.

V některých situacích se však může hodit použít i „vimovský přístup“, v němž je nějaká klávesa (například ono velké Z) mapována na sekvenci znaků zapisovaných na klávesnici (v našem případě xp). V Emacsu samozřejmě prakticky nic není nemožné :-), takže je v tomto případě možné použít zápis:

(define-key evil-normal-state-map "Z" (kbd "xp"))

Obrázek 19: Namapování sekvence znaků „xp“ na klávesu Y.

Používáme zde funkci kbd:

kbd is a compiled Lisp function in ‘subr.el’.
 
(kbd KEYS)
 
Convert KEYS to the internal Emacs key representation.
KEYS should be a string in the format returned by commands such
as ‘C-h k’ (‘describe-key’).
This is the same format used for saving keyboard macros (see
‘edmacro-mode’).
Poznámka: podobné příkazy si můžete snadno naživo otestovat v bufferu *scratch*, v němž po zápisu celého příkazu použijte klávesovou zkratku C-M-x neboli Ctrl+Alt+X. Příkaz, zde konkrétně zavolání funkce define-key, se vykoná a na stavový řádek se vypíše návratová hodnota (ta nás ovšem nemusí příliš zajímat). Ihned poté by měla být nová klávesová zkratka aktivní.

17. Evil a Elisp

V předchozí kapitole jsme se již nepatrně dotkli jedné z nejdůležitějších technologií Emacsu. Jedná se o dialekt programovacího jazyka LISP, který je skutečně s Emacsem takřka neoddělitelně spojen, a to mj. i proto, že dnes pravděpodobně nejrozšířenější varianta Emacsu – GNU Emacs – je z velké části naprogramována v Emacs LISPu (Elispu). Volba LISPu vlastně není ani příliš překvapivá, protože se jednalo o programovací jazyk, který byl v polovině sedmdesátých let minulého století v AI Labu (kde první varianty Emacsu – což byla původně makra nad editorem TECO – vznikaly) poměrně intenzivně používán; později se dokonce někteří lidé z AI Labu podíleli i na konstrukci počítačů s LISPem. Jednalo se o takzvané Lisp Machines vyráběné například společností Symbolics, LMI Lambda či Xerox.

ZMACS

Obrázek 20: ZMACS je pokračovatelem editoru ZWEI naprogramovaného v LISPu (autor screenshotu: Phil.grenet).

Dnes se ještě (alespoň prozatím) nebudeme zabývat konkrétními možnostmi nabízenými Emacs LISPem, ovšem ukážeme si některé základní funkce, způsob vytváření uživatelských funkcí, jejich spouštění atd. Prakticky všechny operace budou prováděny v bufferu *scratch*, který má tři pro nás užitečné vlastnosti:

  1. Je automaticky otevřen po spuštění Emacsu (pokud si neprovedete úpravu konfigurace).
  2. Dovoluje zapisované funkce přímo spouštět (opět lze přenastavit, ale spouštění/vyhodnocování LISPovských funkcí je výchozí chování, protože buffer používá režim lisp-interaction-mode).
  3. Navíc pokud něco pokazíme, tak se obsah tohoto bufferu při ukončení Emacsu ztratí, takže Emacs gentlemansky přejde všechny možné chyby.

Obrázek 21: Čtení na dlouhé zimní večery aneb dokumentace k Emacs LISPu.

V jedenácté kapitole jsme si řekli, jakým způsobem je možné modifikovat funkci klávesy Y. Tato kapitola byla poměrně podrobná, což není náhoda, protože se nyní pokusíme funkci klávesy Y sami doprogramovat. Nebude se v žádném případě jednat o zcela korektní chování, ovšem seznámíme se s koncepcí značek (mark), kill-ringu, pojmu aktivního bodu (point) a taktéž s vlastním zápisem funkcí v Emacs LISPu.

Nejprve si vyzkoušejme jednodušší příklad – vytvoření příkazu pro smazání textu do konce řádku, což je typicky provedeno klávesovou zkratkou D. Očekávané chování klávesy D by mělo být „smaž text od pozice kurzoru do konce řádku a vlož tento text do registru“. Podobná funkce již v Emacsu ve skutečnosti existuje a jmenuje se kill-line (nenechte se zmást jejím jménem, skutečně maže text od pozice kurzoru); standardně je namapována na klávesovou zkratku C-k. Můžeme tedy klávese D tuto funkci přiřadit, a to následujícím způsobem:

(define-key evil-normal-state-map "D" 'kill-line)

Ovšem můžeme si zvolit i složitější způsob. Smazání textu do konce řádku (s uložením textu do kill ringu) lze v Emacsu provést i takto:

C-SPC C-e C-w

Což znamená postupné provedení těchto operací:

  1. Vložení značky (mark) na pozici kurzoru.
  2. Skok kurzorem na konec řádku.
  3. Smazání textu mezi značkou a kurzorem s jeho vložením do kill ringu.

Všechny tři výše zmíněné kroky jsou implementovány v odpovídajících (interaktivních) funkcích nazvaných set-mark-command, move-end-of-line a kill-region, takže je možné vytvořit funkci navázanou na klávesovou zkratku, v níž se postupně všechny tři uvedené funkce budou volat.

18. Využití funkcí evil-*

Ve skutečnosti však bude chování odlišné od klávesové zkratky D, a to z toho důvodu, že v režimu Evil se smazaný text ukládá do bufferů. Podobně tomu bude v případě pokusu o definici funkce namapované na klávesu Y. Můžeme zde ovšem využít ještě jednu možnost – zavolat funkce naprogramované v Emacs LISPu, které pro nás připravili tvůrci modulu Evil. Konkrétně se bude jednat o funkci evil-yank:

Obrázek 22: Nápověda k funkci evil-yank.

Z nápovědy je možné vyčíst, že tato funkce vyžaduje minimálně dva parametry udávající začátek a konec textu, který se má uložit do registru. Začátek textu je jednoduchý – zavoláme funkci point vracející aktuální souřadnice kurzoru:

Obrázek 23: Nápověda k funkci point vracející aktuální souřadnice kurzoru.

Konec oblasti ukládané do registru leží na konci řádku, takže (po delším hledání) můžeme zjistit, že lze použít funkci nazvanou line-end-position, která se v nejjednodušším případě volá bez parametrů:

Obrázek 24: Nápověda k funkci line-end-position vracející souřadnici na konci textového řádku.

Celý příkaz namapovaný na klávesu Y bude vypadat následovně:

Obrázek 25: Výsledný tvar příkazu namapovaného na klávesu Y.

Proč musí tato funkce/příkaz vypadat tak, jak je zapsána (včetně interactive) si řekneme příště.

bitcoin_skoleni

19. Obsah navazujícího článku – projekt Spacemacs

V dalším článku na podobné téma si nejdříve popíšeme další moduly používané společně s modulem evil. Jedná se například o pluginy umožňující komentování označeného bloku kódu, plugin nahrazující Vimovský modul Surround atd. Ve druhé části dalšího článku si představíme projekt Spacemacs, který je z velké části naprogramovaný právě v Emacs Lispu a ukazuje možnosti tohoto jazyka a samozřejmě i „enginu“, nad kterým je tento jazyk postaven.

Obrázek 26: Logo projektu Spacemacs.

20. Odkazy na Internetu

  1. Evil (Emacs Wiki)
    https://www.emacswiki.org/emacs/Evil
  2. Evil (na GitHubu)
    https://github.com/emacs-evil/evil
  3. Evil (na stránkách repositáře MELPA)
    https://melpa.org/#/evil
  4. Evil Mode: How I Switched From VIM to Emacs
    https://blog.jakuba.net/2014/06/23/e­vil-mode-how-to-switch-from-vim-to-emacs.html
  5. GNU Emacs (home page)
    https://www.gnu.org/software/emacs/
  6. GNU Emacs (texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs
  7. An Introduction To Using GDB Under Emacs
    http://tedlab.mit.edu/~dr/gdbin­tro.html
  8. An Introduction to Programming in Emacs Lisp
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/index.html
  9. 27.6 Running Debuggers Under Emacs
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­macs/Debuggers.html
  10. GdbMode
    http://www.emacswiki.org/e­macs/GdbMode
  11. Emacs (Wikipedia)
    https://en.wikipedia.org/wiki/Emacs
  12. Emacs timeline
    http://www.jwz.org/doc/emacs-timeline.html
  13. Emacs Text Editors Family
    http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily
  14. Vrapper aneb spojení možností Vimu a Eclipse
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/
  15. Vrapper aneb spojení možností Vimu a Eclipse (část 2: vyhledávání a nahrazování textu)
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse-cast-2-vyhledavani-a-nahrazovani-textu/
  16. Emacs/Evil-mode – A basic reference to using evil mode in Emacs
    http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet
  17. From Vim to Emacs+Evil chaotic migration guide
    https://juanjoalvarez.net/es/de­tail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
  18. Introduction to evil-mode {video)
    https://www.youtube.com/wat­ch?v=PeVQwYUxYEg
  19. EINE (Emacs Wiki)
    http://www.emacswiki.org/emacs/EINE
  20. EINE (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?EINE
  21. ZWEI (Emacs Wiki)
    http://www.emacswiki.org/emacs/ZWEI
  22. ZWEI (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?ZWEI
  23. Zmacs (Wikipedia)
    https://en.wikipedia.org/wiki/Zmacs
  24. Zmacs (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?Zmacs
  25. TecoEmacs (Emacs Wiki)
    http://www.emacswiki.org/e­macs/TecoEmacs
  26. Micro Emacs
    http://www.emacswiki.org/e­macs/MicroEmacs
  27. Micro Emacs (Wikipedia)
    https://en.wikipedia.org/wi­ki/MicroEMACS
  28. EmacsHistory
    http://www.emacswiki.org/e­macs/EmacsHistory
  29. Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
    http://www.finseth.com/emacs.html
  30. evil-numbers
    https://github.com/cofi/evil-numbers
  31. Debuggery a jejich nadstavby v Linuxu (1.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  32. Debuggery a jejich nadstavby v Linuxu (2.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  33. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  34. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  35. Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim
    https://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-5-ladeni-aplikaci-v-editorech-emacs-a-vim/
  36. Org mode
    https://orgmode.org/
  37. The Org Manual
    https://orgmode.org/manual/index.html
  38. Kakoune (modální textový editor)
    http://kakoune.org/
  39. Vim-style keybinding in Emacs/Evil-mode
    https://gist.github.com/tro­yp/6b4c9e1c8670200c04c16036805773d8
  40. Emacs – jak začít
    http://www.abclinuxu.cz/clan­ky/navody/emacs-jak-zacit
  41. Programovací jazyk LISP a LISP machines
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lisp-a-lisp-machines/
  42. Evil-surround
    https://github.com/emacs-evil/evil-surround
  43. Spacemacs
    http://spacemacs.org/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.