{"id":21354683,"url":"https://github.com/iveevi/tuicpp","last_synced_at":"2026-02-20T22:39:35.788Z","repository":{"id":132435335,"uuid":"436336457","full_name":"iveevi/tuicpp","owner":"iveevi","description":"A simple C++ wrapper around ncurses to ease the developement of TUI applications.","archived":false,"fork":false,"pushed_at":"2022-04-12T19:55:14.000Z","size":180,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-24T04:49:10.895Z","etag":null,"topics":["cpp","ncurses","tui"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iveevi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-12-08T17:36:13.000Z","updated_at":"2023-03-07T23:02:14.000Z","dependencies_parsed_at":"2024-01-26T00:04:00.627Z","dependency_job_id":null,"html_url":"https://github.com/iveevi/tuicpp","commit_stats":null,"previous_names":["iveevi/tuicpp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/iveevi/tuicpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iveevi%2Ftuicpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iveevi%2Ftuicpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iveevi%2Ftuicpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iveevi%2Ftuicpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iveevi","download_url":"https://codeload.github.com/iveevi/tuicpp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iveevi%2Ftuicpp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29667093,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T19:49:36.704Z","status":"ssl_error","status_checked_at":"2026-02-20T19:44:05.372Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","ncurses","tui"],"created_at":"2024-11-22T04:14:13.106Z","updated_at":"2026-02-20T22:39:35.766Z","avatar_url":"https://github.com/iveevi.png","language":"C++","readme":"# tuicpp\n\ntuicpp is a C++ wrapper API for ncurses which eases the developement of text\nbased interfaces and applications.\n\nAll API elements are enclosed inside the `tuicpp` namespace.\n\nTable of Contents\n=================\n\n* [tuicpp](#tuicpp)\n   * [Table of Contents](#table-of-contents)\n   * [Overview of tuicpp](#overview-of-tuicpp)\n      * [Setting up](#setting-up)\n      * [Import Structures](#import-structures)\n         * [ScreenInfo](#screeninfo)\n         * [World](#world)\n      * [Window types](#window-types)\n         * [PlainWindow](#plainwindow)\n            * [Method Summary](#method-summary)\n         * [BoxedWindow](#boxedwindow)\n         * [DecoratedWindow](#decoratedwindow)\n         * [SelectionWindow](#selectionwindow)\n         * [Table](#table)\n         * [FieldEditor](#fieldeditor)\n\nCreated by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)\n\n## Overview of tuicpp\n\n### Setting up\n\nThe classes in `tuicpp` can be used almost immediately, however ncurses must\nactually be initialized with `initscr()`. Likewise, it must be manually ended\nwith `endwin()` to prevent it from screwing with your terminal.\n\n```cpp\n// Example main\nint main()\n{\n\t// Initialize ncurses\n\tinitscr();\n\n\t// tuicpp stuff goes here...\n\n\t// End ncurses\n\t// \tdon't worry about the ncurses window\n\t//\thandles, they are managed by tuicpp's\n\t//\twindows\n\tendwin();\n}\n```\n\n### Import Structures\n\n#### ScreenInfo\n\nThe `ScreenInfo` struct is defined as follows.\n\n```cpp\n// Screen info\nstruct ScreenInfo {\n        int height;\n        int width;\n        int y;\n        int x;\n};\n```\n\nIt describes the position and size of the window. Note that `height` is before\n`width` and `y` is before `x`. To avoid confusions with this altogether,\ninitialize these objects as follows:\n\n```cpp\nauto si = ScreenInfo {\n\t.height = 20,\n\t.width = 20,\n\t.y = 0,\t\t// 0 is default\n\t.x = 0\t\t// 0 is default\n};\n```\n\n#### World\n\nThe `World` class does not represent an ncurses window, only the essential\nmembers that all derived `Window` types will have.\n\nA method to note from this class is the static `World::limits()` which returns a\n`std::pair \u003cint, int\u003e` of the terminal's maximum height and width (note this\norder).\n\n### Window types\n\nNow for the exciting stuff. Each section will show a snippet of code\ndemonstrating the construction and usage of the window and an animation of the\ncorresponding execution.\n\n#### PlainWindow\n\nAs plain as a window can get.\n\n```cpp\nauto win = tuicpp::PlainWindow(\n\ttuicpp::ScreenInfo {\n\t\t.height = height,\n\t\t.width = width,\n\t\t.y = y,\n\t\t.x = x\n\t}\n);\n\nwin.printf(\"Hello World!\\n\");\nwin.printf(\"This is just an ordinary window!\\n\");\nwin.printf(\"Notice that the text is being wrapped!\\n\");\nwin.printf(\"Press any key to continue...\\n\");\nwin.getc();\n```\n\nResult:\n\n![](media/plain_window.png)\n\nThis class is important because it contains a conventional set of methods that\nare inherited by all the remaining window types.\n\n##### Method Summary\n\nMethod\t\t\t\t\t\t\t| Description\n---\t\t\t\t\t\t\t| ---\n`refresh()`\t\t\t\t\t\t| Refreshes the window, essentially doing `wrefresh()`.\n`clear()`\t\t\t\t\t\t| Clears the window, essentially doing `wclear()`.\n`erase()`\t\t\t\t\t\t| Erase the window, essentially doing `werases()`. Unlike `clear()` there should not be as much flickering. All derived classes should this method as necessary.\n`resize(int height, int width)`\t\t\t\t| Resizes the window. Note the order of the arguments.\n`move(int y, int x)`\t\t\t\t\t| Moves the ***cursor*** to the yth row and xth column.\n`printf(const char *fmt, ...)`\t\t\t\t| Prints to the window, like `wprintw`.\n`mvprintf(int y, int x, const char *fmt, ...)`\t\t| Prints to the window starting at the yth row and xth column, like `mvwprintw`.\n`add_char(const chtype ch)`\t\t\t\t| Prints a characetr to the the window, like `waddch`.\n`mvadd_char(int y, int x, const chtype ch)`\t\t| Prints a characetr to the the window at the yth row and xth column, like `mvwaddch`.\n`getc()`\t\t\t\t\t\t| Get a character that the user pressed, like `wgetc()`. Will block until a key is pressed.\n`set_keypad(bool bl)`\t\t\t\t\t| Enables keypad for the window.\n`cursor(int y, int x)`\t\t\t\t\t| A more sensible alias for `move()`.\n`attribute_on(int attr)`\t\t\t\t| Turn on the attribute `attr` for the window, like `wattron()`.\n`attribute_off(int attr)`\t\t\t\t| Turn off the attribute `attr` for the window, like `wattroff()`.\n`attribute_set(int attr)`\t\t\t\t| Set the attribute for the window to `attr`, like `wattrset()`.\n\nSome of these methods (i.e. `refresh()` and `clear()`) are overriden in derived\nclasses.\n\n#### BoxedWindow\n\nA window with a border surrounding it.\n\n```cpp\nauto win = tuicpp::BoxedWindow(\n\ttuicpp::ScreenInfo {\n\t\t.height = height,\n\t\t.width = width,\n\t\t.y = y,\n\t\t.x = x\n\t}\n);\n\nwin.printf(\"Hello World!\\n\");\nwin.printf(\"This is no ordinary window ... it has a border!\\n\");\nwin.printf(\"Text is still being wrapped...\\n\");\nwin.printf(\"Press any key to continue...\\n\");\nwin.getc();\n```\n\nResult:\n\n![](media/boxed_window.png)\n\n#### DecoratedWindow\n\nA window with a border and a title bar.\n\n```cpp\nauto win = tuicpp::DecoratedWindow(\n\t\"My Decorated Window\",\n\ttuicpp::ScreenInfo {\n\t\t.height = height,\n\t\t.width = width,\n\t\t.y = y,\n\t\t.x = x\n\t}\n);\n\nwin.printf(\"Hello World!\\n\");\nwin.printf(\"This is a decorated window\\n\");\nwin.printf(\"It has a title bar and a border\\n\");\nwin.printf(\"Press any key to continue...\\n\");\nwin.getc();\n```\n\nResult:\n\n![](media/decorated_window.png)\n\nNow we get into more niche window types.\n\n#### SelectionWindow\n\nA window which handles the selection from a set of options. The constructor for\nthis class requires passing a `struct` of type `SelectionWindow::Option` to\nspecify certain options.\n\n```cpp\nauto opts = tuicpp::SelectionWindow {\n\t// Dictates whether the options should\n\t//\tbe center within the window\n\t.centered = true,\n\n\t// Allows multiple options to be selected\n\t//\t(and then be confirmed by an [OK] button)\n\t.multi = false\n};\n```\n\nConstruction is fairly simple:\n\n```cpp\n// List of options -- OptionList is just an alias\n//\tfor std::vector \u003cstd::string\u003e\nauto opt_list = tuicpp::SelectionWindow {\n\t\"Option A\",\n\t\"Option B\",\n\t\"Option C\",\n\t\"Option D\"\n};\n\n// As will be shown later, it should be more\n//\tcommon to allocate the window on heap,\n//\tso that it can be smoothly removed from\n//\tthe screen when it is done\nauto win = new tuicpp::SelectionWindow(\n\t\"Selection Window\",\n\tscreen_info,\n\topt_list,\n\topts\n);\n```\n\nThe options that the user selects will be stored as indices to the `OptionList`\nin a `SelectionWindow::Selection` object (an alias for `std::set \u003cint\u003e`).\n\n```cpp\nauto selection = tuicpp::SelectionWindow::Selection {};\n\n// The return of this method is whether the\n//\tuser has selected at least one option\n//\t(i.e. selection.size() \u003e 0)\nbool yeilded = win-\u003eyield(selection);\n\n// Delete the window now that we are done with it\ndelete win;\n\n// Whatever else we want to do...\n```\n\nThe result of this is the following: [TODO]\n\nWith `opts.multi = true` it would instead look this: [TODO]\n\n#### Table\n\nThe `Table` class is a templated interface designed to conveniently display a\ntable in ncurses. Its construction requires an auxiliarly structure, `Table \u003cT\u003e\n::From`, which describes the columns of the table and how to generate them.\n\n```cpp\n// This lambda describes how to generate the column\n//\tentries for the table for one data input\n//\t(float, in our case)\nauto to_str = [](const float \u0026i, size_t column) {\n\tif (column == 0) {\n\t\t// First column is x\n\t\treturn std::to_string(i);\n\t} else {\n\t\t// Second column is x * x\n\t\treturn std::to_string(i * i);\n\t}\n};\n\nauto from = auto from = tuicpp::Table \u003cfloat\u003e ::From({\"x\", \"f(x)\"}, to_str);\n```\n\nTo fill in the actual data for the table, one must assign the `.data` field (a\n`std::vector` of the template parameter).\n\n```cpp\nfrom.data = {\n\t0, 0.5, 1.0, 1.5, 2.0, 2.5,\n\t3.0, 3.5, 4.0, 4.5, 5.0\n};\n```\n\nNow, construction is simply as follows.\n\n```cpp\nauto win = tuicpp::Table \u003cfloat\u003e (\n\tfrom,\n\ttuicpp::ScreenInfo {\n\t\t.height = height,\n\t\t.width = width,\n\t\t.y = y,\n\t\t.x = x\n\t}\n);\n```\n\nThe result is the following:\n\n![](media/table_window.png)\n\nAdditional options can be supplied to the table through the `From` structure.\nThe `.length` member (`std::vector \u003csize_t\u003e`) specifies the width of each table\ncolumn, and the boolean `.auto_resize` dictates whether the `Table` object's\nwindow will be resized to fit the entire table.\n\nThe `Table` class also comes with the following methods.\n\nMethod\t\t\t\t\t\t\t| Description\n---\t\t\t\t\t\t\t| ---\n`set_data(const Data \u0026data, bool auto_resize = false)`\t| Changes the table's data to `data`. If `auto_resize` is set to `true`, then the window will resize to fit the whole table.\n`set_lengths(const Lengths \u0026lengths)`\t\t\t| Sets the width of each column.\n`set_generator(const Generator \u0026generator)`\t\t| Changes the column generator function to `generator`. The expected signature for `Generator` is `std::string (const T \u0026, size)`.\n`highlight_row(int row)`\t\t\t\t| Highlight's a specific row in the table.\n\n\n#### FieldEditor\n\nEdit fields in a slick little window. Construction is very easy:\n\n```cpp\n// We allocate this on the heap to remove it from\n//\tour app seamlessly\nauto win = new tuicpp::FieldEditor(\n\t\"Employee Editor\",\n\t{\"Name\", \"Email\"},\t\t// Names of the fields\n\ttuicpp::ScreenInfo {\n\t\t.height = height,\n\t\t.width = width,\n\t\t.y = y,\n\t\t.x = x\n\t}\n);\n```\n\nThis defines an editor with the fields \"Name\" and \"Email\". To get user input\n(and display the editor), one does the following:\n\n```cpp\n// Assign the initial values of the fields\nstd::string name = \"Bob Joe\";\nstd::string email;\n\n// \"Yield\" the user input\nwin-\u003eyield({\n\ttuicpp::yielder(\u0026name),\n\ttuicpp::yielder(\u0026email)\n});\n\n// Done with the editor, we can free it now\ndelete win;\n\n// Do whatever else...\n```\n\nThe `yield` method takes some pretty weird objects. For now, think of\n`yielder(\u0026name)` as a wrapper to the reference to `name`. When the editor is\ndone with the `yield` method, the contents of the fields will the stored in\n`name` and `email`. No extra hassle.\n\nThe result of this setup is the following.\n\n![](media/editor_window.gif)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiveevi%2Ftuicpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiveevi%2Ftuicpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiveevi%2Ftuicpp/lists"}