ウォームチューブテキストインターフェース。 ほぼ簡単

定期的にハブのトピックを調べてみると、ラップトップのもう少しのインターフェイスとニューラルインターフェイスが現実になると常に考えています。 私の仕事では、現代人は単純なコマンドラインを本当に理解せず、愛していないという事実に常に出会っています。 そして、それらへのマニュアルをさらに怠toに読みます。

しかし、私の実践では、1つまたは2つの機能を実行する小さなユーティリティが必要になることがよくあります。 そして、それが正確に実行される場所は不明です。 それはWindowsでも、端末Linuxだけでも、ブートメディアでもかまいません。 私はプログラマーではありませんが、時には自分自身や他の人の生活を楽にすることが必要です。 できればできるだけ明確に。 最初は、コンソールユーティリティだけを作成しようとしました。 実際、これはおそらく誰もが開始する場所です。 しかし、printf / sprintf / puts(および私はCで書いています)を使用すると、テキストをフォーマットし、情報を表示するのはあまり便利ではないことがすぐにわかりました。 一定の「スクロール」を伴うウィンドウはあまり美しくありません。多くの情報がある場合、それは完全に判読できません。 それから、ncursesを思い出しました。





通常、curses / ncursesはLinuxに関連付けられていますが、実際には多くのプラットフォーム、特にWindowsに互換性のある実装があります。 当初、ユーティリティのほとんどはWinで必要でしたが、グラフィカルフレームワークを知らず、テキストを適切にフォーマットして美しく明瞭にする方法を必死に探しました。 そのとき、私はPublic Domain Cursesに出会いました。 ncursesと互換性があるように設計されているため、元のcurses / ncursesの機能のほとんどを使用して、クロスプラットフォームアプリケーションを作成できます。 しかし、残念ながら、バグや制限なしにはできません。 しかし、これは最初に思われたほど怖くない。 コンソールフレンドリーな擬似ウィンドウアプリケーションの作成はそれほど難しくないことを示したいと思います。 そして出力では、ウォームチューブTUIを取得します。 このようなユーザーとの共同作業方法を人々に忘れてはいけない。

この投稿では、PDcursesと互換性のある作業について説明します。したがって、これらの例はWindowsとLinuxの両方で問題なく構築する必要があります。

開始する


テキストインターフェイスを使用するため、ディメンションの単位に1文字が使用されます。 通常のASCII文字とワイド文字の両方を使用できます。 cursesは端末がサポートするもののみを表示できることに注意してください。 残念ながら、個人的には80%の疑似画像が適切に表示されていません。 Linuxでは少し良くなり、Windowsでは非常に悪くなります。 幸いなことに、通常は単純な線が引かれます。

ウィンドウ、パネル、色、テキスト(スクロール、コピーなどを含む)を使用できます。

仕事を始める前に、仕事の準備をし、必要なオプションをオン(オン)にします。



これが私の通常の仕事の始まりです。
initscr(); //  cbreak(); //     getch() raw(); nonl(); noecho(); //    ,      curs_set(0); //  keypad(stdscr, TRUE); //    (,     ) if (has_colors() == FALSE) //    ,      . { endwin(); puts("\nYour terminal does not support color"); return (1); } start_color(); //   use_default_colors(); // stscr  "" init_pair(1, COLOR_WHITE, COLOR_BLUE); //   (background-foreground)    ,    init_pair(2, COLOR_WHITE, COLOR_RED); ......
      
      









最初に窓がありました


ターミナルのエミュレータ/インスタンスを実行すると、stdscrに自分自身が見つかります。 これが私たちの基本である最初のウィンドウです。 作業することも、ウィンドウを作成することもできます。

十分な言葉で、ビジネスに取り掛かりましょう。 ウィンドウを作成します。 すぐに重要なニュアンスに注意したい-どこでも、すべての機能で、最初にY、次にXが来る



 WINDOW *win = newwin(height, width, y, x);
      
      







新しいウィンドウにはそれぞれ独自の相対座標があり、将来的に操作します。 これは重要で便利です。





ウィンドウが作成されましたが、コンソールには何も表示されませんでした。 ウィンドウが親の属性を継承しているためです-この例ではstdscrです。

すぐに私がそれを行う方法を示します。 「仮想ウィンドウ」を記述する構造があります。パネルについては後で説明します

 struct cursed_window { WINDOW *background; WINDOW *decoration; WINDOW *overlay; PANEL *panel; }; typedef struct cursed_window curw;
      
      





これは、最初に変更されず静的なデザインを作成するために行います。 作業データのみを変更し、設計を上書きしません。

ウィンドウの背景-透明な背景とウィンドウからの影。

装飾-フレーム、自動的に描画されます

オーバーレイ-実際には、作業フィールド。 これは新しいウィンドウであり、フレームとシャドウを修正する必要がないため、座標の原点は0.0になります。

パネルについて-後で。



仮想ウィンドウを作成します
 curw *tui_new_win(int sy, int sx, int h, int w, char *label) { curw *new = malloc (sizeof *new); new->background = newwin(h, w, sy, sx);//      wattron(new->background, COLOR_PAIR(7));// ,  .    //     for (int i= w*0.1; i<w;i++) mvwaddch(new->background, h-1, i, ' '); for (int i= h*0.2; i<h;i++) mvwaddch(new->background, i, w-1, ' '); wattroff(new->background, COLOR_PAIR(7)); //   ,      .    //   new->decoration = derwin(new->background, h-2, w-2, 1, 1); wbkgd(new->decoration, COLOR_PAIR(1)); //  box(new->decoration, 0, 0); int x, y; getmaxyx(new->decoration, y, x); new->overlay = derwin(new->decoration, y-4, x-2, 3, 1);//   wbkgd(new->overlay, COLOR_PAIR(1)); new->panel = new_panel(new->background); tui_win_label(new->decoration, label, 0); //       update_panels(); doupdate(); return new; }
      
      













実際、この上に2つ目のウィンドウを作成すると、背景が下のウィンドウに「ズームイン」します。 これはいです。 しかし、使い捨て。 しかし、これは別の議論のトピックです。 簡単にするために影を削除して、いくつかのウィンドウを作成しましょう



しかし今、私たちはパネルについて言うことができます。 パネルは、ウィンドウとそのすべての子ウィンドウを含むスタックコンテナです。 パネルを使用すると、多くの興味深い操作を実行できます。

パネル


これで、パネルの機能を実際にデモンストレーションできます。 スタックの一番上のウィンドウは、デフォルトで作業に使用できます。 また、スタック内のウィンドウやパネルに下からアクセスし、上のスタック内のウィンドウに影響を与えることなくそれらに書き込むことができます。 ウィンドウを自分でソート、移動、サイズ変更できます。 原始コードは申し訳ありませんが、もっと明確にしようとしました。



最後に、メインループを作成しましょう
  int x, y; getmaxyx(stdscr, y, x); curw *wins[3]; //   wins[0] = tui_new_win(0, 0, y - 5, x - 5, "-=Hello Habr=-", 1); wins[1] = tui_new_win(y / 3, x / 2, 15, 30, "-=Data=-", 4); wins[2] = tui_new_win(5, 5, 10, 20, "-=Memo=-", 5); PANEL *TOP = wins[0]->panel; int panel_counter = 0; do { switch ( user_key ) { case 0x9: //TAB if(++panel_counter > 2) { panel_counter=0; } TOP = wins[panel_counter]->panel; break; case KEY_UP: case KEY_DOWN: case KEY_LEFT: case KEY_RIGHT: tui_move_panel(wins[panel_counter], user_key); default: if(isalpha(user_key)) waddch(wins[panel_counter]->overlay, user_key); break; } //         top_panel(TOP); touchwin(panel_window(TOP)); update_panels( ); doupdate( ); } while (( user_key = getch( )) != KEY_F(12));
      
      









そして、これがウィンドウ移動ルーチンです
 void tui_move_panel(curw *win, int ch) { int begy, begx, maxx, maxy, x, y; getbegyx(panel_window(win->panel), begy, begx); getmaxyx(panel_window(win->panel), maxy, maxx); getmaxyx(stdscr, y, x); switch (ch) { case KEY_UP: if ((begy - 1) >= 0) begy--; break; case KEY_DOWN: if (((begy + 1) + maxy) <= y) begy++; break; case KEY_LEFT: if ((begx - 1) >= 0) begx--; break; case KEY_RIGHT: if (((begx + 1) + maxx) <= x) begx++; break; } move_panel(win->panel, begy, begx); }
      
      









よくそして結果として







もっと説明しようと思ったが、どうやらそれは大きすぎて退屈な投稿になりそうなので、十分な機能を備えたこの「古代の技術」に注目したかった。 舞台裏には、テキストや属性などの操作がありました。 たとえば、任意のウィンドウからテキスト行をコピーして、その色とモードを調べることができます。 その他。

これが退屈ではないことを願っています。



All Articles