From a65307e2f92528944aabbdee98fc2d9adf912ce5 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sat, 6 Jul 2024 14:08:35 +0200 Subject: Various --- japanese.vim | 103 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 28 deletions(-) diff --git a/japanese.vim b/japanese.vim index 62f0726..ac1c882 100644 --- a/japanese.vim +++ b/japanese.vim @@ -39,8 +39,26 @@ const s:punctuation = { \ "?": "?", \ } -" const s:hiragana_string = "かきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもやゆよらりるれろわゐゑを" -" const s:katakana_string = "カキクケコガギグゲゴサシスセソザジズゼゾタチツテトダヂヅデドナニヌネノハヒフヘホバビブベボパピプペポマミムメモヤユヨラリルレロワヰヱヲ" +let s:hira2kata = {} +let s:kata2hira = {} +let s:hira2id = {} +let s:id2hira = [] +function s:filltables() + let i = 0 + for ln in readfile("table.txt") + let words = split(ln, " ") + let s:hira2kata[words[0]] = words[1] + let s:kata2hira[words[1]] = words[0] + let s:hira2id[words[0]] = i + call add(s:id2hira, words[0]) + let i += 1 + endfor +endfunction +call s:filltables() +lockvar! s:hira2kata +lockvar! s:kata2hira +lockvar! s:hira2id +lockvar! s:id2hira function s:renderkana(s, kanamode) if len(a:s) == 0 @@ -74,10 +92,15 @@ function s:renderkana(s, kanamode) elseif s:isconsonant(c0) && s:isvowel(c1) && index(s:nokana_digraph, c0 .. c1) == -1 let result ..= hira ? digraph_get(c0 .. c1) : digraph_get(toupper(c0) .. c1) let i += 2 + " v-dakuten kana + elseif c0 ==# "v" && s:isvowel(c1) + let kata = digraph_get("V" .. c1) + let result ..= hira ? s:kata2hira[kata] : kata + let i += 2 " glide elseif s:isconsonant(c0) && c1 ==# "y" && s:isvowel(c2) let result ..= hira ? digraph_get(c0 .. "i") : digraph_get(toupper(c0) .. "i") - let result ..= hira ? digraph_get("y" .. toUpper(c2)) : digraph_get("Y" .. toUpper(c2)) + let result ..= hira ? digraph_get("y" .. toupper(c2)) : digraph_get("Y" .. toupper(c2)) let i += 3 " normal n elseif c0 ==# "n" && c1 ==# "n" @@ -88,9 +111,13 @@ function s:renderkana(s, kanamode) let result ..= (hira ? "ん" : "ン") let i += 1 " geminated consonant - elseif s:isconsonant(c0) && s:isconsonant(c1) + elseif s:isconsonant(c0) && c0 ==# c1 let result ..= (hira ? "っ" : "ッ") let i += 1 + " small vowel + elseif (c0 ==# "x" || c0 ==# "l") && s:isvowel(c1) + let result ..= hira ? digraph_get(toupper(c1) .. "5") : digraph_get(c1 .. "6") + let i += 2 " sokuon elseif c0 == "-" let result ..= "ー" @@ -109,18 +136,28 @@ function s:renderkana(s, kanamode) return result endfunction -" matchid: ID of the match() region +function s:make_region_match(region) + const ln = getline(a:region.y_1) + const prefix = strcharpart(ln, 0, a:region.x1_1 - 1) + const infix = strcharpart(ln, a:region.x1_1 - 1, a:region.x2_1 - a:region.x1_1) + return matchaddpos("JapaneseVimFragment", [[a:region.y_1, strlen(prefix) + 1, strlen(infix)]]) +endfunction + " y_1: 1-based line number of the region -" x1_1: 1-based x of start of region, inclusive -" x2_1: 1-based x of end of region, exclusive +" x1_1: 1-based x (chars) of start of region, inclusive +" x2_1: 1-based x (chars) of end of region, exclusive " kanamode: 1 for hiragana, 2 for katakana -function s:make_region(matchid, y_1, x1_1, x2_1, kanamode) - return #{matchid: a:matchid, - \ y_1: a:y_1, - \ x1_1: a:x1_1, - \ x2_1: a:x2_1, - \ kanamode: a:kanamode, - \ } +" +" Additional automatic fields: +" matchid: ID of the match() region +function s:make_region(y_1, x1_1, x2_1, kanamode) + let d = #{y_1: a:y_1, + \ x1_1: a:x1_1, + \ x2_1: a:x2_1, + \ kanamode: a:kanamode, + \ } + let d.matchid = s:make_region_match(d) + return d endfunction " The fragment currently being typed and formatted. @@ -134,6 +171,17 @@ function s:terminate_region() endif endfunction +function s:refresh_region_matchid() + if s:cur_region.matchid > 0 + call matchdelete(s:cur_region.matchid) + endif + + const ln = getline(s:cur_region.y_1) + const prefix = strcharpart(ln, 0, s:cur_region.x1_1 - 1) + const infix = strcharpart(ln, s:cur_region.x1_1 - 1, s:cur_region.x2_1 - s:cur_region.x1_1) + let s:cur_region.matchid = matchaddpos("JapaneseVimFragment", [[s:cur_region.y_1, strlen(prefix) + 1, strlen(infix)]]) +endfunction + function s:handle_keypress(key) " call s:insert_at_cursor("key " .. a:key) const y_1 = line(".") @@ -170,42 +218,41 @@ function s:handle_keypress(key) call setcursorcharpos(y_1, newx_1) if s:cur_region is v:null - const startcol = x - input_extra_chars - const matchid = matchaddpos("JapaneseVimFragment", [[y_1, strlen(strcharpart(fullline, 0, startcol)) + 1, strlen(result)]]) - let s:cur_region = s:make_region(matchid, y_1, startcol + 1, newx_1, 1) + let s:cur_region = s:make_region(y_1, x + 1 - input_extra_chars, newx_1, 1) else - call matchdelete(s:cur_region.matchid) let s:cur_region.x2_1 += strcharlen(result) - input_extra_chars - const reglen = len(strcharpart(getline("."), s:cur_region.x1_1 - 1, s:cur_region.x2_1 - s:cur_region.x1_1)) - let s:cur_region.matchid = matchaddpos("JapaneseVimFragment", [[s:cur_region.y_1, strlen(strcharpart(getline("."), 0, s:cur_region.x1_1 - 1)) + 1, reglen]]) + call s:refresh_region_matchid() endif endfunction function s:convert_region_kana(tokanamode) if s:cur_region is v:null - " Sound a bell - execute "normal! \" + const x_1 = charcol(".") + let s:cur_region = s:make_region(line("."), x_1, x_1, a:tokanamode) return endif const ln = getline(s:cur_region.y_1) const s = strcharpart(ln, s:cur_region.x1_1 - 1, s:cur_region.x2_1 - s:cur_region.x1_1) let result = "" - " TODO: this conversion is not complete, but it gets the most important kana. for c in s - let n = char2nr(c) " hiragana -> katakana - if a:tokanamode == 2 && strcharlen(c) == 1 && 0x3041 <= n && n <= 0x3096 - let result ..= nr2char(n + (0x30A0 - 0x3040)) + if a:tokanamode == 2 + let result ..= get(s:hira2kata, c, c) " katakana -> hiragana - elseif a:tokanamode == 1 && strcharlen(c) == 1 && 0x30A1 <= n && n <= 0x30F6 - let result ..= nr2char(n + (0x3040 - 0x30A0)) + elseif a:tokanamode == 1 + let result ..= get(s:kata2hira, c, c) else let result ..= c endif endfor call setline(s:cur_region.y_1, strcharpart(ln, 0, s:cur_region.x1_1 - 1) . result . strcharpart(ln, s:cur_region.x2_1 - 1)) + if strcharlen(s) != strcharlen(result) + let s:cur_region.x2_1 += strcharlen(result) - strcharlen(s) + call s:refresh_region_matchid() + " TODO: move cursor appropriately + endif let s:cur_region.kanamode = a:tokanamode endfunction -- cgit v1.2.3-70-g09d2