25. heinäkuu 2012, 13:27

Pythonin vastaisku lispeille: IPython ja vim-ipython

Tai “Pythonin uusi toivo” tai “Pythonin paluu”. Mistä on kyse? Pythonin tulkin me kaikki kai tiedämme: kaikki siinä periaatteessa on, mutta ei sillä mitään kunnollista rakentele. Koska se on niin rajoittunut. Sillä voi tehdä pikaiset kokeilut, mutta eipä paljoa muuta. Nyt ilmeisesti asian on moni python-koodailija aina eksperttejäkin myöten huomannut, ja on kehitetty aikojen saatossa paranneltu tulkki- ja kehitysympäristö IPython.

Kuulin tästä vasta toissapäivänä ensimmäistä kertaa, ja luonnollisesti heräsi kiinnostus tulkin kykyihin. Jos se tulkki olisi kirjoitettu oikeaoppisesti ja kaukonäköisesti, sillä voisi saada vimiin sellaiset integraatiot, joista vain Swank ja SLIME on aiemmin tunnettu.

(Vimillehän löytyy SLIME:n toiminnallisuutta replikoiva SLIMV, joka toivottavasti jonain päivänä kehittyy käytettävälle tasolle. Lisäksi pelkästään Clojurelle löytyy erinomaiseksi viritelty VimClojure, jota suosittelen sydämeni kyllyydestä.)

IPython käytännössä

Vaikka vimiä ei käyttäisikään, kannattaa IPython asentaa jo rutkasti parannellun tulkin takia. Ja ominaisuuksiahan siitä riittää! Parhaat mehut siitä puristetaan kuitenkin vasta kunnollisen editori-integraation avulla.

IPython toimittaa ns. kernelin, joka vastaa javan yhtä virtuaalikonetta tai lispien vastaavia kerneleitä. Mitä ytimeen on määritelty, se siellä säilyy. Kunnes roskat kerätään tai kerneli sammutetaan. Näitä kerneleitä voi käynnistellä itsenäisiksi palvelimiksi. Tällöin se kerneli vastaa lispien Swank-palvelinta: asiakasohjelma lähettää TCP:n välityksellä palvelimelle koodia tai muun vastaavan kyselyn, ja palvelin (kerneli) lähettää vastineen takaisin. Mukana tulee pari kappaletta klienttejä. Oletuksena starttaa konsolisovellus, mutta myös graafisia QT-konsoleita voi halutessaan käytellä.

IPython-version tulisi olla mielellään 0.12, jotta esittelemäni integraatio näyttää samalta kuin siellä ruuduilla.

vim-ipython

Siistin kokoinen vim-ipython on yhden tiedoston ihme, joskin se kannattaa silti asentaa oikeaoppisia reittejä (l. Pathogen) paikoilleen. Jos Pathogen on käytössä oletuspoluilla, niin asennus on näinkin simppeli:

cd ~/.vim/bundle
git clone git://github.com/ivanov/vim-ipython.git

Huomaatte oitis, että tämä ei ole aivan kokonaisvaltainen Python-ratkaisu vimiin. Syntaksivärjäykset ja automaattiset sisennykset pitää hommata muualta, mutta useinpa ne tulevat vim-asennuksien mukana. Ylläolevalla github-sivulla on pari linkkiä opastusvideoihin, mutta koodia seuraamalla selviää pääkohdat. Ja vimissä on oltava Python-tuki mukaankäännettynä. Moderneissa vimeissä usein onkin.

Asennus oli näin helppo! Oletusnäppäinyhdistelmät ovat hieman rumat, mutta niitäpä saa onneksi tuunata sydämensä kyllyydestä. Niitä katsotaan lopuksi.

Käyttö

Ensin käynnistetään kerneli tavalla tai toisella. Kokeillaan ensin naiivia jakoa kahteen, eli toiseen termikseen käynnistetään perinteinen IPython-instanssi kerneleineen. Käskyttämällä ipython console pitäisi saada ruutu täyteen python-tulkkia.

Nyt vimissä avaamme python-bufferin tai muuten vaihdamme bufferin tiedostotyypiksi pythonin. Voimme komentaa :IPython ja homman pitäisi sillä selvitä: skripti ottaa yhteyttä tuoreimpaan IPython-kerneliin, jonka se löytää.

Python-puskurissa kirjoitettuja rivejä voi lähettää kernelille <C-s>-näpäytyksellä. Sitten voimme todeta, että uusi funktio, hello, on todellakin kernelissä. Rämpyttelemme alempaan ikkunaan jotain testintapaista. Käytössämme on parhaat palat molemmista maailmoista, mutta vim-ipython osaa kikkoja omastakin takaa:

  • <C-s> lähettää valitut rivit kernelille.
  • <F5> ajaa tiedoston kernelillä.
  • \d tekee kyselyn kursorin alla olevasta oliosta ja lähettää datan pikkuikkunaan vimissä. Tämän ruudun saa nopeasti kiinni q-näpäytyksellä (kunhan olet aktivoinut oikean akkunan).
  • \s avaa pikkuikkunaan backlogin kernelin lähettämistä vastauksista. Tämänkin saa kiinni q:lla.
  • Lisäysmoodissa toimii kunnollinen täydennys, ja se on <C-x><C-u>:n takana. Se tuntee oliot ja ominaisuudet kuten kuuluukin: kyselee kerneliltä luultavasti dir-funktioiden avulla tarkat tiedot.
  • <M-c> kommentoi ja <M-S-c> epäkommentoi. Itsehän käytän vakiintunutta ja yleisesti hyväksyttyä NERDCommenteria mieluummin.

Korvaathan \-näppäimen jollain muulla, jos olet vaihtanut leader-asetusta vimissä. Suominäppäimistöllä taisteleville varmasti kannattava vaihdos, sillä tuo \ on aika kehnossa paikassa.

Tämä on peruskäyttöä. Periaatteessa vim-ipython sisältää sen verran työkaluja, että erillistä tulkkia ei tarvitse koko aikaa pitää esillä. Suurin puute taisi olla, että debuggaustoimintoja ei ole integroitu vielä mukaan. Toisaalta konsolin voi käynnistää milloin tahansa ja kytkeä sen olemassaolevaan kerneliin, jos tulee sellaisia tarpeita. Ihmisiä tuntui kuitenkin kiinnostavan se tapaus, että samaan ikkunaan saisi sullottua tuon tulkin. Tutkitaan sitäkin nyt.

Kaikki vimin sisälle

Koska IPythonin konsoliklientti on vain tavallinen värejä ja readlinea käyttävä ratkaisu, on se helppo saada toimimaan vimin sisällä mainion conque-pluginin avulla. Itse asiassa noissa Conquen demokuvaruutukaappauksissakin näkyy IPython käytössä. Se on hieman isompi kokonaisuus kuin vim-ipython, joten Pathogenin käyttö on entistäkin suositeltavampaa. No, asennat sen niin tai näin, on lopulta käytettävissä terminaaliemulaattori vimin sisällä.

Nyt käynnistetään IPython-kerneli (pelkkä kerneli riittää) tausta-ajoon.

$ ipython kernel&

Koska kerneli ei suolla ulos tulosteita, voimme avata vimin samaan ikkunaan. Sekä konsoli-vim että gvim toimii. GVimissä luultavasti saa paremmat värit Conquen väriemuloinnista johtuen. Käynnistämme vimin tyhjään python-puskuriin esimerkissämme ja ajamme :IPython-komennon. So far so good. Pikainen python-näpertely ja koodin lähettäminen osoittaa, että kerneli on toiminnassa ja aktiivinen. Kaikki lelut toimivat, kuten \d ja koodintäydennys.

Sitten vielä se ruutu: komentorimpsun :ConqueTermSplit ipython console --existing pitäisi toimia heittämällä. Ja kas näin… enempää et taida tarvita. Conque avaa oman bufferin kaikilla herkuilla, jotka eivät aina osu yksiin vimin omien näppäinten kanssa. Sen kanssa on koitettava elää, ja onhan Conquekin aika kustomointikykyinen paketti. Koska kyseessä on aivan tavallinen puskuri, sen voi asetella aivan miten haluaa. Horisontaaliseksi tai vertikaaliseksi splittaukseksi tai laittaa omaan tabiinsa, tai vaikka pitää piilossa.

Jos Conque alkaa hyytyä värienkäytöstä jossain vaiheessa, kannattaa tutkia IPythonin dokumentaatioista mahdollisuus nyppiä värit pois. Saman voi tehdä toki Conquenkin puolelta. Hyvä vastine on laittaa vimin oma python-värjäys päälle. Se on tehokkaampi ratkaisu tosiaan.

Näppäinten kustomointi

Kaikki näyttää hyvältä tähän asti… kyllä. Katsotaan vielä joitain ergonomisempia näppäinyhdistelmiä skriptille. Nykyisissä on hieman suunnitteluvikaa ja sen sellaista. Yleensä leader-näppäinyhdistelmät varataan globaaleille skripteille ja tiedostotyyppispesifisiä yhdistelmiä laitetaan localleader-näppäimen taakse (localleader kannattaa asettaa pilkuksi .vimrc:ssä).

Fiksuin tapa näppäinten ylikirjoittamiseen taitaa olla sopivan muuttujan määritteleminen .vimrc:ssä ja sitten kirjoitamme uudet näppäimet vim-skriptiksi. Asetetaan seuraava rivi .vimrc:hen:

let g:ipy_perform_mappings = 0

Nyt vim-ipython on ilman mitään valmiita näppäimiä. Tehdään vaikkapa tiedosto ~/.vim/after/ftplugin/python/vim-ipython-customkeys.vim. Kuten varmaan tiedättekin, after-hakemiston alle tehdyt skriptit ajetaan aivan viimeisenä, eli vim-ipythonin oletamme ajetuksi.

Seuraavanlaista huttua sinne voi suoltaa:

" vim-ipython: kustomoidut näppäimet ergonomiaa ajatellen.

" samoja kuin alkuperäisessä + <buffer>
map <buffer> <silent> <F5> :python run_this_file()<CR>
map <buffer> <silent> <S-F5> :python run_this_line()<CR>
map <buffer> <silent> <F9> :python run_these_lines()<CR>
map <buffer> <silent> <S-F9> :python toggle_reselect()<CR>
imap <buffer> <C-F5> <C-O><F5>
imap <buffer> <S-F5> <C-O><S-F5>
imap <buffer> <silent> <F5> <C-O><F5>
map <buffer> <C-F5> :call <SID>toggle_send_on_save()<CR>

" dokumentaatio
map <buffer> <silent> <localleader>d :py get_doc_buffer()<CR>
map <buffer> <silent> K :py get_doc_buffer()<CR>

map <buffer> <silent> <localleader>s :py if update_subchannel_msgs(force=True): echo("vim-ipython shell updated",'Operator')<CR>

" koodin lähettäminen. Nämä ovat VimClojuresta napattuja ja hyväksihavaittuja.
map <buffer> <silent> <localleader>el :python run_this_line()<CR>
map <buffer> <silent> <M-s> :python dedent_run_this_line()<CR>
vmap <buffer> <silent> <localleader>e :python run_these_lines()<CR>
vmap <buffer> <silent> <M-s> :python dedent_run_these_lines()<CR>

" lähetä nykyinen funktio, eli yksi tekstikappale
map <buffer> <silent> <localleader>et vip:python run_these_lines()<CR>

" lähetä koko puskuri. Ei tarvitse olla siis tallennettu tiedostoon, kuten
" <F5>:sta painettaessa.
map <buffer> <silent> <localleader>eb ggvG:python run_these_lines()<CR>

" sulje ylin esikatseluikkuna. Toimii vain, kun se on dokumentaatio- tai
" logiakkuna. Lisäksi toimii vain kun kursori python-bufferissa. Ja vierestä ei
" noin vain hypätä, vain alhaalta ylös. Puutteita, puutteita...
map <buffer> <silent> <localleader>p 99<C-w>kq

" Kooditäydennys. Tabia havittelevat tutkivat SuperTabia googlella.  Vapaita
" näppäimiä lisäysmoodissa vaikka <C-f>, <C-b>, ... kokeilemalla selviää.
" <C-Space> taitaa toimia Gvimissä, mutta ei konsolissa.
"inoremap <buffer> <silent> <C-Space> <C-x><C-u>

Oleellisesti näillä näppäimillä saadaan seuraavat VimClojure-henkiset näppäimet käyttöön:

  • ,el lähettää nykyisen rivin.
  • ,et lähettää nykyisen tekstikappaleen. Se käy python-funktiosta, jos kirjoitat rivit yhteen rimpsuun. (Tähän voisi hakea toivotun parannuksen googlaamalla jonkun python-skriptin, joka hakee luotettavasti funktion alun ja lopun.)
  • ,eb lähettää koko puskurin.
  • ,d kysyy olion dokumentaatiota. (Sulje q:lla.)
  • K synonyymi edelliselle. (Vimin oikeaoppinen dokumentaationhakunäppäin.)
  • ,s hakee kernelin login ikkunaan.
  • ,p sulkee avautuvat pikkuruudut (ei toimi kunnolla tosin, lähinnä kernelilogin sulkemiseksi).

Näiden lisäksi on ne vanhat näppäimet: <F5> ajaa nykyisen tiedoston, jonka pitää siis olla tallennettuna. Vim-ipythonin saa myös lähettämään tiedoston aina tallennuksen jälkeen, johon on noita näppäimiä, joilla togglata (<C-F5>).

Tageja: , ,

---
---

---

Aiheen vierestä