GNU nanoの折り返しを全角対応にしてみる

GNU nanoを日本語で使う上で問題となるのが、全角の折り返しだったりする。

例えば80桁で折り返す設定にしている場合、80桁目に全角文字が来た時にはその文字はちゃんと折り返しされずに空白で表示されてしまう。日本語を扱う身としては非常に使い難い。

一般的なエディタではそのような場合、79桁目まで表示して全角文字を次の行に折り返すパターンが多いと思われるので、なんとかGNU nanoでもそのようにできないか、ソースを確認。

文字列の表示自体はupdate_lineで実施しているので、ソフトラップ時の処理を見てみると、COLSで単純に割っている。ここを1行に入る分だけ表示し、それ以降は次の行に折り返す処理に変更する。actual_xstrnlenptを使って実装した。

カーソルの表示はreset_cursorで行なっている。こっちは折り返しが発生する際の桁数を見て補正していく形で実装。ひとまず動きはするレベルの実装になってしまっているので要修正。

もうちょっとスマートに実装したいところではある。

GNU nano 2.7.0をAndroid用にコンパイルした。

GNU nano 2.7.0が9/1にリリースされている。

大きな変更は二つ。一つはShift+で範囲選択が出来るようになったこと、もう一つはGNU nano標準でターミナルの行数/列数が非常に小さい値を返すような場合に対応したこと。

前者はキーボードで選択するのが楽になったはず。Android Terminal Emulator(ATE)上では物理キーボードでないと恩恵が少ないかもだが。

後者は対応する意味がわからないと思うが、少なくともATE上では発生しうることであった。例えばATOKで文字入力している時に変換候補を上フリックすると、ATOKで全画面表示になるため、ATEの表示領域がなくなるので、2.6.3まではnano.c 697行目の

if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)

で引っかかってしまい、nanoが落ちてしまっていた。ここに引っかからないように、事前にCOLSとeditwinrowsを補正したパッチを書く必要があった。今回の2.7.0でそのパッチ部分が不要になった。

2.6.3で書いた他のパッチを適用して、ATE上で動くことを確認。

GNU nano2.6.3をAndroid Terminal Emulatorで日本語を打てるように

8/10にGNU nano2.6.3が公開された。今回のポイントはAlt+3でコメント化ができるようになったことだろう。Ctrl+矢印もそれなりに使い勝手が上がりそうである。

早速Build。一部関数名が違っていたりするのでパッチの修正はそのぐらい。相変わらずglobには対応させていない。

現状、自分がAndroid用にコンパイルしているncursesはja_JP.UTF-8を決め打ちで返すようにしてしまっている。自分が使う分にはまったく困らないのだけど、公開するとなると気が引けているのが実情。

とりあえず、パッチを当てるときに嵌まった点を列挙。

MB_MAX_LENとMB_CUR_LEN

日本語パッチを作ろうとして大嵌まりしたのはこれにつきる。NDKだと1なのよね。マルチバイトまわりをmusl実装で置き換えたときに期待通りに動かなくてかなり悩んだ。

再定義して事なきを得たけど、UTF-8環境では4か6か、どちらで定義するのかという問題がある。

本来5オクテット以上の表現は不正なのだから、4だというのはわかるのだけど、6オクテットまでは例えそれが不正な形式とはいえ、形式上は取りうることができるのだからと言う理由で6で定義。もちろん、それが不正な形式を許容してよいという意味ではない。

もっとも、UTF-8の第1オクテットを見れば、その時点で5オクテット以上になるかどうかはわかるのだから、4で問題ないはずなんだけど。

ttynameとgetpwentとglob

NDKで実装されていない関数。

ttynameはひとまず使わなくてもすむように強制コメント化。

getpwentはなにもしない実装して空ぶらせることに。~userみたいなのはどうせ使わないから、なにもしない実装で困ることはないだろうということで。

globの実装は2.5.3と同様に見送り。2.2相当のファイル指定ができれば、自分は困らないので優先度を落とした。

nano 2.5.3をAndroid Terminal Emulatorで日本語が使えるようにビルドした。

Linux環境でのテキストエディタはメインにnanoを使っている。jedも併用してるけど、nanoの方が気楽ではある。

Androidのターミナルでもnanoを使っているのだけど、通常だと日本語で文字化けしてしまう。日本語を開く機会はあまりないのだけども、文字化けしないに越したことはないので、nano 2.5.3をutf-8に対応させるべく、ソースからビルドしてみることに。予めapt-getでgcc-arm-linux-androideabiを入れておく。

 

まずはncursesが必要なので、ncursesをビルドすることにする。
ビルドするにあたっては下記サイトを参考にした。
Compiling GNU Nano for Android at Compdigitec Labs

その後fty_num.cのソースを一部変更。
この時点ではnanoのconfigureを通すのが目的なのでこれ以上の変更はしない。
そしてmake && make install。ncurseswのライブラリが作成された。

次はnanoのビルドにとりかかる。

configureを実行したところ通らないので修正して強引に通す。

android用のライブラリは一部実装されていないのものがある。例えばmblen、mbtowc、wctomb、getpwentはそもそもの実体がないのでリンクの時にエラーが出る。UTF-8の実装はmuslを使うことにする。

ncursesをロケール決め打ちの実装にする。そしてマルチバイト周りをmuslの実装を呼び出すようにして再度ビルド。

次にnano側でmuslのUTF-8の実装をする。getpwentはgetenv(“HOME”)で代用。globはinclude用に使われているので、ひとまず2.2.6相当で読めればなんとかなるからglobを実装から外す。ttynameもちゃんとした実装されていないから、呼び出さなくて良いように変更。

jedをAndroidタブレットに導入する

jedをAndroidタブレットに入れて運用することにする。自分用に作成しているUTF-8対応Android版nanoと使い分けることに。

jedはemacsライクのテキストエディタ。emacsはLISPだけど、代わりにS-Langを使うらしい。

emacsライクだけあって、emacsキーバインド。nanoがemacsに近いキーバインドのためにあまり苦にならない。昔はemacsキーバインドって抵抗あったんだけどなぁ(それでもviと比べればかなりマシではある)。

インストールは Android端末にEmacs風テキストエディタjedを移植する を参照。すんなり導入成功。

以下変更点や嵌った点を。

Altキーが効かない

Android Terminal Emulator(以下ATE)の「AltキーでESCを送出する」にチェックをすることで、解決。

キーバインドの変更

多少nanoライクに。

キー 設定内容 備考
C-l redraw nanoと同じキーバインド
C-u yp_yank nanoと同じキーバインド
C-y page_up nanoと同じキーバインド
C-z undo サスペンドはさせたくない
` self_insert_cmd `はそのまま入力
M-a smart_set_mark_cmd nanoと同じキーバインド
M-L toggle_line_number_mode 行番号の表示切り替え
\e[3~ delete_char_cmd ATEでの[DEL]
\e[1;5A page_up ATEの[CTRL]+[↑]
\e[1;5B page_down ATEの[CTRL]+[↓]
HTML Generating Time : 0.055 s