-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
k.vim
148 lines (118 loc) · 3.36 KB
/
k.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
function! s:capital(char) abort
return substitute(a:char, '.', '\U\0', '')
endfunction
function! s:is_capital(char) abort
return '[A-Z]' =~# a:char
endfunction
let s:kana_start_pos = [0, 0]
let s:is_enable = v:false
let s:keys_to_remaps = []
let s:keys_to_unmaps = []
function! k#is_enable() abort
return s:is_enable
endfunction
function! k#enable() abort
if s:is_enable
return ''
endif
let s:keys_to_remaps = []
let s:keys_to_unmaps = []
for k in extendnew(s:start_keys, s:end_keys)->keys()
let current_map = maparg(k, 'i', 0, 1)
if empty(current_map)
call add(s:keys_to_unmaps, k)
else
call add(s:keys_to_remaps, current_map)
endif
execute $"inoremap <expr> {k} k#ins('{k}')"
if k =~ '\l'
execute $"inoremap <expr> {s:capital(k)} k#ins('{k}',1)"
endif
endfor
inoremap <expr> <space> k#henkan(" ")
call add(s:keys_to_unmaps, "<space>")
inoremap <expr> <cr> k#kakutei("\n")
call add(s:keys_to_unmaps, "<cr>")
let s:is_enable = v:true
return ''
endfunction
function! k#disable() abort
if !s:is_enable
return ''
endif
for m in s:keys_to_remaps
call mapset('i', 0, m)
endfor
for k in s:keys_to_unmaps
execute 'iunmap' k
endfor
let s:keys_to_remaps = []
let s:keys_to_unmaps = []
let s:is_enable = v:false
return ''
endfunction
function! k#toggle() abort
return k#is_enable() ? k#disable() : k#enable()
endfunction
function! k#initialize() abort
let raw = json_decode(join(readfile('./kana_table.json'), "\n"))
let s:start_keys = {}
let s:end_keys = {}
for [key, val] in items(raw)
let preceding_keys = slice(key, 0, -1)
let start_key = slice(key, 0, 1)
let end_key = slice(key, -1)
let s:start_keys[start_key] = 1
if !has_key(s:end_keys, end_key)
let s:end_keys[end_key] = {}
endif
let s:end_keys[end_key][preceding_keys] = val
endfor
endfunction
let s:henkan_start_pos = [0, 0]
function! k#ins(key, henkan = v:false) abort
let current_pos = getcharpos('.')[1:2]
if s:kana_start_pos[0] != current_pos[0] || s:kana_start_pos[1] > current_pos[1]
let s:kana_start_pos = current_pos
endif
if a:henkan
let s:henkan_start_pos = current_pos
endif
let kana_dict = get(s:end_keys, a:key, {})
if !empty(kana_dict)
let preceding_str = getline('.')->slice(s:kana_start_pos[1]-1, charcol('.')-1)
let i = len(preceding_str)
while i > 0
let tail_str = slice(preceding_str, -i)
if has_key(kana_dict, tail_str)
return repeat("\<bs>", i) .. kana_dict[tail_str]
endif
let i -= 1
endwhile
endif
return get(kana_dict, '', a:key)
endfunction
function! k#henkan(fallback_key) abort
let current_pos = getcharpos('.')[1:2]
if s:henkan_start_pos[0] != current_pos[0] || s:henkan_start_pos[1] > current_pos[1]
return a:fallback_key
endif
let preceding_str = getline('.')->slice(s:henkan_start_pos[1]-1, charcol('.')-1)
echomsg preceding_str
let s:henkan_start_pos = [0, 0]
return ''
endfunction
function! k#kakutei(fallback_key) abort
let current_pos = getcharpos('.')[1:2]
if s:henkan_start_pos[0] != current_pos[0] || s:henkan_start_pos[1] > current_pos[1]
return a:fallback_key
endif
let s:henkan_start_pos = [0, 0]
return ''
endfunction
augroup k_augroup
autocmd!
autocmd InsertLeave * call k#disable()
augroup END
call k#initialize()
inoremap <expr> <c-j> k#toggle()