⌨️

CorvusSKKのinit.luaをカスタマイズして変換候補を追加する

に公開
1

できるようになったこと

  • abbrevモードでCapital CaseとUPPER CASEの候補を出す

  • 郵便番号と住所をセットで変換する


    ハイフンが含まれていてもOK

  • SKKサーバ使用時にGoogle日本語入力APIが出してくる余計な候補を除外する


    本> 本> ポン> ポン> などの候補を出さない

やったこと

init.luaskk_search 関数をカスタムした。

local function to_skkdict_entry(t)
	local ret = ""
	if #t < 1 then
		return ret
	end
	for i = 1, #t do
		ret = ret .. "/" .. t[i]
	end
	return ret .. "/\n"
end

local function add_prefix_to_skkdict_entry(pref, ent)
	return string.gsub(ent, "/%C", function(m)
		return "/" .. pref .. string.sub(m, 2)
	end)
end

local function skk_search(key, okuri)
	local ret = ""

	-- ユーザー辞書検索
	ret = ret .. crvmgr.search_user_dictionary(key, okuri)

	-- SKK辞書検索
	local from_skk_dict = crvmgr.search_skk_dictionary(key, okuri)
	ret = ret .. from_skk_dict

	-- 郵便番号変換(郵便番号SKK辞書は数字7桁)
	if 0 < string.len(from_skk_dict) and string.match(key, "^%d%d%d%d%d%d%d$") then
		local pref = string.sub(key, 1, 3) .. "-" .. string.sub(key, 4) .. " "
		ret = ret .. add_prefix_to_skkdict_entry(pref, from_skk_dict)
	end
	if string.match(key, "^%d%d%d%-%d%d%d%d$") then
		local k = string.gsub(key, "-", "")
		local s = crvmgr.search_skk_dictionary(k, okuri)
		if 0 < string.len(s) then
			local pref = key .. " "
			ret = ret .. add_prefix_to_skkdict_entry(pref, s)
		end
	end

	-- Capital Case と UPPER CASE を追加
	if string.match(key, "^[a-z]+$") then
		local c = string.upper(string.sub(key, 1, 1)) .. string.sub(key, 2)
		ret = ret .. to_skkdict_entry({c, string.upper(key)})
	end

	--[[
		SKK辞書サーバー検索
		- 英数から始まる場合、接辞の>で終わる場合は Google 日本語入力 CGI APIへの問い合わせを除外する。
		- crvskkserv.ini で正規表現を書く方法もあるが、設定の一元管理のために init.lua で設定しておく。
	--]]
	if not string.match(key, "^[a-zA-Z0-9#].+") then
		local tail = string.sub(key, string.len(key))
		if tail ~= ">" then
			ret = ret .. crvmgr.search_skk_server(key)
		end
	end

	if (okuri == "") then
		-- Unicodeコードポイント変換
		ret = ret .. crvmgr.search_unicode(key)

		-- JIS X 0213面区点番号変換
		ret = ret .. crvmgr.search_jisx0213(key)

		-- JIS X 0208区点番号変換
		ret = ret .. crvmgr.search_jisx0208(key)

		local cccplen = string.len(charcode_conv_prefix)
		if (cccplen < string.len(key) and string.sub(key, 1, cccplen) == charcode_conv_prefix) then
			local subkey = string.sub(key, cccplen + 1)

			-- 文字コード表記変換
			ret = ret .. crvmgr.search_character_code(subkey)
		end
	end

	-- 余計な"/\n"を削除
	ret = string.gsub(ret, "/\n/", "/")

	return ret
end
オリジナルとの差分
+ local function to_skkdict_entry(t)
+ 	local ret = ""
+ 	if #t < 1 then
+ 		return ret
+ 	end
+ 	for i = 1, #t do
+ 		ret = ret .. "/" .. t[i]
+ 	end
+ 	return ret .. "/\n"
+ end

+ local function add_prefix_to_skkdict_entry(pref, ent)
+ 	return string.gsub(ent, "/%C", function(m)
+ 		return "/" .. pref .. string.sub(m, 2)
+ 	end)
+ end

local function skk_search(key, okuri)
	local ret = ""

	-- ユーザー辞書検索
	ret = ret .. crvmgr.search_user_dictionary(key, okuri)

	-- SKK辞書検索
- 	ret = ret .. crvmgr.search_skk_dictionary(key, okuri)
+	local from_skk_dict = crvmgr.search_skk_dictionary(key, okuri)
+	ret = ret .. from_skk_dict

+	-- 郵便番号変換(郵便番号SKK辞書は数字7桁)
+	if 0 < string.len(from_skk_dict) and string.match(key, "^%d%d%d%d%d%d%d$") then
+		local pref = string.sub(key, 1, 3) .. "-" .. string.sub(key, 4) .. " "
+		ret = ret .. add_prefix_to_skkdict_entry(pref, from_skk_dict)
+	end
+	if string.match(key, "^%d%d%d%-%d%d%d%d$") then
+		local k = string.gsub(key, "-", "")
+		local s = crvmgr.search_skk_dictionary(k, okuri)
+		if 0 < string.len(s) then
+			local pref = key .. " "
+			ret = ret .. add_prefix_to_skkdict_entry(pref, s)
+		end
+	end

+	-- Capital Case と UPPER CASE を追加
+	if string.match(key, "^[a-z]+$") then
+		local c = string.upper(string.sub(key, 1, 1)) .. string.sub(key, 2)
+		ret = ret .. to_skkdict_entry({c, string.upper(key)})
+	end

-	-- SKK辞書サーバー検索
-	ret = ret .. crvmgr.search_skk_server(key)
+	--[[
+		SKK辞書サーバー検索
+		- 英数から始まる場合、接辞の>で終わる場合は Google 日本語入力 CGI APIへの問い合わせを除外する。
+		- crvskkserv.ini で正規表現を書く方法もあるが、設定の一元管理のために init.lua で設定しておく。
+	--]]
+	if not string.match(key, "^[a-zA-Z0-9#].+") then
+		local tail = string.sub(key, string.len(key))
+		if tail ~= ">" then
+			ret = ret .. crvmgr.search_skk_server(key)
+		end
+	end

	if (okuri == "") then
		-- Unicodeコードポイント変換
		ret = ret .. crvmgr.search_unicode(key)

		-- JIS X 0213面区点番号変換
		ret = ret .. crvmgr.search_jisx0213(key)

		-- JIS X 0208区点番号変換
		ret = ret .. crvmgr.search_jisx0208(key)

		local cccplen = string.len(charcode_conv_prefix)
		if (cccplen < string.len(key) and string.sub(key, 1, cccplen) == charcode_conv_prefix) then
			local subkey = string.sub(key, cccplen + 1)

			-- 文字コード表記変換
			ret = ret .. crvmgr.search_character_code(subkey)
		end
	end

	-- 余計な"/\n"を削除
	ret = string.gsub(ret, "/\n/", "/")

	return ret
end

以下、解説。

解説

公式ソースコードのコメントにも書いてあるように、 skk_search/<C1><;A1>/<C2><;A2>/.../<Cn><;An>/\n という形式の文字列を返す。

https://github.com/nathancorvussolis/corvusskk/blob/4170dd35762f49e196aeb7255de186fd57f09ba9/installer/config-lua/init.lua#L1123-L1127

変換時にはこの文字列を / で区切った各見出し語が表示されている。

つまり下図の場合は /阿;阿呆/婀;婀娜っぽい/痾;宿痾/唖;聾唖/……/\n という文字列が返されている。

ので、この形式に沿うように文字列を整形してやればいい。
そのために関数を2つ追加する。

-- テーブルで渡した見出し語を辞書形式に変換する
local function to_skkdict_entry(t)
	local ret = ""
	if #t < 1 then
		return ret
	end
	for i = 1, #t do
		ret = ret .. "/" .. t[i]
	end
	return ret .. "/\n"
end

to_skkdict_entry({"あ", "い"})/あ/い/\n となる。

-- エントリの各見出し語の先頭に任意の文字列を追加する
local function add_prefix_to_skkdict_entry(pref, ent)
	return string.gsub(ent, "/%C", function(m)
		return "/" .. pref .. string.sub(m, 2)
	end)
end

add_prefix_to_skkdict_entry("hoge", "/あ/い/\n") とすると出力は /hogeあ/hogeい/\n

正規表現で置換しているのは、たとえば 9610000 /福島県白河市/福島県西白河郡西郷村/ のように1つの郵便番号が複数の見出し語をもつケースが存在するため。

abbrevモードでCapital CaseとUPPER CASEの候補を出す

-- Capital Case と UPPER CASE を追加
if string.match(key, "^[a-z]+$") then
	local c = string.upper(string.sub(key, 1, 1)) .. string.sub(key, 2)
	ret = ret .. to_skkdict_entry({c, string.upper(key)})
end

skk_search の引数の key にはユーザー入力した文字列。
これがすべてアルファベットだったとき(poyo)、1文字目を大文字にしたCapital Caseの見出し語(Poyo)と全部大文字にしたUPPER CASEの見出し語(POYO)を追加している。

郵便番号と住所をセットで変換する

郵便番号辞書を追加すると数字7桁で住所に変換できるようになる。

しかし辞書の見出し語は 東京都葛飾区 のような住所表記のみなので、Google日本語入力のように 124-0000 東京都葛飾区 というセットで変換することができない。

そこで、SKK辞書検索のプロセスにひと手間加える。

-- SKK辞書検索
local from_skk_dict = crvmgr.search_skk_dictionary(key, okuri)
ret = ret .. from_skk_dict

if 0 < string.len(from_skk_dict) and string.match(key, "^%d%d%d%d%d%d%d$") then
	local pref = string.sub(key, 1, 3) .. "-" .. string.sub(key, 4) .. " "
	ret = ret .. add_prefix_to_skkdict_entry(pref, from_skk_dict)
end

ローカルのSKK辞書を検索して、郵便番号にヒットすれば add_prefix_to_skkdict_entry() で郵便番号(3桁-4桁フォーマット)を先頭に追加する。

コピペしてきた郵便番号を再変換するケースにも対応。

if string.match(key, "^%d%d%d%-%d%d%d%d$") then
	local k = string.gsub(key, "-", "")
	local s = crvmgr.search_skk_dictionary(k, okuri)
	if 0 < string.len(s) then
		local pref = key .. " "
		ret = ret .. add_prefix_to_skkdict_entry(pref, s)
	end
end

この場合は - を除いた7桁の郵便番号で辞書を再検索し、結果に追加している。

SKKサーバ使用時にGoogle日本語入力APIが出してくる余計な候補を除外する

SKKサーバーはGoogle日本語入力APIに問い合わせるため、英数・記号を全角化した見出し語も候補に挙げてくる。

たとえば td で現在の日付を実行変換するようにしていたときにも td を候補として出してきたり、接辞変換で ぽん> としたときに 本> 本> ポン> ポン> といった記号を全角化した候補を挙げてくるなど、ノイズが混じってしまう。

そこで、ユーザーの入力が英数から始まるもしくは > で終わる場合はサーバーに問い合わせないように条件分岐を設ける。

if not string.match(key, "^[a-zA-Z0-9#].+") then
	local tail = string.sub(key, string.len(key))
	if tail ~= ">" then
		ret = ret .. crvmgr.search_skk_server(key)
	end
end

SKKサーバーの設定で 見出し語の検索除外条件 をカスタムすることもできるが、正規表現がどんどん複雑になるうえに管理すべきファイルを増やしたくないのでこの方針で。


最新:

https://github.com/AWtnb/CorvusSKK

1

Discussion