Windows support enhancement (text.console, text.line-edit and termios) #173

Open
wants to merge 13 commits into
from

Projects

None yet

2 participants

@Hamayama
Contributor
Hamayama commented Mar 2, 2016

<変更点>

  • text.console
  (1)MS-IMEがONのときのスクロール表示の不具合対応(コマンドプロンプトごと異常終了するので対策。
     日本語版Windowsのバグだと思うが。。。)
  (2)サロゲートペアの文字の入力に対応
  (3)カーソル位置取得の処理変更(カーソル位置取得中に受信した文字をキューイングするようにした)
  • text.line-edit
  (1)ワイド文字対応
     (<line-edit-context> に、文字のバッファ上の幅と表示上の幅のプロパティを追加)
  (2)mintty上で、入力がエコーバックされる件の対策
     (read-line/edit で端末モードの変更と復帰を毎回しているが、次回の read-line/edit までの
      間にキー入力があると、エコーバックしてしまう。対策として、サンプルの line-editor.scm
      では、メインループ全体を call-with-console で囲うようにした。また、
      read-line/edit では、オプション引数で call-with-console の使用有無を選択可能とした)
  (3)MS-IMEがONのときのスクロール表示の不具合対応(text.consoleだけでは吸収できなかった。。。)
  (4)文字列の貼り付け(ペースト)の高速化
     (長い文字列を張り付けると1文字ごとに全体を再表示するため、入力中は表示をスキップする
      ようにした)
  (5)複数行入力してカーソルを先頭に戻してEnterキーを押すと、2行目以降がエコーバックに消され
     る件の対策(コミット時に入力文字列全体を再表示して、カーソルを末尾に移動するようにした)
  (6)mintty上で、画面サイズを超える複数行を入力すると、カーソル移動がおかしくなる件の対策
     (画面表示のクリッピング処理を追加した)
  (7)端を越えてカーソル移動しようとするとマークが外れる件の対策
  (8)Ctrl+l キーによる再表示で、表示が右にずれていく件の対策
  (9)漢字を入力しようとして Alt+半角/全角キーを押すと終了する件の対策
     (Alt+nullキーにダミーコマンドを設定)
  (10)Home/Endキーを押すとエラーになる件の対策
  • gauche.termios
  (1)Windows で MSYS2 の Mintty 使用時に、with-terminal-mode で端末モードを変更可能とした
     (外部コマンドの stty を使用)

参考URL:
https://github.com/Hamayama/line-editor-gw
(ここで実験した結果を反映しています)

OS : Windows 8.1 (64bit)
開発環境 : MSYS2/MinGW-w64 (64bit) (gcc version 5.3.0 (Rev1, Built by MSYS2 project))
Total: 15900 tests, 15900 passed, 0 failed, 0 aborted.

@Hamayama Hamayama referenced this pull request Mar 2, 2016
Closed

Change for mintty on MSYS2 #172

@shirok
Owner
shirok commented Mar 2, 2016

ありがとうございます。backward-charなどで無条件に'moveを返すようになっているのは何か理由がありますか?

@Hamayama
Contributor
Hamayama commented Mar 2, 2016

(7)の端を越えてカーソル移動しようとすると、マークが外れる件の対策だったと思います。

例えば、abcde を入力中に、先頭で Ctrl+スペース でマークして、Ctrl+f で進んでいき、末尾までいってリージョンに入れようとして、行き過ぎると選択が解除されてしまったため、対策しました。

( #fを返すと、clear-mark! が呼ばれると分かったので、'move を返すようにしました。 )

@shirok
Owner
shirok commented Mar 2, 2016

わかりました。moveだと再表示されてしまうので、「本当に何もしない」っていうアクションを作ろうと思います。

@Hamayama
Contributor
Hamayama commented Mar 4, 2016

いくつか修正、変更しました。

  • text.line-edit
  (1)複数行入力時のカーソル上下移動でマークが外れる件の対策
  (2)複数行入力時の複数行のリージョン選択で、第2プロンプトも選択状態になる件の対策
  (3)windows.scm の call-with-console にダミーの mode キーを追加
  (4)その他、プログラムの一部見直し等

また、gdb で調べたところ、コマンドプロンプトが異常終了すると思っていたのは間違いで、
バッファの最終行に対する、write や WriteConsole で、エラーの戻り値が返って来ていました。
それが port.c の file_flusher でチェックされて、Scm_Exit(1) で終了していました。

MS-IME としては、ON のときに最終行に書き込まれると困るので、エラーを返しているのかもしれません。
(しかし "\n" の表示はエラーになるが、" \n" (半角スペースあり) の表示はエラーにならない等、
エラーになる条件が、よく分からない)

しかし、ユーザとしては、MS-IME がいつ ON になるか分からないので、結局、
「1行余分にスクロールして最終行を空ける」等の対策が必要なことには、変わりありませんでした。
(windows.scm だけで対策できるとよいと思い、いろいろ試したのですが、うまくいかず。。。)

@shirok
Owner
shirok commented Mar 4, 2016

ありがとうございます。一旦自分で理解したうえで、機能毎に小分けにしてマージしたいと思います。

@Hamayama
Contributor
Hamayama commented Mar 7, 2016

gauche.termios の without-echoing を、mintty 対応にしました。
その他、一部プログラムを見直しました。

なんとなく、MS-IMEの不具合対応 や MSYS の mintty 対応等を、標準版のソースに
入れる必要がないような気もしてきましたが。。。

@shirok
Owner
shirok commented Mar 7, 2016

標準的な環境ではout-of-boxで動いて欲しいので、MSYS対応やIME対応は入れたいと思っています。

@Hamayama
Contributor
Hamayama commented Mar 8, 2016

<windows-console> の reset-terminal の仕様を <vt100> の仕様に合わせました。

あと gauche.termios を少し整理しました。

@shirok
Owner
shirok commented Mar 8, 2016

termiosの変更だけ別にまとめてコミットする予定です。
2369b92でmsys-get-sttyにtemplateを渡していますが、それって必要でした?

@Hamayama
Contributor
Hamayama commented Mar 8, 2016

msys-get-stty の template 引数ですが、
without-echoing と with-terminal-mode の両方から msys-get-stty が呼ばれるため、
テンポラリファイルのプレフィックスを変えれるようにしたものです。
調査等で、テンポラリファイルがどちらの手続きから作られたのか分かるようにそのようにしました。
しかし、まあ不要かもしれません。。。

@shirok
Owner
shirok commented Mar 9, 2016

あ、なるほど。デバッグ用ですね。

@Hamayama
Contributor

(1) line-edit.scm の redisplay の処理を一部見直しました。

(2) windows.scm の クラスのプロパティ参照の書式を統一しました。
(「~ con 'keybuf」→「~ con'keybuf」等、半角スペースを消去)

(3) console.scm は、コミット 33b06e4 の変更に追従しました。

すいません。(3) をやろうとして自分のブランチ上で git rebase master としたら、履歴が移動してしまったようです。。。

@Hamayama
Contributor

termios.scm に追加した cond-expand の else が抜けていたので追加しました。

@shirok
Owner
shirok commented Mar 10, 2016

termios.scmはこちらでもいじっているので、そちらの変更を取り込んで近いうちにコミットします。そしたらそれに合わせてrebaseお願いできますか。

@shirok
Owner
shirok commented Mar 10, 2016

termiosの変更をpushしました。 413d79e

取りこぼしはないとは思いますが、そちらのブランチでtermios.scmを差し替えて確認お願いします。
has-windows-console? はexportされてるので(unofficialですが)、text.consoleからはwith-moduleなしで使えます。将来は変えるかもしれませんが。

text.consoleの他の変更と、text.line-editの変更もそれぞれ別のコミットにまとめて取り込もうと思っています。と言っても直接そちらのconsoleブランチのHEADを追いかけているので、特にコミットをまとめて頂くといったことは必要ありません。

@Hamayama
Contributor

ありがとうございます。rebase しました。

@shirok
Owner
shirok commented Mar 11, 2016

console.scmのget-raw-charsで最初にdequeue-all!するようにしていますが、それが無いと何か不都合がありましたか?

@Hamayama
Contributor

もしキューに raw でない加工済みの値( (ALT #\a) 等)が入っていたとすると、それが get-raw-chars で返ってしまうと混乱するかと思い、クリアするようにしました。
しかし、現状の getch 等では加工済みの値はすぐに消費しているようなので、現状の作りであれば、いらないかも。。。

@shirok
Owner
shirok commented Mar 11, 2016

なるほど、確かにその可能性はありますね。ただ、黙って失われてしまうのもいまいちなので、「入力キューをクリアする」というAPIを別に作る方向でいこうかな。

@shirok
Owner
shirok commented Mar 12, 2016

五月雨ですみません。console/windows.scmのclear-to-eosで、nの計算を現在行の先頭以降としているように見えますが、元のコードでは不都合が出ましたか?

@Hamayama
Contributor

clear-to-eos は、もともとは、カーソル位置から画面の右下までを計算して消していました。

しかし、画面の高さを超える複数行を入力中に、カーソルを先頭に移動すると、
画面の右下を超えた分が消せずに残ってしまったため、バッファの最後まで消すように変更しました。

画面のクリッピング処理を追加すれば、画面の右下を超えることがなくなるので、
このような追加分の消去は不要になるのですが、
MS-IME の問題で、「画面の右下」が変動するので、
<windows-console> の場合は、クリッピング処理を入れられませんでした。

@shirok
Owner
shirok commented Mar 12, 2016

ああ、わかりました。今のnだとバッファを越える場合もあると思うのですがそれは特に不都合がないのですね。
「画面の高さを越える複数行」についてはまだちゃんと考えてなかったので上位で解決すべき問題も混ざってるかもしれませんが、clear-to-eosがこれで不都合がないならこのまま頂きます。

@shirok shirok added a commit that referenced this pull request Mar 12, 2016
@shirok text.console - Improvements for mintty/MSYS and windows console
Incorporating PR from Hamayama (#173)
Handling surrogate pairs in Windows console, workaround for Windows
IME bug, keeping input buffer queue sane, etc.  See ChangeLog for the
details.
e368ac0
@shirok
Owner
shirok commented Mar 12, 2016

console.scmとconsole/windows.scmはpushしました。last-scrollはensure-bottom-roomという名前に変えてあります。

line-editの変更(2)について、read-line/editの使用局面を考えると、read-line/editがアクティブでない場合に入力がエコーバックされるのは仕様といえると思います。(例えばREPLで使っていて、(read-line)を評価したら、エコーバックが無いと困りますよね?) ですので常にread-line/editの中でcall-with-consoleして良いと思うのですが、それで何か不都合が考えられますか?

@Hamayama
Contributor

line-editの変更(2)ですが、
複数行をまとめてペーストしたときに、エコーバックがまざって、ところどころ2回入力したような表示になったために対策したものです。

しかし、REPL にした場合には、evaluator を、結局エコーバックありの call-with-console でさらに囲うことになったので、確かに不完全な対策でした。
(若干発生頻度が下がった程度)

表示が2倍になるだけで、実際に入力が2倍になるわけではないので、これは仕様とするべきかもしれません。。。

@Hamayama
Contributor

console.scm の query-cursor-position で、座標情報以外のエスケープシーケンスを
(~ con'input-buffer) キューに入れていますが、このキューは、getch を使う場合には、
加工済みの値( KEY_UP 等)が入っていると想定されていると思います。

このため、入力時に Enter の直後に素早くカーソルキーを押したりすると、[A 等が入力されます。
(だれも押さないかもしれませんが。。。)

ここは、自分の改造では、加工済みの値にするのが大変だったので、
エスケープシーケンスごと捨ててしまっていました。

今の処理でもほぼ問題ないかと思いますが、一応情報として挙げておきます。

@shirok
Owner
shirok commented Mar 13, 2016

query-cursor-positionについて: ああ、そうですね。translation無しで読んでるんでした。完璧な対策というのは難しそうなので、リーズナブルな動作をもう少し考えてみます。

line-editの変更(2)について: 普通のreadlineを使ったシェルとかでも「readlineがアクティブでない時はエコーバックされる」という動作なのでエコーバック自体は問題ないと思います。ペースト時の重複がシェル等に比べ目立つとしたら、処理速度の問題かなあ。

@Hamayama
Contributor

あと、すいません
windows.scm の get-ctrl-char ですが、
(= vk 32)) ; #\space
という行は私の勘違いで、不要なので削除をお願いします。
(これを計算すると負の値になってしまう。Ctrl+space が Ctrl+@ と同じだと気が付きませんでした)

@shirok
Owner
shirok commented Mar 13, 2016

あ、見落としてました> (= vk 32)

@Hamayama
Contributor

あと、console.scm の query-cursor-position の中の
(until (r) (cut eqv? <> #\x1b) => ch (enqueue! q ch))
という行で、q が未定義のようです。
( test-module で確認 )

@shirok
Owner
shirok commented Mar 13, 2016

何でmake checkで引っかからなかったんだろう、と思ったらtext.consoleがテストされてなかったですね。とほほ。

@Hamayama
Contributor

rebase すると、履歴が変わったり、消えたりするようなので、今回は merge にしてみました。

サンプルプログラムは修正不要なので (先頭の display は、アイコンダブルクリックによる gosh-noconsole.exe での実行用に追加していました ) 、
あとは line-edit.scm だけかと。。。

line-edit.scm の改造についても、気になる点等があると思いますが、都度質問いただければと思います。

@shirok shirok added a commit that referenced this pull request Mar 20, 2016
@shirok Fix some key bindings
Windows IME on/off key (ALT+#\null), KEY_HOME, KEY_END
Based on the patch from Hamayama ( #173 )
20a89e4
@shirok
Owner
shirok commented Mar 20, 2016

line-edit.scmのうち、ワイド文字対応および画面の縦幅を越える入力への対応以外は済みました。
ワイド文字対応はもう少し考えます。

@Hamayama
Contributor

git merge master しました。

@Hamayama
Contributor

git merge master して、
line-edit.scm の更新 (括弧の対応表示) に追従しました。

@Hamayama
Contributor

cursor-down/scroll-up を変更して、<vt100><windows-console>
の違いを吸収するようにしてみました。

cursor-down/scroll-up のオプション引数で、カーソルのY座標と画面の高さHを指定すると、
カーソルのY座標がどれだけ変化したか(差分値)を返すようにしました。

これによって、line-edit.scm の redisplay に書いていた、Windows IME の不具合対応の処理を、
windows.scm に移動できました。

あとは、redisplay の内容を少し整理しました。

@shirok
Owner
shirok commented May 26, 2016

なるほど。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment