{"id":13495044,"url":"https://github.com/p-ranav/tabulate","last_synced_at":"2025-04-11T06:26:04.082Z","repository":{"id":39857323,"uuid":"229167004","full_name":"p-ranav/tabulate","owner":"p-ranav","description":"Table Maker for Modern C++","archived":false,"fork":false,"pushed_at":"2024-07-04T19:30:45.000Z","size":9866,"stargazers_count":1995,"open_issues_count":38,"forks_count":144,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-03-27T17:13:17.394Z","etag":null,"topics":["aligned","alignment","borders","cli","column-alignment","cpp11","cpp14","cpp17","font-styles","formatted-text","library","mit-license","multi-byte-characters","single-header","single-header-lib","table","table-maker","terminal","view"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p-ranav.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-20T01:27:40.000Z","updated_at":"2025-03-24T06:05:35.000Z","dependencies_parsed_at":"2023-02-19T05:15:35.025Z","dependency_job_id":"190f3e17-bb43-4612-b8e8-5e92020772e7","html_url":"https://github.com/p-ranav/tabulate","commit_stats":{"total_commits":397,"total_committers":12,"mean_commits":"33.083333333333336","dds":0.08060453400503775,"last_synced_commit":"b35db4cce50a4b296290b0ae827305cdeb23751e"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-ranav%2Ftabulate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-ranav%2Ftabulate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-ranav%2Ftabulate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-ranav%2Ftabulate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p-ranav","download_url":"https://codeload.github.com/p-ranav/tabulate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247052619,"owners_count":20875685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["aligned","alignment","borders","cli","column-alignment","cpp11","cpp14","cpp17","font-styles","formatted-text","library","mit-license","multi-byte-characters","single-header","single-header-lib","table","table-maker","terminal","view"],"created_at":"2024-07-31T19:01:30.685Z","updated_at":"2025-04-03T18:10:46.687Z","avatar_url":"https://github.com/p-ranav.png","language":"C++","funding_links":[],"categories":["CLI","C++","C/C++程序设计","Uncategorized","Data Formatting and Presentation","Libraries"],"sub_categories":["资源传输下载","Uncategorized","Misc"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg height=\"50\" src=\"img/logo.jpg\"/\u003e  \n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.com/p-ranav/tabulate\"\u003e\n    \u003cimg src=\"https://travis-ci.com/p-ranav/tabulate.svg?token=haZMYySrhmkE9vsJse61\u0026branch=master\" alt=\"ci status\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://en.wikipedia.org/wiki/C%2B%2B11\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/C%2B%2B-11-blue.svg\" alt=\"standard\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/p-ranav/tabulate/blob/master/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"license\"/\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/version-1.5-blue.svg?cacheSeconds=2592000\" alt=\"version\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/summary.png\"/\u003e  \n  \u003cp align=\"center\"\u003e\n   Source for the above image can be found\n    \u003ca href=\"https://github.com/p-ranav/tabulate/blob/master/samples/summary.cpp\"\u003e\n      here\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n*   [Quick Start](#quick-start)\n*   [Formatting Options](#formatting-options)\n    *   [Style Inheritance Model](#style-inheritance-model)\n    *   [Word Wrapping](#word-wrapping)\n    *   [Font Alignment](#font-alignment)\n    *   [Font Styles](#font-styles)\n    *   [Cell Colors](#cell-colors)\n    *   [Borders and Corners](#borders-and-corners)\n    *   [Range-based Iteration](#range-based-iteration)\n    *   [Nested Tables](#nested-tables)\n    *   [UTF-8 Support](#utf-8-support)\n*   [Exporters](#exporters)\n    *   [Markdown](#markdown)\n    *   [AsciiDoc](#asciidoc)\n*   [Building Samples](#building-samples)\n*   [Generating Single Header](#generating-single-header)\n*   [Contributing](#contributing)\n*   [License](#license)\n\n## Quick Start\n\n`tabulate` is a header-only library. Just add `include/` to your `include_directories` and you should be good to go. A single header file version is also available in `single_include/`.\n\n**NOTE** Tabulate supports `\u003e=C++11`. The rest of this README, however, assumes `C++17` support. \n\nCreate a `Table` object and call `Table.add_rows` to add rows to your table.\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n\n  Table universal_constants;\n\n  universal_constants.add_row({\"Quantity\", \"Value\"});\n  universal_constants.add_row({\"Characteristic impedance of vacuum\", \"376.730 313 461... Ω\"});\n  universal_constants.add_row({\"Electric constant (permittivity of free space)\", \"8.854 187 817... × 10⁻¹²F·m⁻¹\"});\n  universal_constants.add_row({\"Magnetic constant (permeability of free space)\", \"4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²\"});\n  universal_constants.add_row({\"Gravitational constant (Newtonian constant of gravitation)\", \"6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²\"});\n  universal_constants.add_row({\"Planck's constant\", \"6.626 0693(11) × 10⁻³⁴ J·s\"});\n  universal_constants.add_row({\"Dirac's constant\", \"1.054 571 68(18) × 10⁻³⁴ J·s\"});\n  universal_constants.add_row({\"Speed of light in vacuum\", \"299 792 458 m·s⁻¹\"});\n```\n\nUse `RowStream` to format table data with stream insertion.\n\n```cpp\n  employees.add_row({\"Emp. ID\", \"First Name\", \"Last Name\", \"Department / Business Unit\", \"Pay Rate\"});\n  employees.add_row(RowStream{} \u003c\u003c 101 \u003c\u003c \"Donald\" \u003c\u003c \"Patrick\" \u003c\u003c \"Finance\" \u003c\u003c 59.6154);\n  employees.add_row(RowStream{} \u003c\u003c 102 \u003c\u003c \"Rachel\" \u003c\u003c \"Williams\" \u003c\u003c \"Marketing and Operational\\nLogistics Planning\" \u003c\u003c 34.9707);\n  employees.add_row(RowStream{} \u003c\u003c 103 \u003c\u003c \"Ian\" \u003c\u003c \"Jacob\" \u003c\u003c department \u003c\u003c 57.0048);\n```\n\nYou can format this table using `Table.format()` which returns a `Format` object. Using a fluent interface, format properties of the table, e.g., borders, font styles, colors etc.\n\n```cpp\n  universal_constants.format()\n    .font_style({FontStyle::bold})\n    .border_top(\" \")\n    .border_bottom(\" \")\n    .border_left(\" \")\n    .border_right(\" \")\n    .corner(\" \");\n```\n\nYou can access rows in the table using `Table[row_index]`. This will return a `Row` object on which you can similarly call `Row.format()` to format properties of all the cells in that row.\n\nNow, let's format the header of the table. The following code changes the font background of the header row to `red`, aligns the cell contents to `center` and applies a padding to the top and bottom of the row.\n\n```cpp\n  universal_constants[0].format()\n    .padding_top(1)\n    .padding_bottom(1)\n    .font_align(FontAlign::center)\n    .font_style({FontStyle::underline})\n    .font_background_color(Color::red);\n```\n\nCalling `Table.column(index)` will return a `Column` object. Similar to rows, you can use `Column.format()` to format all the cells in that column.\n\nNow, let's change the font color of the second column to yellow:\n\n```cpp\n  universal_constants.column(1).format()\n    .font_color(Color::yellow);\n```\n\nYou can access cells by indexing twice from a table: From a row using `Table[row_index][col_index]` or from a column using `Table.column(col_index)[cell_index]`. Just like rows, columns, and tables, you can use `Cell.format()` to format individual cells\n\n```cpp\n  universal_constants[0][1].format()\n    .font_background_color(Color::blue)\n    .font_color(Color::white);\n}\n```\n\nPrint the table using the stream `operator\u003c\u003c` like so:\n\n```cpp\n  std::cout \u003c\u003c universal_constants \u003c\u003c std::endl;\n``` \n\nYou could also use `Table.print(stream)` to print the table, e.g., `universal_constants.print(std::cout)`. \n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/universal_constants.png\"/\u003e  \n\u003c/p\u003e\n\n## Formatting Options\n\n### Style Inheritance Model\n\nFormatting in `tabulate` follows a simple style-inheritance model. When rendering each cell:\n1.    Apply cell formatting if specified\n2.    If no cell formatting is specified, apply its parent row formatting\n3.    If no row formatting is specified, apply its parent table formatting\n4.    If no table formatting is specified, apply the default table formatting\n\nThis enables overriding the formatting for a particular cell even though row or table formatting is specified, e.g., when an entire row is colored `yellow` but you want a specific cell to be colored `red`.\n\n### Word Wrapping\n\n`tabulate` supports automatic word-wrapping when printing cells. \n\nAlthough word-wrapping is automatic, there is a simple override. Automatic word-wrapping is used only if the cell contents do not have any embedded newline `\\n` characters. So, you can embed newline characters in the cell contents and enforce the word-wrapping manually. \n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table table;\n\n  table.add_row({\"This paragraph contains a veryveryveryveryveryverylong word. The long word will \"\n                 \"break and word wrap to the next line.\",\n                 \"This paragraph \\nhas embedded '\\\\n' \\ncharacters and\\n will break\\n exactly \"\n                 \"where\\n you want it\\n to\\n break.\"});\n\n  table[0][0].format().width(20);\n  table[0][1].format().width(50);\n\n  std::cout \u003c\u003c table \u003c\u003c std::endl;\n}\n```\n\n*  The above table has 1 row and 2 columns. \n*  The first cell has automatic word-wrapping. \n*  The second cell uses the embedded newline characters in the cell contents - even though the second column has plenty of space (50 characters width), it uses user-provided newline characters to break into new lines and enforce the cell style.\n*  **NOTE**: Whether word-wrapping is automatic or not, `tabulate` performs a trim operation on each line of each cell to remove whitespace characters from either side of line.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/word_wrapping.png\"/\u003e  \n\u003c/p\u003e\n\n**NOTE**: Both columns in the above table are left-aligned by default. This, however, can be easily changed.\n\n### Font Alignment\n\n`tabulate` supports three font alignment settings: `left`, `center`, and `right`. By default, all table content is left-aligned. To align cells, use `.format().font_align(alignment)`. \n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table movies;\n  movies.add_row({\"S/N\", \"Movie Name\", \"Director\", \"Estimated Budget\", \"Release Date\"});\n  movies.add_row({\"tt1979376\", \"Toy Story 4\", \"Josh Cooley\", \"$200,000,000\", \"21 June 2019\"});\n  movies.add_row({\"tt3263904\", \"Sully\", \"Clint Eastwood\", \"$60,000,000\", \"9 September 2016\"});\n  movies.add_row({\"tt1535109\", \"Captain Phillips\", \"Paul Greengrass\", \"$55,000,000\", \" 11 October 2013\"});\n\n  // center align 'Director' column\n  movies.column(2).format()\n    .font_align(FontAlign::center);\n\n  // right align 'Estimated Budget' column\n  movies.column(3).format()\n    .font_align(FontAlign::right);\n\n  // right align 'Release Date' column\n  movies.column(4).format()\n    .font_align(FontAlign::right);\n\n  // center-align and color header cells\n  for (size_t i = 0; i \u003c 5; ++i) {\n    movies[0][i].format()\n      .font_color(Color::yellow)\n      .font_align(FontAlign::center)\n      .font_style({FontStyle::bold});\n  }\n\n  std::cout \u003c\u003c movies \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/movies.png\"/\u003e  \n\u003c/p\u003e\n\n### Font Styles\n\n`tabulate` supports 8 font styles: `bold`, `dark`, `italic`, `underline`, `blink`, `reverse`, `concealed`, `crossed`. Depending on the terminal (or terminal settings), some of these might not work. \n\nTo apply a font style, simply call `.format().font_style({...})`. The `font_style` method takes a vector of font styles. This allows to apply multiple font styles to a cell, e.g., ***bold and italic***.\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table styled_table;\n  styled_table.add_row({\"Bold\", \"Italic\", \"Bold \u0026 Italic\", \"Blinking\"});\n  styled_table.add_row({\"Underline\", \"Crossed\", \"Dark\", \"Bold, Italic \u0026 Underlined\"});\n\n  styled_table[0][0].format()\n    .font_style({FontStyle::bold});\n\n  styled_table[0][1].format()\n    .font_style({FontStyle::italic});\n\n  styled_table[0][2].format()\n    .font_style({FontStyle::bold, FontStyle::italic});\n\n  styled_table[0][3].format()\n    .font_style({FontStyle::blink});\n\n  styled_table[1][0].format()\n    .font_style({FontStyle::underline});\n\n  styled_table[1][1].format()\n    .font_style({FontStyle::crossed});\n\n  styled_table[1][2].format()\n    .font_style({FontStyle::dark});\n\n\n  styled_table[1][3].format()\n    .font_style({FontStyle::bold, FontStyle::italic, FontStyle::underline});\n\n  std::cout \u003c\u003c styled_table \u003c\u003c std::endl;\n\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/font_styles.png\"/\u003e  \n\u003c/p\u003e\n\n**NOTE**: Font styles are applied to the entire cell. Unlike HTML, you cannot currently apply styles to specific words in a cell.\n\n### Cell Colors\n\nThere are a number of methods in the `Format` object to color cells - foreground and background - for font, borders, corners, and column separators. Thanks to [termcolor](https://github.com/ikalnytskyi/termcolor), `tabulate` supports 8 colors: `grey`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, and `white`. The look of these colors vary depending on your terminal.\n\nFor font, border, and corners, you can call `.format().\u003celement\u003e_color(value)` to set the foreground color and `.format().\u003celement\u003e_background_color(value)` to set the background color. Here's an example:\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table colors;\n\n  colors.add_row({\"Font Color is Red\", \"Font Color is Blue\", \"Font Color is Green\"});\n  colors.add_row({\"Everything is Red\", \"Everything is Blue\", \"Everything is Green\"});\n  colors.add_row({\"Font Background is Red\", \"Font Background is Blue\", \"Font Background is Green\"});\n\n  colors[0][0].format()\n    .font_color(Color::red)\n    .font_style({FontStyle::bold});\n  colors[0][1].format()\n    .font_color(Color::blue)\n    .font_style({FontStyle::bold});\n  colors[0][2].format()\n    .font_color(Color::green)\n    .font_style({FontStyle::bold});\n\n  colors[1][0].format()\n    .border_left_color(Color::red)\n    .border_left_background_color(Color::red)\n    .font_background_color(Color::red)\n    .font_color(Color::red);\n\n  colors[1][1].format()\n    .border_left_color(Color::blue)\n    .border_left_background_color(Color::blue)\n    .font_background_color(Color::blue)\n    .font_color(Color::blue);\n\n  colors[1][2].format()\n    .border_left_color(Color::green)\n    .border_left_background_color(Color::green)\n    .font_background_color(Color::green)\n    .font_color(Color::green)\n    .border_right_color(Color::green)\n    .border_right_background_color(Color::green);\n\n  colors[2][0].format()\n    .font_background_color(Color::red)\n    .font_style({FontStyle::bold});\n  colors[2][1].format()\n    .font_background_color(Color::blue)\n    .font_style({FontStyle::bold});\n  colors[2][2].format()\n    .font_background_color(Color::green)\n    .font_style({FontStyle::bold});\n\n  std::cout \u003c\u003c colors \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/colors.png\"/\u003e  \n\u003c/p\u003e\n\n### Borders and Corners\n\n`tabulate` allows for fine control over borders and corners. For each border and corner, you can set the text, color, and background color.\n\n**NOTE**: You can use `.corner(..)`, `.corner_color(..)`, and `.corner_background_color(..)` to set a common style for all corners. Similarly, you can use `.border(..)`, `.border_color(..)` and `.border_background_color(..)` to set a common style for all borders.\n\n**NOTE**: Note the use of `.format().multi_byte_characters(true)`. Use this when you know your table has multi-byte characters. This is an opt-in because the calculation of column width when dealing with multi-byte characters is more involved and you don't want to pay the performance penalty unless you need it. Just like any other format setting, you can set this at the table-level, row-level, or on a per-cell basis. \n\nHere's an example where each border and corner is individually styled:\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table table;\n\n  table.add_row({\"ᛏᚺᛁᛊ ᛁᛊ ᚨ ᛊᛏᛟᚱy ᛟᚠᚨ ᛒᛖᚨᚱ ᚨᚾᛞ\\n\"\n                 \"ᚨ ᚹᛟᛚᚠ, ᚹᚺᛟ ᚹᚨᚾᛞᛖᚱᛖᛞ ᛏᚺᛖ\\n\"\n                 \"ᚱᛖᚨᛚᛗᛊ ᚾᛁᚾᛖ ᛏᛟ ᚠᚢᛚᚠᛁᛚᛚ ᚨ ᛈᚱᛟᛗᛁᛊᛖ\\n\"\n                 \"ᛏᛟ ᛟᚾᛖ ᛒᛖᚠᛟᚱᛖ; ᛏᚺᛖy ᚹᚨᛚᚲ ᛏᚺᛖ\\n\"\n                 \"ᛏᚹᛁᛚᛁᚷᚺᛏ ᛈᚨᛏᚺ, ᛞᛖᛊᛏᛁᚾᛖᛞ ᛏᛟ\\n\"\n                 \"ᛞᛁᛊcᛟᚹᛖᚱ ᛏᚺᛖ ᛏᚱᚢᛏᚺ\\nᛏᚺᚨᛏ ᛁᛊ ᛏᛟ cᛟᛗᛖ.\"});\n\n  table.format()\n      .multi_byte_characters(true)\n      // Font styling\n      .font_style({FontStyle::bold, FontStyle::dark})\n      .font_align(FontAlign::center)\n      .font_color(Color::red)\n      .font_background_color(Color::yellow)\n      // Corners\n      .corner_top_left(\"ᛰ\")\n      .corner_top_right(\"ᛯ\")\n      .corner_bottom_left(\"ᛮ\")\n      .corner_bottom_right(\"ᛸ\")\n      .corner_top_left_color(Color::cyan)\n      .corner_top_right_color(Color::yellow)\n      .corner_bottom_left_color(Color::green)\n      .corner_bottom_right_color(Color::red)\n      // Borders\n      .border_top(\"ᛜ\")\n      .border_bottom(\"ᛜ\")\n      .border_left(\"ᚿ\")\n      .border_right(\"ᛆ\")\n      .border_left_color(Color::yellow)\n      .border_right_color(Color::green)\n      .border_top_color(Color::cyan)\n      .border_bottom_color(Color::red);\n\n  std::cout \u003c\u003c table \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/runic.png\"/\u003e  \n\u003c/p\u003e\n\n### Range-based Iteration\n\nHand-picking and formatting cells using `operator[]` gets tedious very quickly. To ease this, `tabulate` supports range-based iteration on tables, rows, and columns. Quickly iterate over rows and columns to format cells.\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table table;\n\n  table.add_row({\"Company\", \"Contact\", \"Country\"});\n  table.add_row({\"Alfreds Futterkiste\", \"Maria Anders\", \"Germany\"});\n  table.add_row({\"Centro comercial Moctezuma\", \"Francisco Chang\", \"Mexico\"});\n  table.add_row({\"Ernst Handel\", \"Roland Mendel\", \"Austria\"});\n  table.add_row({\"Island Trading\", \"Helen Bennett\", \"UK\"});\n  table.add_row({\"Laughing Bacchus Winecellars\", \"Yoshi Tannamuri\", \"Canada\"});\n  table.add_row({\"Magazzini Alimentari Riuniti\", \"Giovanni Rovelli\", \"Italy\"});\n\n  // Set width of cells in each column\n  table.column(0).format().width(40);\n  table.column(1).format().width(30);\n  table.column(2).format().width(30);\n\n  // Iterate over cells in the first row\n  for (auto\u0026 cell : table[0]) {\n    cell.format()\n      .font_style({FontStyle::underline})\n      .font_align(FontAlign::center);\n  }\n\n  // Iterator over cells in the first column\n  for (auto\u0026 cell : table.column(0)) {\n    if (cell.get_text() != \"Company\") {\n      cell.format()\n        .font_align(FontAlign::right);\n    }\n  }\n\n  // Iterate over rows in the table\n  size_t index = 0;\n  for (auto\u0026 row : table) {\n    row.format()\n      .font_style({FontStyle::bold});\n\n    // Set blue background color for alternate rows\n    if (index \u003e 0 \u0026\u0026 index % 2 == 0) {\n      for (auto\u0026 cell : row) {\n        cell.format()\n          .font_background_color(Color::blue);\n      }      \n    }\n    index += 1;\n  }\n\n  std::cout \u003c\u003c table \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/iterators.png\"/\u003e  \n\u003c/p\u003e\n\n### Nested Tables\n\n`Table.add_row(...)` takes either a `std::string` or a `tabulate::Table`. This can be used to nest tables within tables. Here's an example program that prints a UML class diagram using `tabulate`. Note the use of font alignment, style, and width settings to generate a diagram that looks centered and great.\n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table class_diagram;\n\n  // Global styling\n  class_diagram.format().font_style({FontStyle::bold}).font_align(FontAlign::center).width(60);\n\n  // Animal class\n  Table animal;\n  animal.add_row({\"Animal\"});\n  animal[0].format().font_align(FontAlign::center);\n\n  // Animal properties nested table\n  Table animal_properties;\n  animal_properties.format().width(20);\n  animal_properties.add_row({\"+age: Int\"});\n  animal_properties.add_row({\"+gender: String\"});\n  animal_properties[1].format().hide_border_top();\n\n  // Animal methods nested table\n  Table animal_methods;\n  animal_methods.format().width(20);\n  animal_methods.add_row({\"+isMammal()\"});\n  animal_methods.add_row({\"+mate()\"});\n  animal_methods[1].format().hide_border_top();\n\n  animal.add_row({animal_properties});\n  animal.add_row({animal_methods});\n  animal[2].format().hide_border_top();\n\n  class_diagram.add_row({animal});\n\n  // Add rows in the class diagram for the up-facing arrow\n  // THanks to center alignment, these will align just fine\n  class_diagram.add_row({\"▲\"});\n  class_diagram[1][0].format().hide_border_top().multi_byte_characters(true); // ▲ is multi-byte\n  \n  class_diagram.add_row({\"|\"});\n  class_diagram[2].format().hide_border_top();\n  class_diagram.add_row({\"|\"});\n  class_diagram[3].format().hide_border_top();\n\n  // Duck class\n  Table duck;\n  duck.add_row({\"Duck\"});\n  duck[0].format().font_align(FontAlign::center);\n\n  // Duck proeperties nested table\n  Table duck_properties;\n  duck_properties.format().width(40);\n  duck_properties.add_row({\"+beakColor: String = \\\"yellow\\\"\"});\n\n  // Duck methods nested table\n  Table duck_methods;\n  duck_methods.format().width(40);\n  duck_methods.add_row({\"+swim()\"});\n  duck_methods.add_row({\"+quack()\"});\n  duck_methods[1].format().hide_border_top();\n\n  duck.add_row({duck_properties});\n  duck.add_row({duck_methods});\n  duck[2].format().hide_border_top();\n\n  class_diagram.add_row({duck});\n  class_diagram[4].format().hide_border_top();\n\n  std::cout \u003c\u003c class_diagram \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg height=\"600\" src=\"img/class_diagram.png\"/\u003e  \n\u003c/p\u003e\n\n### UTF-8 Support\n\nIn \\*nix, `wcswidth` is used to compute the display width of multi-byte characters. Column alignment works well when your system supports the necessary locale, e.g., I've noticed on MacOS 10 there is no Arabic locale (searched with `locale -a`) and this ends up causing alignment issues when using Arabic text, e.g., `\"ٲنَا بحِبَّك (Ana bahebak)\"` in tables.\n\nThe following table prints the phrase `I love you` in different languages. Note the use of `.format().multi_byte_characters(true)` for the second column. Remember to do this when dealing with multi-byte characters. \n\n```cpp\n#include \u003ctabulate/table.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table table;\n\n  table.format().corner(\"♥\")\n    .font_style({FontStyle::bold})\n    .corner_color(Color::magenta)\n    .border_color(Color::magenta);\n\n  table.add_row({\"English\", \"I love you\"});\n  table.add_row({\"French\", \"Je t’aime\"});\n  table.add_row({\"Spanish\", \"Te amo\"});\n  table.add_row({\"German\", \"Ich liebe Dich\"});\n  table.add_row({\"Mandarin Chinese\", \"我爱你\"});\n  table.add_row({\"Japanese\", \"愛してる\"});\n  table.add_row({\"Korean\", \"사랑해 (Saranghae)\"});\n  table.add_row({\"Greek\", \"Σ΄αγαπώ (Se agapo)\"});\n  table.add_row({\"Italian\", \"Ti amo\"});\n  table.add_row({\"Russian\", \"Я тебя люблю (Ya tebya liubliu)\"});\n  table.add_row({\"Hebrew\", \"אני אוהב אותך (Ani ohev otakh)\"});\n\n  // Column 1 is using mult-byte characters\n  table.column(1).format()\n    .multi_byte_characters(true);\n\n  std::cout \u003c\u003c table \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg height=\"600\" src=\"img/unicode.png\"/\u003e  \n\u003c/p\u003e\n\nYou can explicitly set the locale for a cell using `.format().locale(value)`. Note that the locale string is system-specific. So, the following code might throw `std::runtime_error locale::facet::_S_create_c_locale name not valid` on your system. \n\n```cpp\n  // Set English-US locale for first column\n  table.column(0).format().locale(\"en_US.UTF-8\");\n  table[0][1].format().locale(\"en_US.UTF-8\");\n\n  // Set locale for individual cells\n  table[1][1].format().locale(\"fr_FR.UTF-8\");  // French\n  table[2][1].format().locale(\"es_ES.UTF-8\");  // Spanish\n  table[3][1].format().locale(\"de_DE.UTF-8\");  // German\n  table[4][1].format().locale(\"zh_CN.UTF-8\");  // Chinese\n  table[5][1].format().locale(\"ja_JP.UTF-8\");  // Japanese\n  table[6][1].format().locale(\"ko_KR.UTF-8\");  // Korean\n  table[7][1].format().locale(\"el_GR.UTF-8\");  // Greek\n  table[8][1].format().locale(\"it_IT.UTF-8\");  // Italian\n  table[9][1].format().locale(\"ru_RU.UTF-8\");  // Russian\n  table[10][1].format().locale(\"he_IL.UTF-8\"); // Hebrew\n```\n\n## Exporters\n\n### Markdown\n\nTables can be exported to GitHub-flavored markdown using a `MarkdownExporter`. Simply create an exporter object and call `exporter.dump(table)` to generate a Markdown-formatted `std::string`. \n\n```cpp\n#include \u003ctabulate/markdown_exporter.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table movies;\n  movies.add_row({\"S/N\", \"Movie Name\", \"Director\", \"Estimated Budget\", \"Release Date\"});  \n  movies.add_row({\"tt1979376\", \"Toy Story 4\", \"Josh Cooley\", \"$200,000,000\", \"21 June 2019\"});\n  movies.add_row({\"tt3263904\", \"Sully\", \"Clint Eastwood\", \"$60,000,000\", \"9 September 2016\"});\n  movies.add_row(\n      {\"tt1535109\", \"Captain Phillips\", \"Paul Greengrass\", \"$55,000,000\", \" 11 October 2013\"});\n\n  // center align 'Director' column\n  movies.column(2).format().font_align(FontAlign::center);\n\n  // right align 'Estimated Budget' column\n  movies.column(3).format().font_align(FontAlign::right);\n\n  // right align 'Release Date' column\n  movies.column(4).format().font_align(FontAlign::right);\n\n  // Color header cells\n  for (size_t i = 0; i \u003c 5; ++i) {\n    movies[0][i].format().font_color(Color::yellow).font_style({FontStyle::bold});\n  }\n\n  // Export to Markdown\n  MarkdownExporter exporter;\n  auto markdown = exporter.dump(movies);\n\n  // tabulate::table\n  std::cout \u003c\u003c movies \u003c\u003c \"\\n\\n\";\n\n  // Exported Markdown\n  std::cout \u003c\u003c markdown \u003c\u003c std::endl;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/markdown_export.png\"/\u003e  \n\u003c/p\u003e\n\nThe above table renders in Markdown like below.\n\n**NOTE**: Unlike `tabulate`, you cannot align individual cells in Markdown. Alignment is on a per-column basis. Markdown allows a second header row where such column-wise alignment can be specified. The `MarkdownExporter` uses the formatting of the header cells in the original `tabulate::Table` to decide how to align each column. As per the Markdown spec, columns are left-aligned by default.\n\n| S/N       | Movie Name       |     Director    | Estimated Budget |     Release Date |\n| :----     | :----            |      :---:      |            ----: |            ----: |\n| tt1979376 | Toy Story 4      |   Josh Cooley   |     $200,000,000 |     21 June 2019 |\n| tt3263904 | Sully            |  Clint Eastwood |      $60,000,000 | 9 September 2016 |\n| tt1535109 | Captain Phillips | Paul Greengrass |      $55,000,000 |  11 October 2013 |\n\n### AsciiDoc\n\nTabulate can export tables as AsciiDoc using an `AsciiDocExporter`. \n\n```cpp\n#include \u003ctabulate/asciidoc_exporter.hpp\u003e\nusing namespace tabulate;\n\nint main() {\n  Table movies;\n  movies.add_row({\"S/N\", \"Movie Name\", \"Director\", \"Estimated Budget\", \"Release Date\"});\n  movies.add_row({\"tt1979376\", \"Toy Story 4\", \"Josh Cooley\", \"$200,000,000\", \"21 June 2019\"});\n  movies.add_row({\"tt3263904\", \"Sully\", \"Clint Eastwood\", \"$60,000,000\", \"9 September 2016\"});\n  movies.add_row(\n      {\"tt1535109\", \"Captain Phillips\", \"Paul Greengrass\", \"$55,000,000\", \" 11 October 2013\"});\n\n  // center align 'Director' column\n  movies.column(2).format().font_align(FontAlign::center);\n\n  // right align 'Estimated Budget' column\n  movies.column(3).format().font_align(FontAlign::right);\n\n  // right align 'Release Date' column\n  movies.column(4).format().font_align(FontAlign::right);\n\n  movies[1][2].format().font_style({FontStyle::bold, FontStyle::italic});\n  movies[2][1].format().font_style({FontStyle::italic});\n\n  // Color header cells\n  for (size_t i = 0; i \u003c 5; ++i) {\n    movies[0][i]\n        .format()\n        .font_color(Color::white)\n        .font_style({FontStyle::bold})\n        .background_color(Color::blue);\n  }\n\n  AsciiDocExporter exporter;\n  auto asciidoc = exporter.dump(movies);\n\n  // tabulate::table\n  std::cout \u003c\u003c movies \u003c\u003c \"\\n\\n\";\n\n  // Exported AsciiDoc\n  std::cout \u003c\u003c asciidoc \u003c\u003c std::endl;\n}\n```\nBelow is the export of the example above:\n\n```\n[cols=\"\u003c,\u003c,^,\u003e,\u003e\"]\n|===\n|*S/N*|*Movie Name*|*Director*|*Estimated Budget*|*Release Date*\n\n|tt1979376|Toy Story 4|*_Josh Cooley_*|$200,000,000|21 June 2019\n|tt3263904|_Sully_|Clint Eastwood|$60,000,000|9 September 2016\n|tt1535109|Captain Phillips|Paul Greengrass|$55,000,000| 11 October 2013\n|===\n```\nThe rendered output you can see here: http://tpcg.io/pbbfU3ks\n\n**NOTE** Alignment is only supported per column. The font styles `FontStyle::bold` and `FontStyle::italic` can be used for each cell, also in combination.\n\n## Building Samples\n\nThere are a number of samples in the `samples/` directory, e.g., [Mario](https://github.com/p-ranav/tabulate/blob/master/samples/mario.cpp). You can build these samples by running the following commands.\n\n```bash\nmkdir build\ncd build\ncmake -DSAMPLES=ON -DUSE_CPP17=ON ..\nmake\n./samples/mario\n```\n\nNote the `USE_CPP17` variable. `Tabulate` uses `std::variant` and `std::optional`. If you do not have `C++17` compiler support for these data structures, build without this flag. `Tabulate` will then use [variant-lite](https://github.com/martinmoene/variant-lite) and [optional-lite](https://github.com/martinmoene/optional-lite).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"400\" src=\"img/mario.png\"/\u003e  \n\u003c/p\u003e\n\n## Generating Single Header\n\n```bash\npython3 utils/amalgamate/amalgamate.py -c single_include.json -s .\n```\n\n## Contributing\nContributions are welcome, have a look at the [CONTRIBUTING.md](CONTRIBUTING.md) document for more information.\n\n## License\nThe project is available under the [MIT](https://opensource.org/licenses/MIT) license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp-ranav%2Ftabulate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp-ranav%2Ftabulate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp-ranav%2Ftabulate/lists"}