Makra
Zdaleka nejvíce vaši práci urychlí vhodná definice maker. Zejména při editaci textů psaných ve značkovacích jazycích (HTML, XML, TeX a jeho nadstavby, *roff,…), je život bez nich krajně otravný. Téhle oblasti jsem věnoval nemalé množství energie a představím vám současnou podobu mého života s makry, se kterou jsem docela spokojen.
Můj první pokus o makra se odehrával cestou zkratek (příkaz :abbreviation
, zkráceně :ab
). Rychle jsem je však zavrhl, protože zkratka ke své aktivaci vyžaduje, aby byla následována „neslovním“ znakem (typicky mezerou, koncem řádku, <Esc> apod.). Vzniká ale problém, co s oním znakem. Pokud mi makro má zapnout tučné písmo, nechci za ním mít mezeru, ale první znak tučného textu. Což člověka nutí psát mezery, které vzápětí vymazává, či dělat podobné věci proti přírodě. Tudy podle mne cesta nevede.
Klasický Vi nic moc jiného nenabízel, protože mapování kláves (příkaz :map
) pracovalo jen v příkazovém režimu. A odskakovat si z vkládacího režimu do příkazového pokaždé, když chcete zapnout tučné písmo, je krajně otravné. Vim naštěstí umí toto mapování provádět i ve vkládacím režimu prostřednictvím příkazu :imap
.
Považuji :imap
za optimální způsob pro definici maker. Zbývá najít vhodné klávesy, které se budou mapovat. Začínal jsem s Ctrl-něco, jenže jsem neustále narážel na konflikty s existujícími příkazy. V nápovědě se doporučuje používat Alt-něco, což fungovalo dobře až do nástupu grafické verze editoru. Zde Alt-písmeno otevírá odpovídající menu, takže zase problémy.
Nakonec jsem dospěl k tomu, že místo klávesové kombinace budu mapovat sérii kláves, což jde. Zahajující klávesou je vždy čárka. Hraje vlastně roli Ctrl či Alt. V běžném textu za čárkou skoro vždy přichází mezera, takže hrozba konfliktu s makry je minimální. Takže když napíši ve vkládacím režimu sekvenci ,bb
, znamená to „vložit příkazy pro tučné písmo“. Zcela konkrétně při editaci HTML textu se vloží značky <STRONG></STRONG> a kurzor couvne zpět mezi ně, abych se mohl rovnou pustit do psaní tučného textu. Celá definice vypadá následovně:
imap ,bb <STRONG></STRONG><Esc>F<i
Původně jsem používal ,b
, ale mapovaná sekvence nesmí být začátkem jiné mapované sekvence, takže tím jsem si znepřístupnil všechny názvy začínající na „b“. Proto u základních (nejpoužívanějších) sekvencí písmeno zdvojuji, což člověk napíše skoro stejně rychle jako jediné písmeno, a přitom si neblokuji normální jména začínající na „b“.
Podívejme se, kolik práce mi dá napsat tučné slovo (v HTML) ve srovnání s tímtéž úkolem v nějakém WYSIWYG nástroji:
Tabulka č. 123 Vim: ,bb
slovo<Alt-doprava>
WYSIWYG: <Ctrl-B>
slovo<Ctrl-B>
Vynaložená práce je prakticky stejná (ve Vim je o jedno sáhnutí na klávesnici více).
Vhodné složení maker je samozřejmě zcela individuální otázkou. Závisí především na tom, jakého charakteru jsou texty, které píšete. Já například jen vzácně sepisuji matematické vzorce, takže nemám žádná makra pro TeXovskou matematiku. Na druhé straně často potřebuji vkládat obrázky a tabulky, takže jsem si připravil makra i pro tyto složitější konstrukce. Například tabulku vkládám makrem ,tab
:
imap ,tab <TABLE BORDER="0"><CR><TR><TD></TD> <TD></TD></TR><CR></TABLE><Esc>k02f>a
(vše na jednom řádku)
Hodí se také makra pohybová, která odpovídají editovanému formátu. Například výše použitá kombinace <Alt-doprava> mi přesune kurzor za následující znak „>“, což se v HTML dost hodí:
imap <M-Right> <Esc>f>a
Jedinou nástrahou víceznakových maker začínajících čárkou je jejich případná kolize s normálním textem. Vim sleduje zapisované znaky a pokud tvoří začátek vyvolávací sekvence některého makra, nevkládá je do textu. Jen si je pamatuje a sleduje, co bude dál. Možnosti jsou tři:
- zapíšete název některého makra - pak bude provedeno
- pokračování již nevyhovuje jménu žádného makra - v tom případě se všechny znaky normálně vloží do textu (tohle se např. děje tehdy, když za čárkou napíši mezeru)
- uděláte při psaní delší přestávku - Vim přeruší sledování makra a znaky vloží do textu
První dva případy jsou jasné. Třetí vychází z předpokladu, že makro budete psát souvisle. Tedy jednotlivé znaky budou následovat rychle po sobě. Uděláte-li delší přestávku, zřejmě se nemá jednat o makro. Znaky tudíž budou vloženy do textu a Vim se o ně přestane zajímat jako o potenciální makro.
Implicitní doba čekání na další znak do makra je jedna sekunda. Můžete ji nastavit příkazem :set timeoutlen=
čas, kde čas se zadává v milisekundách. Tuto vlastnost můžete i zcela vypnout pomocí :set notimeout
. Pak bude Vim čekat na další klávesu neomezeně dlouho a jeho chování se omezí jen na první dva případy.
Asi nejjednodušší cestou ke vložení sekvence znaků, které normálně vyvolají makro, je přerušit ji nevhodným znakem (např. mezerou). Například po čárce napíšete mezeru, kterou vzápětí vymažete. Ale start makra už tím byl přerušen, čárka se zapsala do textu a Vim už ji dále nebude chápat jako zahajovací.
Nejlepší však je se takovým situacím zcela vyhnout. Takže například zásadně nemapuji makra na sekvence začínající čárka-číslice, protože tahle kombinace se běžně vyskytuje.
Stejné chování pro různé formáty
Život je pestrý a editují se různé věci, z nichž některé jsou si podobné. Například já střídavě upravuji texty ve třech různých formátech: LaTeX, HTML a XML (podle vlastního DTD, které se dost podobá HTML). Považuji za silně žádoucí, aby se Vim choval konzistentně. Tedy aby například ,bb
vždy znamenalo „tučné písmo“. Čili aby přizpůsobovalo svou činnost editovanému formátu a jednou vkládalo \textbf{}
, podruhé <STRONG></STRONG>
a ve třetím případě <b></b>
.
Makra sama o sobě takhle chytrá být nedovedou, ale můžete zařídit, že Vim automaticky načte jejich definice v závislosti na editovaném formátu (dobrá, na příponě souboru). Zařídí to příkaz :autocommand
.
Zcela konkrétně jsem si ve svém domácím adresáři vytvořil podadresář .vim, do nějž ukládám definiční soubory maker pro jednotlivé formáty - například tex.vim a html.vim. Do svého soukromého .vimrc jsem si pak přidal následující příkazy:
autocmd BufRead,BufNewFile *.html source ~/.vim/html.vim autocmd BufRead,BufNewFile *.htm source ~/.vim/html.vim autocmd BufRead,BufNewFile *.tex source ~/.vim/tex.vim
Zajistí, že například při vytvoření nebo otevření souboru s příponou .html se aktivují makra definovaná v souboru ~/.vim/html.vim.
Značkovací jazyky zpravidla vyžadují jakousi povinnou kostru dokumentu, která je jednotná. Je výhodné nezačínat s prázdnou a do nově vytvářených souborů rovnou vložit odpovídající kostru. V adresáři ~/.vim mám proto také soubory empty.tex a empty.html. Ve .vimrc pak navíc k výše uvedeným příkazům najdete ještě
autocmd BufNewFile *.html r ~/.vim/empty.html autocmd BufNewFile *.tex r ~/.vim/empty.tex
Kontrola pravopisu
Podívejme se pravdě do očí: Vim neobsahuje podporu pro kontrolu textu. Celkem dlouho jsem to nepovažoval za žádnou velkou tragédii a prostě jsem si externě spouštěl ispell. V poslední době jsem však zavadil o hezký nápad, jak zapojit zvýrazňování syntaxe do služeb kontroly pravopisu. Doufám, že to nebylo tady na rootovi (pokud ano, omlouvám se za opakování).
Myšlenka je jednoduchá a vtipná: zavolá se spell checker, který vydá seznam neznámých slov v textu. Tento seznam se následně transformuje na skupinu syntaktických pravidel, která dotyčná slova zařadí do třídy „chyba“. Pravidla se pak načtou do Vim a výsledkem je, že editor vyznačí všechna neznámá slova.
Hlavní práci vykoná skript vimspell.sh, který jsem umístil do svého oblíbeného adresáře ~/.vim. Spustí ispell, zpracuje jeho výstup, výsledek uloží do adresáře /tmp a vydá jméno odpovídajícího souboru jako svůj výsledek. Do osobního .vimrc (nicméně kontrola pravopisu bude asi zajímat všechny, takže by se hodila i do globální konfigurace) jsem přidal následující dvojici příkazů:
command Spell source `$HOME/.vim/vimspell.sh %`
command NoSpell syntax clear SpellErrors
(V mém klientovi je to dost mizerně vidět, takže zdůrazňuji, že celý text za slovem „source“ v prvním příkazu je uzavřen do zpětných apostrofů.) Definují dvojici nových (uživatelských) příkazů: :Spell
a :NoSpell
. První si spustí skript vimspell.sh a interpretuje obsah souboru, jehož jméno skript vydá, jako příkazy pro Vim. Výsledkem je, že obarví všechna neznámá slova v textu. Příkaz :NoSpell
pak toto obarvení zruší.
Nezapomeňte, že ispell dostane jméno souboru a načítá si text ze souboru, nikoli z pracovní paměti Vim. Nezapomeňte proto před kontrolou pravopisu uložit text na disk.
Chcete-li si interaktivně přidávat neznámá, leč správná slova do uživatelského slovníku, můžete přihodit následující mapování:
:noremap <F10> :execute '!echo <cword> >> $HOME/.ispell_czech' \| Spell<CR><CR>
(opět vše na jednom řádku)
Nyní stačí najet na dotyčné slovo kurzorem a stisknout (v příkazovém režimu) klávesu <F10>. Slovo pod kurzorem se přidá na konec souboru .ispell_czech ve vašem domácím adresáři a rovnou se obnoví hledání a zobrazení chyb.
A tím pro dnešek skončíme. Příště se v posledním pokračování podíváme na uživatelem definovaná menu.