yasudacloudの日記

札幌に住むソフトウェアエンジニア

Flutterで自作ターミナル開発③ 実装&文字化け対応

少し日が空きましたが、前回に続いて実装編。

 

ライブラリはSSHとターミナルが同じ運営元になっている下記にします。

github.com

github.com

 

SSHターミナルはそれぞれのexampleを組み合わせれば最低限の機能を実現できますが、いくつかハマりそうなポイントがあるので具体的に解説していきます。

 

xterm - dartssh2の連携

SSH(dartssh2)の出力 shell.stdoutはStream<Uint8List>型ですが、ターミナル(xterm)の_outStreamはStream<String>と異なっています。

なので下記のようにキャストする一手間が必要です。

 

exampleのコード

final shell = await client.shell();
stdout.addStream(shell.stdout);

 

キャスト挟んだコード

_outStream.addStream(session.stdout.map<String>((event) {
return utf8.decode(event);
}));

 

日本語の文字化け

こちらもexample通り作ると日本語(というよりマルチバイト)が?に置き換わってしまいます。

xterm/sshdart2のコードやIssue、exampleを探してもそれっぽい情報が見当たらず。

マルチバイトがそもそも返ってきてるのかどうか確認しました。

_outStream.addStream(shell.stdout.map<String>((event) {
event.forEach((element) {
if (element >= 128) {
print(element);
}
});
return utf8.decode(event);
}));

しかし上記のifは通らず🤔

めんどくさくなって全部見てみます。

 

すると、

日本語の文字列の部分が63で返ってきており、63は?を表します(ASCIIコードを参照)。つまりxtermの問題ではないことが分かります。

 

しかし、Flutterのxtermだけで調べてると全然ヒットしなかったのでXtermのLocaleでぐぐると色々情報が出てきます。

shellの実行時に環境変数を渡すと良いようです。

final shell = await client.shell(pty: const SSHPtyConfig(
type: 'xterm-256color'
), environment: {
"LANG": "ja_JP.UTF-8",
});

 

Before


After


これで文字化け解消できました。

 

ここまでのアプリの動画収録。たいぽが多いが。。

https://assets.yasuda.cloud/term_capture.mp4

 

続く・・