今年に入ってついにGithub Copilotに課金しちゃったので、環境をnvim+copilotに移行することにしました。
nvimベースにするとnvimの中だけで完結するskkeletonというSKKのIMEが動くので、以前挫折したSKKを再度試してみたくなり導入してみました。
SKKが使えるようになればMozcが入れにくいDistributionでも(Mozcはいいぞ!)nvim内であれば日本語が簡単に使えます。
導入が終わったのでSKKの試運転としてSKKだけ(Copilotにだいぶ補完してもらいながら)でSKKの導入手順を書いてみます。
skkeletonを導入
Geminiさんにお勧めされたのでskkeletonというプラグインを導入しました。
プラグインの管理にはLazyvimを使うようにしています。dotfilesから.config/nvimを持って来ればおしまいなので、環境の変化に強いと思います。
まずはDenoのインストール
dnfになかったのであれ?って思ったら久々のシェルスクリプトインストールでした。
$ curl -fsSL https://deno.land/install.sh | sh
適当にポチポチ進めてたら.bashrcの最後に以下の行が追加されていました。
. "/home/<user_name>/.deno/env"
なので、後はsourceしてあげればOKです。
$ source ~/.bashrc
これでDenoが使えるようになったのでnvimから使えるようdenops.vimを導入します。
-- Setup lazy.nvim
require("lazy").setup({
spec = {
-- その他のプラグイン ...
-- denops.vim (skkeletonを動かすための基盤)
{ "vim-denops/denops.vim" },
skkeletonの導入
Denoが入ったので次にskkeleton本体を導入します。
require("lazy").setup({
spec = {
-- skkeleton本体
{
"vim-skk/skkeleton",
dependencies = { "vim-denops/denops.vim" },
event = "VeryLazy",
},
大きい変換辞書を使いたいのでnvimの起動時に読み込み待ちしないよう遅延ロードにしておきました。
続いてコンフィグ。eventの設定の下にconfigを追加します。
-- skkeletonの設定
config = function()
vim.fn["skkeleton#config"]({
globalDictionaries = {
{ "/home/<user_name>/.config/skk/SKK-JISYO.L", "euc-jp" },
{ "/home/<user_name>/.config/skk/kaomoji.skk", "utf-8" }
},
-- サーバー版SKKを使う場合の設定
-- sources = { 'skk_server' },
-- skkServerHost = '127.0.0.1',
-- skkServerPort = 1178,
eggLikeNewline = true,
registerConvertResult = true,
showCandidatesCount = 2,
})
-- Ctrl-j でskkを有効に
vim.keymap.set({ "i", "c" }, "<C-j>", "<Plug>(skkeleton-enable)", { noremap = false })
vim.keymap.set('n', '<C-j>', 'i<Plug>(skkeleton-enable)', { remap = true, silent = true })
end,
- globalDictionariesでSKK辞書のパスを指定しています。GoogleIMEでずっと育てている顔文字辞書もしっかり(変換して)導入!( ー`дー´)キリッ
- サーバの部分はSKKサーバーを使う場合の設定です。今回はローカル辞書だけで動かすのでコメントアウトしています。
なおskkeletonはSKKサーバに対してEucjpで通信するのでSKKサーバーを立てる場合はEucjp対応にしておく必要があります。 - その他お好みで(Geminiさんとかにお勧めを聞いてみて下さい)
ここで肝なのがC-jの設定で、insert/commandモードだけでなくnormalモードでもC-jでskkeletonを有効にするようにしています。これだけでグッと日本語が入力しやすくなります。
そして最後にローマ字入力のカスタマイズを行います。
デフォルトではlがSKKの無効化キーになっているのですが、私はぁぃぅぇぉっをlから入力するので無効化キーをcに変更しました。
lは小さい仮名入力に使いたいのでテーブルの修正を行なっておきます。
-- lでdisableだったのをl系の仮名入力に変更
vim.fn['skkeleton#register_kanatable']('rom', {
l = { 'l' },
la = { 'ぁ' },
li = { 'ぃ' },
lu = { 'ぅ' },
le = { 'ぇ' },
lo = { 'ぉ' },
ltu = { 'っ' },
}, true)
-- 無効化キーをlからcに変更
vim.fn['skkeleton#register_keymap']('input', 'c', 'disable')
lualineの設定
lualineを使っている場合、skkeletonの状態を表示するように設定しておくと便利です。
「あ」や「ア」や「A」とか1文字表示がいいとのことですが、個人的に文字列のステートはそのまま出すタイプです。
sections = {
lualine_x = {
{
-- skkeletonの状態表示
cond = function()
return vim.fn['skkeleton#is_enabled']()
end,
function()
return vim.fn['skkeleton#mode']()
end,
color = { fg = '#ff9e64', gui = 'bold' }, -- オレンジ色で目立たせる
},
'encoding', 'fileformat', 'filetype'
},
},
SKKのモードはどこにも表示されないので、なんらかの方法でステータスバーなりに表示しておく必要があります。
意外に書けるぞ!
ここまで書いてみて……SKK意外に書けるな!
各モード移行は次の通り。
| モード | 備考 | キー |
|---|---|---|
| ひらがなモード | 他のモードの終了にも使う | Ctrl+j |
| 全角カナモード | 変換前だとモード変更、後だと全角カナ変換 | q |
| 半角カナモード | 変換前だとモード変更、後だと半角カナ変換 | Ctrl+q |
| 全角英数モード | Shift+j | |
| 半角英数モード | は無いので終了させる | c |
| abbrevモード | 登録した略語を展開するモード | / |
| stikyモード | 強制変換モード | ; |
| 入力終了 | VIMのノーマルモードへ | Esc |
顔文字辞書が@始まりなのでSKKの大文字始まりが変換対象というルールとかみあいません。が、;を打つとstikyモードという強制変換モードになるのでその後@キーを押せば@始まりの顔文字辞書が使えます。
まだ顔文字辞書の移行中……
基本は、読み/変換1/変換2/...なのですが、途中に/が入るとさぁ大変。エスケープ……え?まじ?concat でごにょごにょやるしかない……え?skkeletonはconcatもダメ?
使えない文字の入った顔文字抜くしかないのね(´;ω;`)ブワッ
とりあえずGoogleIMEの辞書をExportして、/の入ったエントリを抜いたSKKの辞書作るスクリプト
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
const ConvertFile = "./gjisyo.txt"
// open text file and read contents from os package
file, err := os.Open(ConvertFile)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
// read lines from file with bufio.Scanner
lines := []string{}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
lines = append(lines, line)
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading file:", err)
}
// make string array dict
dict := make(map[string][]string)
// split tab-separated values into lines
containsChecks := []string{"/"}
for _, line := range lines {
values := strings.Split(line, "\t")
if len(values) > 1 {
// check contains_chesks
contains := false
for _, check := range containsChecks {
if strings.Contains(values[1], check) {
contains = true
break
}
}
if contains {
continue
}
// append dict with key as first element and value as second element
key := values[0]
dict[key] = append(dict[key], values[1])
}
}
// print skk header ;; okuri-nasi entries.
fmt.Println(";; okuri-nasi entries.")
// print dict
for key, value := range dict {
// print /value/
fmt.Printf("%s /%s/\n", key, strings.Join(value, "/"))
}
}
;@namidaで変換……
ヨシッ!(゚∀゚)
