MicroPythonのREPLをOLED出力(改良版)

以前作成した、MicroPythonのREPLをOLEDに出力するツールを少し改良し、以前はできなかった行の途中での編集の表示ができるようにしました。今回は動作はESP32-DevKitCで確認しています。

改良版は以下のリポジトリにアップロードしてあります。

boochow/FBConsole: frame buffer console class for MicroPython

古い版では、矢印キーをサポートしていないため、

・矢印キーでカーソルを左に移動すると、カーソルより右の字が消える
・その後、行の途中に字を挿入すると表示がおかしくなる

といった不具合がありました。

実装としては制御文字は改行とバックスペースだけをサポートし、エスケープシーケンスは読み飛ばしていました。
また、バックスペース(BS)を受信したときに文字を消去していました(実際には、消去せずにカーソルを移動するのが正しい)。

今回、実際にREPLで用いられているエスケープシーケンスを調べてみたところ、

・ESC [ K  ・・・ カーソルのいる行のカーソルより右側から行末までを消去
・ESC [ n D ・・・ n文字分、カーソルを左へ移動する

の二つが重要であることが分かったので、これらのみサポートを追加しました。

たとえば、行の途中に1文字を追加する場合は、

1)カーソルより行末までを消去
2)追加する文字を出力
3)その後から行末までを出力
4)行末から元のカーソル位置まで、Backspace(4文字以内の場合)またはESC[nD(5文字以上の場合)で戻る

という処理になっていました。

これらの処理はMicroPythonの内部では、micropython/lib/mp-readline/readline.cで行われているのですが、実装を見ても実際に送られるシーケンスがよく判りませんでした。

そこで、FBConsoleを元に、REPLで出力される文字コードを16進数でOLEDにダンプするコードを作り、これを使ってシーケンスを観察しました。

この例は、REPLで”0000″という文字列が入力された状態で、その先頭に”1″を追加し、さらにカーソルを左へ1文字動かして先頭に”2″を追加しています。

コード08はBSです。
2行目が”1″を追加した際に端末へ出力されたデータです。
「31 30 30 30 30 08 08 08 08」は”10000″を表示後にBSを4回送っていますので、カーソルが”1″と”0″の間に来ます。
そのあと左矢印キーを入力したので、BSが1回送られて、カーソルが”1″の前に来ます。
次に、”2″を入力したので、「32 31 30 30 30 30 」で”210000″を表示し、その後「1B 5B 35 44」はESC + “[5D”ですのでカーソルを5文字左へ移動して”2″と”1″の間に来ています。

以下に、このダンプを表示するクラス(DumpConsole)を載せておきます。
使い方はFBConsoleと全く同じで、OLEDにはwriteリクエストごとに1行ずつ、16進ダンプが表示されます。

コメント