Windows用コマンドラインシェル「NYAGOS」を使い始めたのですが、カーソルキーを多用する私の使い方だと、若干操作に悩ましい部分があったので、拡張してみました。
やりたいこと
- コマンドラインで1単語単位で左右に移動したい
- 上記を「CTRL+←」、「CTRL+→」で実現したい
- NYAGOS単体ではなくて、conemuから動かすことを想定
参考にした解説記事
- ConEmu + nyagos で Windows ターミナル環境を作る
- 2015年版ぼくがかんがえたさいきょうのWindowsターミナル+シェル構成
- ようやく ConEmu と NYAGOS を導入した
NYAGOSのマニュアルを見る
- Lua拡張ができるとのことで、何ができるかを確認したところ、一文字単位の左右移動はLua側からできるようです。
- 単語単位の情報は引数として渡ってきていないっぽいので、現在位置と動かしたい位置までを一文字ずつ移動させる手段が簡単そうです。文字列が多くなると重くなるかもしれませんが。
- もう一つ問題は、バインド可能なキーの組み合わせが少なくて、CTRL+矢印とかバインドできないことです。これは後でconemu側でフックさせます。
NYAGOSでLua拡張
- 左に動かす(戻る方向)は、現在位置から文字列を逆向きに調べて、最初に見つけたスペースまで移動できればいいのですが、Luaはrfind(逆向きサーチ)がなくて、まずそこで詰まりました。
- stackoverflow先生によると、最長マッチでやりたいことができるよ!とのことで、なるほどと思いました。
- 正規表現で()とすると、その位置をindex番号で戻すというのはLuaの仕様なんですね。
- 右に動かす(進む方向)は簡単で、そのままfind使えばいけました。
- スペースがない場合は、最初か最後まで進むことにしています。
- バインドキーの割当は、私が使わないであろうキーとして「M_A(ALT+A)」,「M_B(ALT+B)」に割り当てています。
wordmove.lua
-- ref) http://stackoverflow.com/questions/17386792/how-to-implement-string-rfind-in-lua
nyagos.bindkey("M_A",
function(this)
local pos = (this.text:sub(1,this.pos-1)):match'.*() '
if pos and (pos < this.pos) then
for i = 1, this.pos-pos do
this:call("BACKWARD_CHAR")
end
else
this:call("BEGINNING_OF_LINE")
end
return nil
end
)
nyagos.bindkey("M_B",
function(this)
local pos = this.text:find(' ',this.pos+1)
if pos and (pos > this.pos) then
for i = 1, pos-this.pos do
this:call("FORWARD_CHAR")
end
else
this:call("END_OF_LINE")
end
return nil
end
)
conemuでHotkeyマクロを使う
- conemuのHotKeyを使えばNYAGOSで割り当てたバインドキーを、別のキーアサインで実現することができます。
- conemuの「Keys & Macro」で、空いているところ(Macro01とか)にHotkeyを割り当てます。
- Hotkeyを
ctrl+LEFT
として、GUI Macroに、Keys("!a")
とします。!a
=ALT+AでNYAGOSだとM_A
に相当します。 - Hotkeyを
ctrl+RIGHT
として、GUI Macroに、Keys("!b")
とします。!b
=ALT+BでNYAGOSだとM_B
に相当します。 - これで、conemuから「ctrl+←」と入力すると、ALT+AがNYAGOSに送られて、設定したバインドキーで動作するという流れになります。