Vzhľadom na pozitívny ohlas na predchádzajúci článok o VIMe som pripravil pokračovanie. V minulom článku sme zabudli spomenúť autora VIMu – Bram Moolenaara. Okrem samotného VIMu treba oceniť aj jeho charitatívny program, ktorým prispieva na deti v Ugande. Preto ak máte možnosti a chuť prispieť, a aj takouto formou odmeniť húževnatosť autora, pozrite si jeho sponzorskú stránku.
Už podľa minulej časti je jasné, že v týchto článkoch nie je mojím cieľom ísť do úplných detailov, do ktorých ide referenčná alebo užívateľská príručka. Ak vás nejaká vlastnosť zaujme, je nutné jej detaily doštudovať v helpe. Takže pokročilým užívateľom sa ospravedlňujem za občasnú povrchnosť.
Minule sme sa venovali ergonómii a efektívnosti práce. V dnešnom článku si budeme ďalej spríjemňovať prácu s editorom pomocou okien a ukážeme prácu s viacerými súbormi. Naučíme sa formátovať a ľahko udržiavať písaný text. Minule sme zabudli na značky (marks), takže to dnes napravíme a na záver nevynecháme zopár zaujímavých a užitočných tipov.
Práca s oknami, bufframi a záložkami
Oknami vo VIMe máme na mysli nie tradičné okná vo význame GUI okien, ale rozdelenie GUI na podokná, v ktorých si môžete zobrazovať súbory. Výhodou je, že fungujú rovnako v grafickom systéme aj v znakovej konzole. Okná a buffre sú oddelené systémy. Jedinou podmienkou je, že v jednom (pod)okne môžete mať v danom čase zobrazený iba jeden súbor/buffer. Tu je príklad s tromi oknami, pričom v spodných dvoch je zobrazená vždy iná časť toho istého súboru:
Buffre
Buffre predstavujú otvorené súbory (nové buffre sú iba v pamäti). Buffre môžu byť v jednom z troch stavov. Aktívne (active) buffre sú také, ktoré sú zobrazené v okne a natiahnuté v pamäti, skryté (hidden) nie sú zobrazené v žiadnom okne, ale sú natiahnuté v pamäti a inaktívne nie sú zobrazené v okne a nie sú natiahnuté ani do pamäte. Buffre si môžete zobraziť pomocou :buffers. Ja mám tento príkaz namapovaný na CTRL-L. Pôvodne je príkaz CTRL-L určený na prekreslenie okna. Tento príkaz som ale pre GUI verziu už dlho nepotreboval (ak by sa text rozsypal, môžete použiť :redraw) takže si ho môžete premapovať na zobrazenie buffrov pomocou
:map ^L :buffers^M<Enter>
Pričom ^L napíšete ako <CTRL-Q><CTRL-L> a ^M je <CTRL-Q><Enter>. Potom po stlačení <CTRL-L>sa zobrazí napr.:
:buffers 5 a "[No Name]" line 0 7 %a + "~/clanok2.txt" line 22 10 "aa" line 1
V prvom stĺpci je číslo buffra, v druhom je status, v treťom názov súboru a v poslednom je čislo riadku, na ktorom sa nadchádza kurzor. Detailný popis stavového stĺpca sa dozviete v :help :buffers.
Ešte sa naučíme jeden trik na premapovanie kláves v insert móde. Klávesa <CTRL-O> v insert móde umožní spustiť jeden príkaz v normal móde a vráti vás naspäť do insert módu. Takže na premapovanie <CTRL-L>v insert móde musíme urobiť:
:inoremap ^L ^O:buffers^M<Enter>
Kde namiesto ^ stlačte <CTRL-Q> (pre unixákov <CTRL-V>). Takže ^L znamená <CTRL-Q><CTRL-L>.
Okná
Ak si chcete naraz zobraziť viacero buffrov (rozumej súborov), musíte použiť okná. Okno nie je fixne viazané na buffer. V okne si môžete vymeniť zobrazený buffer. Prejdime niektoré príkazy na prácu s oknami:
- <CTRL-W>n – otvorí nové prázdne okno ‚Window New‘
- <CTRL-W>s – otvorí nové okno s existujúcim buffrom/súborom ‚Window Split‘
- <CTRL-W>v – to isté ako <CTRL-W>s ale vertikálne ‚Window Vertical split‘
- <CTRL-W>c – zatvorí okno ‚Window Close‘
- <CTRL-W>h – presunie kurzor do okna vľavo
- <CTRL-W>l – presunie kurzor do okna vpravo
- <CTRL-W>j – presunie kurzor do okna dole
- <CTRL-W>k – presunie kurzor do okna hore
- <CTRL-W>w – presunie kurzor do ďalšieho okna v poradí
- <CTRL-W>p – presunie kurzor do predchádzajúceho okna v poradí
- <CTRL-W>H – presunie okno najviac doľava
- <CTRL-W>L – presunie okno najviac doprava
- <CTRL-W>J – presunie okno úplne naspodok
- <CTRL-W>K – presunie okno úplne nahor
- <CTRL-W>T – presunie okno do nového tabu
- <CTRL-W>_ – zväčší okno vertikálne na maximum (alebo nastaví na N riadkov)
- <CTRL-W>| – zväčší okno horizontálne na maximum (alebo nastaví na N stĺpcov)
- <CTRL-W>= – pokúsi sa urobiť všetky okná rovnako veľké
- <CTRL-W>o – zatvorí všetky ostatné okná ‚Window Only one‘
- <CTRL-W>+ – zväčší okno o N riadkov (default 1)
- <CTRL-W>- – zmenší okno o N riadkov (default 1)
- <CTRL-W>> – zväčší okno o N stĺpcov (default 1)
- <CTRL-W>< – zmenší okno o N stĺpcov (default 1)
- :bnext – zobrazí do aktuálneho okna ďalší buffer
- :bprev – zobrazí do aktuálneho okna predchádzajúci buffer
- :brew – pretočí buffre na začiatok ‚rewind‘
- :buff N – zobrazí buffer N
Síce som sa chcel vyhnúť popisu v štýle referenčná príručka, ale stalo sa. Tu asi nepomôže nič iné, iba sa tieto skratky naučiť. Samozrejme veľa z nich je logických a ak si odmyslíme <CTRL-W>, tak skratky ako hjkl a HJKL si zapamätáte ľahko, zväčšenie pomocou +- a <> sú tiež pochopiteľné. Samozrejme niektoré príkazy majú aj numerické prefixy, ale nič nelogické, čo by uživateľ neočakával.
Ja okná používam dosť často. Ak napríklad potrebujete pri písaní vidieť inú časť toho istého súboru, otvorte si ho do ďalšieho okna stlačením <CTRL-W>s. V každom z týchto okien môžete pracovať na inej časti toho istého súboru. Minimálne je zábavné otvoriť si súbor do dvoch okien a sledovať pri písaní, ako sa mení aj v druhom okne. Keď ste skončili, môžete zatvoriť aktuálne okno pomocou <CTRL-W>c alebo zatvoriť všetky ostatné <CTRL-W>o. Ak potrebujete iba dočasne pracovať v jednom okne bez potreby vidieť ostatné, ale viete, že neskôr sa k nim chcete vrátiť, roztiahnite si aktuálne okno na maximum pomocou <CTRL-W>_ a<CTRL-W>|. Keď znovu chcete vidieť všetky okná, použite <CTRL-W>=.
Väčšinu :b… príkazov mám namapovaných na skratky. Keďže veľa skratiek vo VIM už má priradenú funkcionalitu a vzniklo veľa skriptov, ktoré premapovávali príkazy, vymyslel Bram spôsob, aby si každy užívateľ mohol vytvoriť vlastný prefix a skripty ho mohli používať. Keď si vytvárate skript, kde si premapovávate klávesy, môžete použiť špeciálnu klávesu <Leader>. Takže v skripte môžete premapovanie urobiť napríklad pomocou:
:map <leader>n :bnext^M
Znak <leader> je štandardne namapovaný na znak \. Takže mapovanie z predchádzajúceho príkladu sa spustí po stlačení \n. Tento znak môžete zmeniť ideálne priamo vo ~/.vimrc
:let mapleader = ","
Samozrejme vo ~/.vimrc bez dvojbodky na začiatku. Ešte jedno upozornenie, po zmene mapleader sa predchádzajúce mapovania zachovávajú, takže iba nové mapovania budú mať nový prefix.
Záložky (ušká)
Ja osobne som záložkám neprišiel na chuť. Radšej si spustím celé nové GVIM okno. Ale pre úplnosť uvediem aj zopár skratiek pre použitie záložiek. Asi všetky príkazy pre prácu s bufframi majú aj záložkový ekvivalent, iba si zameňte v názve príkazu b za tab. Takže si vyskúšajte :tabnew :tabnext :tabprev :tabrew :tabclose :tabonly :tabs :tabedit <subor> :tabmove N. Myslím, že preddefinované klávesové skratky existujú iba na :tabnext a to gt a <CTRL-PageDown> a na :tabprev gT a<CTRL-PageUp>.
Formátovanie textu
Pri formátovaní textu v podstate hovoríme o formátovaní dlhých riadkov textu. Musíme rozlišovať, či chceme text iba vizuálne prívetivejšie zobrazovať, alebo ho chceme skutočne formátovať tak, že budeme vkladať znaky nového riadka (\n \r v rôznych kombináciach podľa druhu OS). V podkapitole „Zobrazenie dlhých riadkov textu“ pojednávam iba o zobrazení a v kapitole „Zalomenie textu“ o aktívnom formátovaní pomocou vkladania znakov nového riadku.
Zobrazenie dlhých riadkov textu
Pri zobrazení dlhých riadkov sa VIM najprv pozerá na nastavenie premennej wrap. Ak chcete, aby text takpovediac pretekal za okraj okna, nastavte :set nowrap. To samozrejme spôsobí, že VIM nemusí nalievať text do okna a text za okrajom až po znak nového riadka proste ignoruje, čo znamená, že zobrazovanie sa radikálne zrýchli. V okne sa ale ťažko rozlišuje, či text je za okrajom. To môžeme vylepšiť nastavením premennej ‚listchars‘ napríklad :set listchars+=extends:>,precedes:<. To zobrazí príslušné znaky, v našom príklade < a > na začiatok a koniec riadku, ktoré pretekajú za ľavý alebo pravý okraj.
Všetky zmeny, ktoré vidíte na nasledujúcich screenshotoch, sa robia na rovnakom texte postupným spúšťaním vysvetľovaných príkazov.
:set nowrap
:set listchars+=extends:>,precedes:<
a po zaskrolovaní doprava pomocou 19w.
Ak potrebujete, aby sa text do okna nalieval, nastavte premennú :set wrap. Takto sa na znaku, ktorý sa už nezmestí na obrazovku, zobrazovanie presunie na ďalší riadok. Ak chcete, aby sa zalamovanie robilo iba medzi slovami, nastavte premennu :set linebreak. To spôsobí, že text je oveľa lepšie čitateľný. Nastavenie linebreak používa premennú breakat, v ktorej sú uvedené znaky, na ktorých je možné text zalomiť. Ak chcete vidieť, ktoré riadky sú zalomené, nastavte premennú :set showbreak=>>>, čo na začiatok každého zalomeného riadku vloží znaky >>>.
:set wrap
:set linebreak
:set showbreak=>>>
:set display+=lastline
Pri veľmi dlhých riadkoch v prípade, že sa pri zalamovaní zistí, že text preteká pod spodný okraj, všetky riadky v odstavci (ak to nie je odstavec na ktorom stojí kurzor) sú nahradené znakom @. Zobraziť aspoň viditeľnú časť riadku môžete zabezpečiť nastavením :set display+=lastline. Ešte raz by som upozornil, že v celej tejto podkapitole sme sa bavili iba o možnostiach zobrazovania. Žiadne z týchto nastavení nemodifikuje obsah súboru. Keďže dlhé riadky sa iba zobrazujú zalomene príkazy na prechod po riadkoch ‚j‘ a ‚k‘ nepracujú tak, ako očakávate, pretože skáču nie po vizuálnych riadkoch, ale po skutočných textových riadkoch. Ak vám to nevyhovuje, použite nasledovné nastavenia vo ~/.vimrc ktoré premapujú štandardné príkazy ‚j‘ ‚k‘ a šipky:
noremap k gk noremap j gj map <up> gk imap <up> <C-o>gk map <down> gj imap <down> <C-o>gj map <home> g<home> imap <home> <C-o>g<home> map <end> g<end> imap <end> <C-o>g<end>
Zalomenie textu
Pri písaní textu ako je HTML alebo bežný text môžete využiť poloautomatické formátovanie textu do požadovanej šírky. Spôsoby formátovania uvedené v tejto podkapitole modifikujú text, a to tak, že mažú alebo vkladajú znak nového riadka podľa nastavení editora. Začneme tým, že nastavíte premennú textwidth na požadovanú šírku textu, napríklad :set textwidth=80
. Potom počas písania, keď sa dostanete za hranicu 80 znakov, práve písané slovo preskočí na nový riadok. Ak potom neskôr upravíte text (zmažete slovo alebo doplníte v strede riadku), je treba znovu ho preformátovať. Najľahšie, ak príslušný text označíte do vizuálneho bloku a spustíte reformátovanie pomocou gq alebo použijeme textové objekty z minulého článku a naformátujeme celý aktuálny odstavec cez gqap. Kusy textov oddelené prázdnym riadkom sa nespájajú, takže je dobré, ak odstavce medzi sebou oddeľujete dvomi entermi (čím vznikne prázdny riadok). To je len tak mimochom a nie náhodou TeX štandard, respektíve VIM rešpektuje tento zaužívaný TeX štandard.
Detaily formátovania si môžete nastaviť v premennej formatoptions
. Nájdete tu aj možnosti napríklad na preskakovanie formátovania komentárov, špeciálnu detekciu odstavcov, podporu pre rozdielne formátovanie prvých riadkov, úplne automatické formátovanie aj počas mazania alebo dopĺňania textu v strede riadku alebo detekciu číslovaných zoznamov. Nájsť si to môžete v helpe :help fo-table. Ak nastavíte premennú paste, zabránite akémukoľvek formátovaniu. Táto premenná sa v GUI nastavuje úplne automaticky. Pred vložením textu z clipboardu sa premenná paste zapne a po ukončení sa vypne. Aj v bežných termináloch sa v znakovom režime väčšinou premenná paste správne nastavuje automaticky a nie je potrebné ju ručne nastavovať. Ak chcete, môžete si pre preformátovanie pomocou gqnastaviť vlastnú VIM funkciu alebo externý program, ktorý sa použije na formátovanie (pozrite si help k ‚formatexpr‘ a ‚formatprg‘).
Podobne, ako nastavujete premennú textwidth, ktorá definuje šírku textov, môžete definovať šírku textu ako vzdialenosť od pravého okraja okna nastavením napríklad :set wrapmargin=5. Premenná textwidth musí byť nastavená na hodnotu 0, ináč sa bude hodnota wrapmargin ignorovať. Nevýhoda premennej wrapmargin je v tom, že šírka formátovaného textu závisí od šírky okna. Ak zmeníte šírku okna, zmení sa aj šírka formátovaného textu. Na čiste textových termináloch je to zas naopak veľmi dobre použiteľné.
VIM diff
Treba vedieť že VIM si detekuje, s akým menom ste ho spustili, a podľa toho sa nastavia niektoré premenné. Aj keď týchto ‚aliasov‘ je viac, ja používam prevažne iba:
- vim – normálny textový VIM (gvim je vim s GUI)
- view – readonly VIM (gview je view s GUI)
- vimdiff – diff súborov (gvimdiff je vimdiff s GUI)
Mnohí ľudia ani nevedia, že VIM môže slúžiť aj ako celkom elegantný diff program. Spustíte gvimdiff file1 file2 alebo gvim -d file1 file2 z príkazového riadku. Priamo vo VIMe môžete porovnať aktuálny buffer s iným pomocou :diffsplit file2 alebo :diffpatch patchfile. Komplikovanejšie je použitie :diffthis, kedy tento option nastavíte najprv pre jeden buffer a pri nastavovaní druhého sa VIM automaticky prepne do diff módu.
Rozdiely medzi súbormi môžete zarovnávať tak, že sa postavíte na riadok, ktorý obsahuje rozdiel (býva farebne odlíšený) a po stlačení do alebo :diffget sa zmena z druhého súboru prenesie do súboru, v ktorom stojíme. Ak použijeme dp alebo :diffput, prenesie zmenu z aktuálneho súboru do druhého súboru. Potom samozrejme môžeme obidva alebo iba jeden zo súborov uložiť na disk.
Posielanie vzdialených príkazov
Z príkazového riadka môžete do bežiaceho VIMu poslať ľubovolný príkaz a takto v podstate vzdialene ovláť bežiaci VIM. Funguje to ale iba pre GUI verziu. Najprv si zistíme zoznam spustených VIMiek pomocou príkazu vim –serverlist. Vypíšu sa mená všetkých spustených VIMiek (servrov), napríklad GVIM. Potom môžete poslať do VIMka napríklad sekvencie kláves pomocou vim –servername GVIM –remote-send ‚<C-\><C-N>:%s/a/QQ/g<Enter>‘, sekvencia <C-\><C-N> zabezpečí, že sa prejde do command módu, nech je editor v akomkoľvek inom móde. Môžete si aj jednoducho otvoriť súbor v už bežiacem VIMku pomocou vim –remote file alebo vim –remote-tab file, ktorý súbor otvorí v novom tabe.
Značky (marks)
Kamarát Zoli ma v minulom článku upozornil na jednu dôležitú vec, ktorú sme v prvom dieli trestuhodne vynechali – robenie značiek. Ak viete, že na určitú pozíciu v súbore sa budete častejšie vracať, môžete si ju označiť pomocou m<pismenko>. Malé písmenká sú lokálne značky vnútri jedného súboru (buffra). Veľké písmenká sú globálne a umožňujú skákať aj medzi súbormi. Na označené miesto sa môžete odkialkoľvek vrátiť stlačením '<pismenko> alebo `<pismenko>. Rozdiel medzi ' a ` je v tom, že obyčajný ' nedodržiava zapamätaný stĺpec, ale vždy skočí na stĺpec 0. Spätný apostrof ` skočí presne na zapamätanú pozíciu vrátane stĺpca.
Nakoľko je obyčajný apostrof viac po ruke (vedľa pravého malíčka) a skok vrátane stĺpca je užitočnejší, môžete si význam príkazov ' a ` prehodiť pomocou:
:nnoremap ' ` :nnoremap ` '
Niektoré značky sa umiestňujú automaticky v texte. Takto môžete skočiť napríklad na nasledujúce automaticky označené pozície:
- . – Pozícia poslednej zmeny
- ^ – Miesto ukončenia posledného insert módu
- < – Začiatok naposledy označenej vizuálnej oblasti
- > – Koniec naposledy označenej vizuálnej oblasti
- " – Miesto v súbore kde ste stáli keď ste súbor (nie okno) zatvárali, značka sa umiestni napríklad po príkazoch :bdelete :x :wq ZZ
Všetky aktuálne značky si môžete zobraziť pomocou :marks. Keď si tento príkaz vyskúšate, zistíte, že v zozname sa vyskytujú aj značky pre čísla. Tam sa v podstate nachádza história naposledy otvorených súborov. To sa mimochodom zachováva aj spolu s inými stavovými informáciami v súbore ~/.viminfo (:help viminfo).
V tejto súvislosti ma napadá jeden užitočný príkaz, gi. Ten umožňuje pokračovať v písaní tam, kde ste naposledy s písaním skončili. Takže ak si neviete spomenúť na niečo, čo máte mimo zorného poľa, ukončite písanie pomocou <ESC> a nájdite to, čo potrebujete, akýmkoľvek spôsobom. Ak niečo potrebujete, natiahnite si to do clipboardu alebo je vám už jasné, čo máte písať, môžete pokračovať pomocou gi. Editor skočí na miesto, kde ste stlačili <ESC> a rovno sa prepne do insert módu.
Iné
Ak chcete premenovať súbor, ktorý práve editujete, môžete použiť :saveas FILENAME. Odvtedy sa všetky operácie so súborom ako napr. :w budú zapisovať do tohto súboru. Samozrejme celý koncept ako všetko vo VIM je komplikovanejší a doštudovať si ho môžete na :help alternate-file.
Ak chcete vrátiť všetky zmeny, ktoré ste urobili, do stavu, v akom sú uložené na disku (revert to saved), urobte :e!
Zobrazenie niektorých štatistík ako počet riadkov, znakov, bytov, slov, môžete urobiť pomocou g<CTRL-G>. Na zobrazenie informácií o znaku, na ktorom stojíte, použite ga alebo g8.
Zobrazenie všetkých premenných (a že ich je dosť) môžete urobiť cez :set all a ak chcete zobraziť tie, ktoré majú inú hodnotu ako štandardnú, použite:set.
Pre rýchlejšie písanie môžete často používané skratky alebo preklepy upravovať počas písania pomocou :iabbr
. Takže si skúsime premapovať text ‚mymail‘ na ‚pavel.tavoda@mojadomena.sk‘.
:iabbr mojmail pavel.tavoda@mojadomena.sk
Spustíme insert mód a napíšeme mojmail<Space>. Po stlačení medzery by mal text expandovať na úplný e-mail.
Trochu problematické je odmapovanie v prípade, že použijete namiesto :iabbr
štandardné :abbr
alebo :cabbr
, ktoré pracuje aj v command móde, pretože pri odosielaní príkazu odmapovania sa po stlačení <Enter> nahradí pravou stranou. Našťastie príkaz :unabbr s tým počíta a ak sa nepodarí nájsť nič v ľavej časti, začne sa prehľadávať v pravej časti abbr tabuľky. Pre komplikovanejšie situácie musíte použiť malý trik napríklad:
:abbr abc 123 :abbr def 123
ak chcete odmapovať druhé mapovanie ‚def‘, môžete to urobiť cez :unabbr def<CTRL-Q><Space><Enter>
pretože ak by ste použili :unabbr def<Enter>
, odmapujú sa obidve.
Blbinka na záver
V GUI si môžete nastaviť alebo zmeniť počet riadkov a stĺpcov, ktoré vidíte v okne. V podstate resiznuť okno bez myšky. Použite príkaz :set columns=120 lines=40<Enter>
. Samozrejme môžete to urobiť aj v ~/.gvimrc .
Záver
Dnes sme si obzor rozšírili o ďalšie zaujímavé možnosti editora VIM. Na záver by som chcel poďakovať Pavlovi Tišnovskému, ktorý prispel niektorými nápadmi a nastaveniami. O ktoré časti by ste mali záujem nabudúce:
- Pikošky s regexp
- Text folding
- Tvorba pluginov
- Známe rozšírenia (VIM Cream, Autocomplete, Najlepšie tipy, …)
- Integrácia VIM do Javy