Voi veljet. Annoin itselleni tehtäväksi parsia tekstimuotoista TODO-listaa koneen paremmin ymmärtämiksi riveiksi, joita on luontevaa antaa vaikka Conkylle pureksittavaksi. Formaattia luulin helpoksi käsiteltävän Pythonilla, mutta toisin kävi.
Formaatti
Tässä on ote Todo-listastani VimWiki-etusivulta.
= TODO = - [ ] Rtorrentista delugeen. Paljon etuja. - [ ] Irssiin joku väritys nimimerkeille. Samanhenkinen systeemi kuin irssilog-syntaksivärjäyksessä vimissä. - [ ] conkyyn viritelmä lukea tästä index.wiki -tiedostosta ruksaamattomia juttuja. Mitäpä ei perlinpätkällä saisi aikaan. Intervalliksi vaikka 5 min, jotta ei tunnu pahasti - [ ] järjestele kaikki allaolevat aliotsakkeet omiksi sivuikseen - [ ] Skeezulle shell-opas: vuoropuhelumalliin? Little Schemer.
No, tässä ei ole vain ote, vaan koko listaus. Ajattelin jo, että tämä onnistuu helpolla iteraatiolla Pythonissa. Mutta ei oikein onnistu. Tiedostoa ensin voi lukea siihen pisteeseen, että löydetään rivi, jolla lukee = TODO =
, ja sitten parsitaan seuraavan kappaleen edestä.
Mutta moniriviset viritelmät lisäävät kovasti työtä, ja koodista tuli hyvin nopeasti epäelegantin näköistä. Fiksuinta olisi ollut kai tässä tapauksessa kirjoittaa rekursio, mutta kyllästyin siihen nopeasti. Vimissä asioita pyöriteltyäni tajusin, että vim-skripti voisi ollakin oikea ratkaisu tähän malliin. Vimiähän on helppo skriptata myös tekstitiedostoa käyttäen, mutta ongelmana oli, että sitä ei saa tulostettua stdouttiin.
Ratkaisuna on ex
, tuo surullisenkuuluisan ed
-ohjelman helpompi seuraaja, jota myös vi
-ohjelman taustalla käytetään. Ex-skriptissä en voi käyttää kaikkia herkullisia vim-komentoja, mutta tulos on silti aika mukiinmenevä. Ex-kieli sopii tämänlaiseen tekstinkäsittelyyn hävyttömän hyvin. Ei tarvitse ajatella niinkään silmukoita tai rekursioita, vaan ajatellaan, että nyt etsitään tämä kohta ja tehdään siihen nämä muutokset. Tässä on lopullinen koodi, ns. ex-skripti:
edit /home/progo/.vim/wiki/index.wiki " Poistetaan kaikki TODO-riviin asti 1,/^= TODO =/d " sekä yksi (toiv.) tyhjä rivi 1d " Sitten poistetaan kaikki TODO-kappaleen jälkeinen, alkaen ensimmäisestä tyhjästä /^\s*$/;$d " sitten yhdistetään moniriviset virsut %g/^ /exe "normal kJ" " ja poistetaan tehdyt pois, ja siistitään. %g/- \[X] /d %s/- \[ ] // %p q!
Rankasti kommentoitu, jotta ei mene sekaisin. Onhan tuo nimittäin aika kryptistä. Pääideana ex-komennoissa on antaa lähtöosoite, loppuosoite, sekä joku toiminto (delete, move, copy). Tavallisesti osoitteet tarkoittavat rivinumeroita, mutta onneksi ex tukee myös hakutoimintoa osoitteen tilalla.
Kun yhdistelemme monirivisiä todo-entryjä, joudumme käyttämään Vim-spesifisiä erikoiskikkoja: nimittäin Vimissä voimme käyttää g
-komennon (global) kanssa vim-komentoja tai -funktioita. Aina löytäessämme sisennetyn rivin, komennamme vim-komentoa kJ
sille riville. Koo niin kuin ylöspäin yksi rivi, ja iso J on alemman rivin joinaaminen ylempään. Turhat välit hävitetään automaattisesti. Tämä olisi pythonilla vaatinut aikamoista iteraatiomagiaa, tai ainakin vakavaa regexp-taituruutta. Väittäisin, että vim-harrastaja näkee tämän ex-skriptin ainakin hieman helppolukuisempana.
Ikävä yllätys oli se, että ex-skriptiä suoritettaessa se tallensi tiedostoon tehdyt muutokset, vaikka en erikseen skriptiin antanut tuttua :write
-komentoa. Erillinen quit!
näyttää kuitenkin auttavan. Onnistuin jo menettämään joitain tekemiäni muutoksia wikin etusivuun. Backup on parin päivän takaa, ja onneksi kaikkea ei menetetty.
Olen kuitenkin haltioissani saadessani lisätä exin työkalupakkiini. Tässä tuntee itsensä järin tehokkaaksi.