if exists("g:loadedtranslit")
finish
endif
let g:loadedtranslit=1
let s:russian={}
scriptencoding utf-8
call extend(s:russian,{"a" : 'а'})
call extend(s:russian,{"b" : 'б'})
call extend(s:russian,{"c" : 'ц'})
call extend(s:russian,{"d" : 'д'})
call extend(s:russian,{"e" : 'е'})
call extend(s:russian,{"f" : 'ф'})
call extend(s:russian,{"g" : 'г'})
call extend(s:russian,{"h" : 'х'})
call extend(s:russian,{"i" : 'и'})
call extend(s:russian,{"j" : 'й'})
call extend(s:russian,{"k" : 'к'})
call extend(s:russian,{"l" : 'л'})
call extend(s:russian,{"m" : 'м'})
call extend(s:russian,{"n" : 'н'})
call extend(s:russian,{"o" : 'о'})
call extend(s:russian,{"p" : 'п'})
call extend(s:russian,{"q" : 'я'})
call extend(s:russian,{"r" : 'р'})
call extend(s:russian,{"s" : 'с'})
call extend(s:russian,{"t" : 'т'})
call extend(s:russian,{"u" : 'у'})
call extend(s:russian,{"v" : 'в'})
call extend(s:russian,{"w" : 'ш'})
call extend(s:russian,{"x" : 'ь'})
call extend(s:russian,{"y" : 'ы'})
call extend(s:russian,{"z" : 'з'})
call extend(s:russian,{"zh" : 'ж'})
call extend(s:russian,{"ch" : 'ч'})
call extend(s:russian,{"wh" : 'щ'})
call extend(s:russian,{"xh" : 'ъ'})
call extend(s:russian,{"sh" : 'ш'})
call extend(s:russian,{"'" : 'ь'})
call extend(s:russian,{"\"" : 'ъ'})
call extend(s:russian,{"e\"": 'ё'})
call extend(s:russian,{"e'" : 'э'})
call extend(s:russian,{"u'" : 'ю'})
call extend(s:russian,{"o'" : 'ё'})
call extend(s:russian,{"i'" : 'й'})
call extend(s:russian,{"c'" : 'ч'})
call extend(s:russian,{"w'" : 'щ'})
call extend(s:russian,{"ex" : 'э'})
call extend(s:russian,{"ux" : 'ю'})
call extend(s:russian,{"ox" : 'ё'})
call extend(s:russian,{"ix" : 'й'})
call extend(s:russian,{"cx" : 'ч'})
call extend(s:russian,{"wx" : 'щ'})
call extend(s:russian,{"sch": 'щ'})
let g:translist={"ru": s:russian}
let s:arrangedtrans={}
" {{{
" function s:IsLong(strans, uchar)
" for s:item in keys(a:strans)
" if s:item=~a:uchar.'.\+'
" return 1
" endif
" endfor
" return 0
" endfunction
" }}}
"{{{ Переделать массив из формы, удобной для человека, в форму, удобную скрипту
function s:ArrangeTrans(trlanguag)
let s:arranged={}
" {{{ Get vars
for [vars, key] in items(g:translist[a:trlanguag])
let s:fstchar=vars[0]
if has_key(s:arranged,s:fstchar)
if strlen(vars)<=1
let s:endvar="END"
else
let s:endvar=vars[1:]
endif
call extend(s:arranged[s:fstchar],{s:endvar : key})
else
if strlen(vars)<=1
let s:endvar="END"
else
let s:endvar=vars[1:]
endif
call extend(s:arranged,{s:fstchar : {s:endvar : key}})
endif
endfor
" }}}
return s:arranged
endfunction
" }}}
" {{{ Получить символ из строки s:ustring
function s:GetcharFromString()
" {{{ Конец строки
if s:index>=strlen(s:string)
return "END:EOS"
endif
" }}}
let s:r0=s:string[s:index]
" {{{ Проверка полученных символов
if !s:backchar
" {{{ Эти символы надо экранировать, чтобы они не интерпретировались
if s:r0=~"\<C-m>\\|\b\\|\<C-c>\\|\e"
let s:backchar=1
return '\'
else
let s:index+=1
endif
" }}}
else
" {{{ Если символы уже были заэкранированы
let s:index+=1
let s:backchar=0
" }}}
endif
" }}}
return s:r0
endfunction
" }}}
" {{{ Транслителировать символ
function s:GetSymb(strans)
if len(a:strans)>1
"{{{ Если есть несколько последовательностьей, начинающихся с символа
"{{{ Объявление переменных
let s:utab='@' " На этом символе обрывается последовательность, но сам
" символ не печатается (предотврашение транслитерации
" конструкции как конструкции из нескольких символов)
let s:uchar=s:getchar() " Следующий символ
" }}}
" {{{ Обрыв последовательности
if s:uchar==s:utab
if has_key(a:strans, "END")
return ["END:Converted,Tab", a:strans["END"]]
endif
return ["END:NotConverted,Tab,NoEND", s:uchar]
endif
" }}}
" {{{ Последовательность
if has_key(a:strans, s:uchar)
" {{{ Это последовательность из нескольких символов
" {{{ Из двух
" if strlen(a:strans[s:uchar])<=1
return ["END:Converted,Len", a:strans[s:uchar]]
" endif
" }}}
"TODO: {{{ Из трёх
" sch — щ ; s — с ; c — ц ; h — х ; sc — к ; scc — т
" {'s': 'с', 'sc': 'к', 'scc': 'т', 'sch': 'щ'}
" {'s': {'END': 'с', 'c': 'к', 'cc': 'т', 'ch': 'щ'}}
" }}}
" }}}
" elseif s:IsLong(a:strans, s:uchar)
elseif has_key(a:strans, "END")
" {{{ Следующий символ — не часть последовательности
return [s:uchar, a:strans["END"]]
" }}}
else
" {{{ Последовательность не обнаружена
return ["END:NotConverted,2,NoEND", s:uchar]
" }}}
endif
" }}}
" }}}
elseif has_key(a:strans, "END")
" {{{ Если она одна
return ["END:Converted,END", a:strans["END"]]
" }}}
endif
" {{{ Последовательность не обнаружена
return ["END:NotConverted,NoEND", s:uchar]
" }}}
endfunction
" }}}
" {{{ Основная функция
function Translit(trlang,tsource,…)
" {{{ Превращение массива в удобный скрипту вид
if !has_key(s:arrangedtrans,a:trlang)
let s:arrtrans=s:ArrangeTrans(a:trlang)
call extend(s:arrangedtrans,{a:trlang : s:arrtrans})
let s:arrtrans=copy(s:arrtrans)
else
let s:arrtrans=s:arrangedtrans[a:trlang]
endif
" }}}
" {{{ Объявление переменных
let s:ucr="END:EO.*" "На этом прерывается транслитерация
let s:ustring="" "Транслитерированная последовательность символов
let s:uch="END:Beginning" "Чтобы не входил в бесконечный цикл
let s:isupper=0 "По умолчанию символ в нижнем регистре
let s:index=0
let s:backchar=0 "По умолчанию символы не специальные
" }}}
" {{{ Второй и следуюшие аргументы
if a:tsource=="string"
" {{{ Ввод из строки символов
if a:0==0
echoerr "Недостаточно аргументов"
return ""
elseif a:0==1
let s:string=a:1
let s:getchar=function("s:GetcharFromString")
else
echoerr "Слишком много аргументов"
return ""
endif
" }}}
elseif a:tsource=="function"
" {{{ Ввод из пользовательской функции
" (задана символьной строкой)
if a:0==0
echoerr "Не задана функция"
elseif a:0==1
let s:getchar=function(a:1)
else
echoerr "Слишком много аргументов"
return ""
endif
" }}}
elseif a:tsource=="input"
" {{{ Ввод из командной строки
let s:string=input("Транслит: ")
let s:getchar=function("s:GetcharFromString")
" }}}
else
" {{{ Ошибка
echoerr "Неизвестная команда: ".a:tsource
return ""
" }}}
endif
" }}}
" {{{ Собственно, транслитерация
while s:uch!~s:ucr
" {{{ Если предыдущая последовательность закончилась
if s:uch=~"END:.*"
let s:uch=s:getchar()
" {{{ Сиволы со специальным значением
" {{{ Прерывание ввода
if s:uch=="\<C-c>" || s:uch=="\e"
break
" }}}
" {{{ Escape-последовательности
elseif s:uch=='\'
let s:gotch=s:getchar()
let s:uch="END:EscapeSeq"
continue
" }}}
" {{{ Пробел
elseif s:uch==" "
let s:ustring.=s:uch
let s:uch="END:Space"
continue
endif
" }}}
" }}}
endif
" }}}
" {{{ Транслитерация
if s:uch!~s:ucr
" {{{ Большие буквы
if s:uch=~'\u'
let s:uch=tolower(s:uch)
let s:isupper=1
endif
" }}}
" {{{ Если есть последовательность, начинающаяся на s:uch
if has_key(s:arrtrans,s:uch)
let s:ulist=s:GetSymb(s:arrtrans[s:uch])
" {{{ Большие буквы
if s:isupper
let s:ulist[1]=toupper(s:ulist[1])
let s:isupper=0
endif
" }}}
let s:ustring.=s:ulist[1]
let s:uch=s:ulist[0]
continue
endif
" }}}
" {{{ Если её нет, то надо провести обратную конвертацию регистра
if s:isupper
let s:uch=toupper(s:uch)
let s:isupper=0
endif
" }}}
let s:ustring.=s:uch
let s:uch="END:NoSymb"
continue
" }}}
else
break
endif
endwhile
" }}}
return s:ustring
endfunction
" }}}
" {{{ Печать таблицы транслитерации
function ReturnTranslitTable(trlang)
let s:rd={}
let s:returnedstring=""
for s:key in keys(a:trlang)
if !has_key(s:rd, a:trlang[s:key])
call extend(s:rd, {a:trlang[s:key]: []})
endif
call add(s:rd[a:trlang[s:key]], s:key)
endfor
let s:max=0
for s:key in keys(s:rd)
if strlen(s:key)>s:max
let s:max=strlen(s:key)
endif
endfor
let s:keys=sort(keys(s:rd))
for s:key in s:keys
let s:returnedstring.=printf("%*s : %s\n", s:max, s:key, s:rd[s:key][0])
let s:rd[s:key]=s:rd[s:key][1:-1]
for s:val in s:rd[s:key]
let s:returnedstring.=printf("%*s %s\n", s:max, " ", s:val)
endfor
endfor
return s:returnedstring
endfunction
" }}}
" vim: fenc=utf-8:ts=4