2

実際にかなりうまく機能する小さなチャットCLIアプリケーションを作成しました!

残念ながら、一方がメッセージを入力し、同時に他方のメッセージを受信すると、両方がインターレースします...これは非常にひどいものになります。

elton: Hey!
john: how are you doing?
fine anjohn: still not to bed?!
d john: haha
you?elton: fine and you?

私はこの種の問題を回避する方法を探しています。ユーザー入力用の最後の行を「予約」したり、データを受信したときにいくつかのアクションを処理してユーザー入力の位置を再計算したりします。

調査の結果、getch()を使用して各文字を1つずつ取得することがわかりました。新しいメッセージが表示されるのを待っているかどうかを定期的に確認して、このケースを処理できるようにします。

しかし、getch()を使用する場合、基本的なアクション(バックスペース、左右の移動など)を手動で再定義する必要があり、一部の文字は1バイト以上かかります。簡単に言えば、それは使用できません。

4

2 に答える 2

1

私の知る限り、ここにはいくつかの選択肢があります。通常、getchを呼び出すだけで、ターミナルを「調理済み」モードと呼ばれるモードで実行しています。これは、端末が文字を到着順に表示するだけで、特別なことは何もないことを意味します。ただし、発見したとおり、競合状態に遭遇します。

オプション1:一度に1文字ずつ読み取り、行全体をバッファリングします。新しい行が到着し、それを印刷したい場合は、(a)ある種の印刷ミューテックス(プログラムの内部)を取得し、(b)現在の行をクリアする必要があります(print'\ r [ space] [space] [space] ... \ r')、(c)入力行+' \ n'を印刷し、(d)前のバッファを(印刷によって)画面に復元し、ミューテックスのロックを解除します。

これは醜くなります。速い。ご存知のように、ライン編集のサポートや特別なものはありません。このアプローチの唯一の良い点は、おそらく端末の約99%で機能することです。

オプション2:端末をrawモードにします。このモードでは、端末を完全に制御できますが、非常に基本的な機能が失われます(たとえば、キーを入力しても、手動で出力しない限り、キーは表示されません)。ナビゲーションなどを手動で実装する必要がありますが、少なくともそれは機能します。この方法はおそらく最も柔軟性があり、最も制御しやすい方法ですが、このように作業するのは非常に難しいため、彼らはそれを発明しました...

オプション3:ncurses(または同様のターミナルライブラリ)を使用します。概念は少し難しいですが、純粋なrawモードで物事を行うよりもはるかに簡単に学ぶことができます。編集とウィンドウ処理(または、入力すると、行の予約)が組み込まれています。インターフェースは、調理済みモードから得られるよりもはるかにきれいにすることができます。

編集私はここで*nix端末についてたくさん話しているが、そのほとんどはWindowsには当てはまらない。

于 2013-01-16T21:19:36.420 に答える
1

この種のことを行う通常の方法は、純粋なCLIの代わりに「コンソールモードのGUI」を作成することです。

たとえば、IRCクライアント、emacsなどに見られるように、 ROWS-2xCOLS出力ウィンドウ、1xCOLS分周器またはモードライン、および1x入力ウィンドウを備えた非常に単純なインターフェイスを非常に簡単に作成できます。COLS

または、初期のUnixチャットプログラムのほとんどに見られるように、他の人/人のチャット用のxウィンドウと、その下のユーザーの現在および以前のメッセージ用のROWS/2xウィンドウを使用して、分割ビューを実行できます。COLSROWS/2COLS

または、一部の最新のIRCクライアントのように、必要に応じてポップアップして消えるウィンドウがいたるところにある空想的なものです。

Pythonにはcursesサポートが組み込まれていますが、Windowsではサポートされていません。クロスプラットフォームソリューションまたはWindowsのみのソリューションが必要な場合は、Pythonのクロスプラットフォームコンソールアプリからcursesのようなライブラリを参照してください。答えはおそらくそこにあります。

これは、IRCクライアントBitchXのスクリーンショットで、あまり手間をかけずに何ができるかを示しています。 BitchX

于 2013-01-16T21:13:43.450 に答える