aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--japanese.vim103
1 files 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! \<Esc>"
+ 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