本稿は自作エディタをつくる Advent Calendar 2016の13日目です、レポジトリはこちら
文字を挿入後にカーソルを1つ後ろにずらす
12日目の積み残しです。ずらしました。
カーソル位置をチェックする
現状の動作だと、カーソルをマイナス3文字目とかに動かせてしまうので、簡単にセグフォが起こせてしまいます。
12日目の保持しているカーソルの位置と、実際のカーソル位置がズレたほうが使いやすそう
問題は、後で考えることにして
いったんセグフォが起きない位置にしかカーソルを動かせないようにします。
ちょっと困ったのはunsigned int
の挙動です。
unsigned int x = 0; x--;
は、コンパイルが通るし、これだけではランタイムエラーにならないです。
unsigned int x = 0; x--;if(x<0) {x=0;}
は、コンパイルで怒られます。
エラー内容はcomparison of unsigned expression < 0 is always false
0未満にはならないよ、ですかね。
ちょっと著者がunsigned
に求めていたものと違うのですが、言われるとそうだよねって感じです。
今回はカーソル位置はたまたま1始まりなのでx<1
にしましたが、設計時点で色々考えればよかった気がします。
教訓として、unsignedを使う時はエラーケースをどこにしまうか考えてからにしよう!って思いました。
余談として、charをunsignedにするとprintfのときは便利ですが、signedのほうがstrcpy等が使いやすいので、指定してあればどちらでも良いのかもしれません。
全体的に、ちょっと型に理解が浅かったですね。
話を元に戻して、カーソル位置について
- 行の先頭より左に行けなくする
- ファイルの先頭より上に行けなくする
は自明ですが、
- 行の末尾より右に行けなくする
は12日目の保持しているカーソルの位置と、実際のカーソル位置がズレたほうが使いやすそう
問題があります
- ファイルの末尾より下に行けなくする
は、その通りでもいいし、空行を追加して下に行けるようにしてほしい派もいる気がします。
けっこうカーソル移動は奥が深いですね。好みの問題の気がするので、とりあえず実装が楽な方に倒します。
これでセグフォは起きなくなりました。
制御文字を入力する(十字キー)
9日目の十字キーの謎
より、十字キー文字コードは分かっているため(mac+bash環境調べ)
up = 0x1B,0x5B,0x41
down = 0x1B,0x5B,0x42
right = 0x1B,0x5B,0x43
left = 0x1B,0x5B,0x44
こんな感じで0x1B、0x5Bを特殊な状態として扱うことで、十字キーを入力できるようにしました。
if(key[0] == 0x1B && flag == NOT_CTRL) {
flag = ALLOW_1;
} else if (key[0] == 0x5B && flag == ALLOW_1) {
flag = ALLOW_2;
} else if (flag == ALLOW_2) {
if(key[0] == 0x41) cmd.command_key = UP;
if(key[0] == 0x42) cmd.command_key = DOWN;
if(key[0] == 0x43) cmd.command_key = RIGHT;
if(key[0] == 0x44) cmd.command_key = LEFT;
flag = NOT_CTRL;
} else {
flag = NOT_CTRL;
cmd.command_key = INSERT;
}
無事に動作したので、u/d/l/rキーの割り当ては無くします。
終了は、後述するCtrl+Qにしました。
制御文字を入力する(それ以外のキー)
ついでに、削除キー等の文字コードもprintfで調べます。
コメントは、どういう操作を割り当てたいかの希望です。
Backspace = 0x7F //文字削除
Esc = 0x1B //終了
Alt + LEFT = 0x1B,0x62 //行先頭へ
Alt + RIGHT = 0x1B,0x66 //行末尾へ
Alt + S = 0xC3 // 保存
Alt + Q = 0xC5 // 終了
Ctrl + S = 0x13 // 保存
Ctrl + Q = 0x11 // 終了
Shift + LEFT = 0x1B,0x5B,0x31,0x3B,0x32,0x44 //範囲選択
Shift + RIGHT = 0x1B,0x5B,0x31,0x3B,0x32,0x44 //範囲選択
Shift + UP / DOWN = 判別不能(Shiftを押さない時と同じ文字コードになる)
ALT + UP / DOWN = 判別不能(Shiftを押さない時と同じ文字コードになる)
Ctrl + 十字キー = 測定不能(Macのスクリーン移動に操作を取られる)
Cmd + 各種キー = 測定不能(Macの固有機能に操作を取られる)
後半の測定不能は、3日目の懸念事項だったものですが、Ctrl+十字キーも無理だとは・・・。
ちょっとショックです。
Escキーって、0x1Bなんですね。
後続に文字が来るかどうかは、現状の実装(getchar)だとわからないので、
十字キー(例:上キーは0x1B,0x5B,0x41)の先頭の0x1Bか、Escキーかはその時点で判断できません。
今の所困らないですが、Escキー単押しに機能を割り振るのは難しそうです。
先人(vi/emacs)の知恵を知る
そもそも、Alt+SはMacだとß
を打つためのキーバインドなので、奪って機能を割り振ってしまうとß
を打ちたい人が困ります。
じゃあCmdキーは・・・、となるとMac固有の機能と衝突するため割り振れません。
となると、Ctrl+何か
、Esc押した後に何か
、あたりが候補に挙がって・・・(๑•̀ㅁ•́๑)✧ ハッ!
まるで vi / emacs のキーバインドですね。(nanoもですね。)
あの変則的なキーバインドに不満を感じたのがエディタを作る動機の1つだったのですが、
どうやら似たキーバインドにたどり着きそうです。なるほど、こういう理由から、キーバインドが生まれたのですかね。
自分のエディタに対して、先人の知恵をなぞるか、新たな形を模索するか考えた方が良さそうです。
ctrl+十字キーさえ打てれば、ctrlで揃えるのもありかなと思ったのですが、ちょっと考えます。
今日のまとめ
- カーソル位置をチェックするようにしました
- vi/emacs/nanoの工夫を垣間見ました
長くなってきたので、文字を削除する
は明日に回します。
vi/emacsの変則的なキーバインドに不満を感じたのがエディタを作る動機の1つだったのですが、
どうやら似たキーバインドにたどり着きそうです
釈迦の掌の上で回ってる気分ですね・・・。なるほどなぁ。
前回分のコメント(自動テストに関して)ありがとうございます。
まだ参照先を読みきれてないですが、単体テストはそろそろ入れないとつらいところ。