[voikko] Oikoluku Vim-editoriin

Teemu Likonen tlikonen at iki.fi
Sun Aug 10 21:50:04 EEST 2008


Vim-editorissa on versiosta 7.0 saakka ollut sisäänrakennettu oikoluku. 
Suomen kielen kannalta se ei paljon lohduta, koska se käyttää omia 
sanastotiedostojaan. Vimille on myös olemassa erilaisia ispelliä tai 
muita ulkoisia ohjelmia käyttäviä laajennoksia, mutta en oikein ole 
ollut niihinkään tyytyväinen: bugisia tai hitaita.

Tilanne otti päähän sen verran, että ohjelmoin oman Vim-laajennoksen. Se 
ei sisällä hienoja ominaisuuksia mutta tekee juuri sen, mitä itse 
kaipasin: nopeasti toimiva reaaliaikainen oikoluku, joka maalaa 
tunnistamattomat sanat. Oikolukuun käytetään /usr/bin/enchant-ohjelmaa, 
joka ainakin Debian 4.0:ssa tulee paketin libenchant1c2a mukana. 
Ilmeisesti oikoluku toimii kaikilla kielillä, joita Enchantin kautta 
tuetaan. Itse olen kokeillut vain Voikon kanssa. Laajennos itsessään ei 
tarjoa minkäänlaisia kieliasetuksia, joten ilmeisesti locale-muuttujat 
vaikuttavat.

Oletuksena oikoluku kytketään päälle Vimin normaalitilassa 
näppäinyhdistelmällä \s1 ja pois päältä yhdistelmällä \s0. 
Näppäinkomennot voi muuttaa laittamalla .vimrc-tiedostoon esimerkiksi 

    nmap <F5> <Plug>EnchantSpellCheckOn
    imap <F5> <Plug>EnchantSpellCheckOn
    nmap <F6> <Plug>EnchantSpellCheckOff
    imap <F6> <Plug>EnchantSpellCheckOff

jolloin F5 kytkee oikoluvun päälle ja F6 pois päältä (sekä normaali- 
että lisäystilassa).

Oikoluvun sai tehokkaaksi sillä, että se oikolukee ainoastaan ikkunassa 
näkyvän alueen. Tunnistamattomat sanat maalataan Vimin värikoodilla 
SpellErrors - sama, mitä sisäänrakennettu oikolukukin käyttää. Oikoluku 
käynnistyy automaattikomentojen CursorHold ja CursorHoldI avulla eli 
suomeksi sanottuna se ajetaan kerran aina sen jälkeen, kun käyttäjä on 
ollut toimettomana Vimin sisäisen 'updatetime'-asetuksen näyttämän ajan. 
Oletuksena se on 4000, ja yksikkönä on millisekunti. Omissa 
asetuksissani pienensin arvoa hieman, jotta oikoluku reagoi vähän 
nopeammin:

    set updatetime=1000

Todennäköisesti hion tätä Vim-laajennosta vielä jonkin verran mutta 
ajattelin jo mainostaa ensimmäistä prototyyppiä tällä listalla. Tässä 
vaiheessa ihmeempiä virhetilanteiden tarkistuksia ei ole. Kannattaa 
asentaa enchant valmiiksi ja käyttää vähintään Vimin versiota 7.0. En 
ole vielä keksinyt edes nimeä tällä, mutta satuin nyt luomaan tiedoston 
niinkin omaperäisellä nimellä kuin voikko.vim (liitteenä). Se asennetaan 
yksinkertaisesti siirtämällä se hakemistoon ~/.vim/plugin/ , jolloin se 
latautuu aina Vimin käynnistyessä.

Palaute on tervetullutta ja käyttö tietysti omalla vastuulla.
-------------- next part --------------
" Enchant-pohjainen oikoluku
"
" Version:	0.0.0.0.1
" Maintainer:	Teemu Likonen <tlikonen at iki.fi>
" License:	Public domain

" {{{1 Alkujutut
if &compatible
	finish
endif
let s:save_cpo = &cpo
set cpo&vim

function! s:SpellCheckSwitch(switch) "{{{1
	if a:switch
		let s:save_isk = &l:isk
		setlocal isk&vim
		autocmd! Voikko
		autocmd Voikko CursorHold,CursorHoldI <buffer> call s:CheckSpelling()
		call s:CheckSpelling()
	else
		autocmd! Voikko
		call clearmatches()
		if exists('s:save_isk')
			let &l:isk = s:save_isk
		endif
		redraw!
	endif
endfunction

augroup Voikko | augroup END
call s:SpellCheckSwitch(0)

function! s:CheckSpelling() "{{{1

	call clearmatches()

	let line = winsaveview()['topline']
	let lines = winheight(0)
	let word_string = ''
	while lines > 0
		let fold = foldclosedend(line)
		if fold > 0
			let line = fold
		else
			let word_string .= getline(line).' '
		endif
		let line += 1
		let lines -= 1
	endwhile

	let spell_errors = split(system('enchant -l',word_string))
	for word in spell_errors
		call matchadd('SpellErrors','\V\<'.word.'\>')
	endfor
	redraw!
endfunction

" {{{1 Näppäinhommat

nnoremap <silent> <Plug>EnchantSpellCheckOn  :call <SID>SpellCheckSwitch(1)<CR>
nnoremap <silent> <Plug>EnchantSpellCheckOff :call <SID>SpellCheckSwitch(0)<CR>

function! s:Add_Mapping(mode, lhs, rhs)
	if maparg(a:lhs, a:mode) == '' && !hasmapto(a:rhs, a:mode)
		execute a:mode.'map '.a:lhs.' '.a:rhs
	endif
endfunction

call s:Add_Mapping('n','<Leader>s1','<Plug>EnchantSpellCheckOn')
call s:Add_Mapping('n','<Leader>s0','<Plug>EnchantSpellCheckOff')
delfunction s:Add_Mapping

" {{{1 Loppujutut
let &cpo = s:save_cpo
" vim600: fdm=marker


More information about the voikko mailing list