├── .clang-format ├── .github └── workflows │ ├── ci.yml │ └── coverage.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── doc ├── ANSI.md └── tabulate.md ├── images ├── class_diagram.png ├── colors.png ├── iterators.png ├── mario.png ├── markdown_export.png ├── movies.png ├── runic.png ├── styles.png ├── summary.png ├── unicode.png ├── universal_constants.png └── word_wrap.png ├── samples ├── class-diagram.cc ├── colors.cc ├── iterators.cc ├── mario.cc ├── moives.cc ├── refresh-table.cc ├── refresh-table.cc.skip ├── runic.cc ├── styles.cc ├── summary.cc ├── unicode.cc ├── universal-constants.cc └── word-wrap.cc ├── scripts └── 24-bit-color.sh ├── tabulate.cc └── tabulate.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: '-1' 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveMacros: 'true' 6 | AlignConsecutiveAssignments: 'false' 7 | AlignConsecutiveDeclarations: 'false' 8 | AlignEscapedNewlines: Left 9 | AlignOperands: 'true' 10 | AlignTrailingComments: 'true' 11 | AllowAllArgumentsOnNextLine: 'true' 12 | AllowAllConstructorInitializersOnNextLine: 'true' 13 | AllowAllParametersOfDeclarationOnNextLine: 'true' 14 | AllowShortBlocksOnASingleLine: Never 15 | AllowShortCaseLabelsOnASingleLine: 'false' 16 | AllowShortFunctionsOnASingleLine: Empty 17 | AllowShortIfStatementsOnASingleLine: false 18 | AllowShortLambdasOnASingleLine: Inline 19 | AllowShortLoopsOnASingleLine: 'true' 20 | AlwaysBreakAfterDefinitionReturnType: None 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: 'false' 23 | AlwaysBreakTemplateDeclarations: 'Yes' 24 | BinPackArguments: 'true' 25 | BinPackParameters: 'true' 26 | BraceWrapping: 27 | AfterCaseLabel: 'false' 28 | AfterClass: 'false' 29 | AfterControlStatement: 'false' 30 | AfterEnum: 'false' 31 | AfterFunction: 'true' 32 | AfterNamespace: 'true' 33 | AfterObjCDeclaration: 'false' 34 | AfterStruct: 'false' 35 | AfterUnion: 'false' 36 | AfterExternBlock: 'false' 37 | BeforeCatch: 'false' 38 | BeforeElse: 'false' 39 | IndentBraces: 'false' 40 | SplitEmptyFunction: 'true' 41 | SplitEmptyRecord: 'true' 42 | SplitEmptyNamespace: 'true' 43 | BreakBeforeBinaryOperators: NonAssignment 44 | BreakBeforeBraces: Custom 45 | InsertBraces: 'true' 46 | RemoveEmptyLinesInUnwrappedLines: true 47 | BreakBeforeTernaryOperators: 'true' 48 | BreakConstructorInitializers: BeforeColon 49 | BreakInheritanceList: BeforeColon 50 | BreakStringLiterals: 'true' 51 | ColumnLimit: '160' 52 | CompactNamespaces: 'false' 53 | ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' 54 | ConstructorInitializerIndentWidth: '4' 55 | ContinuationIndentWidth: '4' 56 | Cpp11BracedListStyle: 'true' 57 | LambdaBodyIndentation: OuterScope 58 | DerivePointerAlignment: 'false' 59 | DisableFormat: 'false' 60 | ExperimentalAutoDetectBinPacking: 'false' 61 | FixNamespaceComments: 'true' 62 | ForEachMacros: 63 | [ 64 | 'foreach', 65 | 'FOREACH', 66 | 'RANGES_FOR', 67 | 'hlist_for_each_entry_continue', 68 | 'hlist_for_each_entry', 69 | 'hlist_for_each_entry_from', 70 | 'hlist_for_each_entry_safe', 71 | 'hlist_for_each_safe', 72 | 'list_for_each_entry', 73 | 'list_for_each_entry_continue', 74 | 'list_for_each_entry_continue_reverse', 75 | 'list_for_each_entry_from', 76 | 'list_for_each_entry_reverse', 77 | 'list_for_each_entry_safe', 78 | 'list_for_each_entry_safe_continue', 79 | 'list_for_each_entry_safe_from', 80 | 'list_for_each_entry_safe_reverse', 81 | 'list_for_each_from', 82 | 'list_for_each_prev', 83 | 'list_for_each_prev_safe', 84 | 'list_for_each_safe' 85 | ] 86 | TypenameMacros: ['STACK_OF', 'LIST'] 87 | IncludeBlocks: Regroup 88 | IncludeIsMainRegex: '([-_](test|unittest))?$' 89 | IndentCaseLabels: 'true' 90 | IndentPPDirectives: AfterHash 91 | IndentWidth: '2' 92 | IndentWrappedFunctionNames: 'false' 93 | RemoveSemicolon: true 94 | RemoveParentheses: MultipleParentheses 95 | RequiresClausePosition: WithPreceding 96 | RequiresExpressionIndentation: OuterScope 97 | SeparateDefinitionBlocks: Always 98 | KeepEmptyLinesAtTheStartOfBlocks: 'false' 99 | MaxEmptyLinesToKeep: '3' 100 | NamespaceIndentation: None 101 | PenaltyBreakAssignment: '2' 102 | PenaltyBreakBeforeFirstCallParameter: '1' 103 | PenaltyBreakComment: '300' 104 | PenaltyBreakFirstLessLess: '120' 105 | PenaltyBreakString: '1000' 106 | PenaltyBreakTemplateDeclaration: '10' 107 | PenaltyExcessCharacter: '1000000' 108 | PenaltyReturnTypeOnItsOwnLine: '500' 109 | PointerAlignment: Right 110 | RawStringFormats: 111 | - Language: Cpp 112 | Delimiters: 113 | - 'cc' 114 | - 'CC' 115 | - 'cpp' 116 | - 'Cpp' 117 | - 'CPP' 118 | - 'c++' 119 | - 'C++' 120 | CanonicalDelimiter: '' 121 | BasedOnStyle: google 122 | - Language: TextProto 123 | Delimiters: 124 | - 'pb' 125 | - 'PB' 126 | - 'proto' 127 | - 'PROTO' 128 | EnclosingFunctions: 129 | - EqualsProto 130 | - EquivToProto 131 | - PARSE_PARTIAL_TEXT_PROTO 132 | - PARSE_TEST_PROTO 133 | - PARSE_TEXT_PROTO 134 | - ParseTextOrDie 135 | - ParseTextProtoOrDie 136 | CanonicalDelimiter: '' 137 | BasedOnStyle: google 138 | ReflowComments: 'true' 139 | SortIncludes: 'false' 140 | SortUsingDeclarations: 'false' 141 | SpaceAfterCStyleCast: 'false' 142 | SpaceAfterLogicalNot: 'false' 143 | SpaceAfterTemplateKeyword: 'true' 144 | SpaceBeforeAssignmentOperators: 'true' 145 | SpaceBeforeCpp11BracedList: 'false' 146 | SpaceBeforeCtorInitializerColon: 'true' 147 | SpaceBeforeInheritanceColon: 'true' 148 | SpaceBeforeParens: ControlStatements 149 | SpaceBeforeRangeBasedForLoopColon: 'true' 150 | SpaceInEmptyParentheses: 'false' 151 | SpacesBeforeTrailingComments: '1' 152 | SpacesInAngles: 'false' 153 | SpacesInCStyleCastParentheses: 'false' 154 | SpacesInContainerLiterals: 'false' 155 | SpacesInParentheses: 'false' 156 | SpacesInSquareBrackets: 'false' 157 | Standard: Auto 158 | StatementMacros: ['__maybe_unused'] 159 | TabWidth: '2' 160 | UseTab: Never 161 | 162 | --- 163 | Language: C 164 | AccessModifierOffset: '-1' 165 | AlignAfterOpenBracket: Align 166 | AlignConsecutiveMacros: 'true' 167 | AlignConsecutiveAssignments: 'false' 168 | AlignConsecutiveDeclarations: 'false' 169 | AlignEscapedNewlines: Left 170 | AlignOperands: 'true' 171 | AlignTrailingComments: 'true' 172 | AllowAllArgumentsOnNextLine: 'true' 173 | AllowAllParametersOfDeclarationOnNextLine: 'true' 174 | AllowShortBlocksOnASingleLine: Never 175 | AllowShortCaseLabelsOnASingleLine: 'false' 176 | AllowShortFunctionsOnASingleLine: Empty 177 | AllowShortIfStatementsOnASingleLine: false 178 | AllowShortLoopsOnASingleLine: 'true' 179 | AlwaysBreakAfterDefinitionReturnType: None 180 | AlwaysBreakAfterReturnType: None 181 | AlwaysBreakBeforeMultilineStrings: 'false' 182 | BinPackArguments: 'true' 183 | BinPackParameters: 'true' 184 | BraceWrapping: 185 | AfterCaseLabel: 'false' 186 | AfterControlStatement: 'false' 187 | AfterEnum: 'false' 188 | AfterFunction: 'true' 189 | AfterStruct: 'false' 190 | AfterUnion: 'false' 191 | AfterExternBlock: 'false' 192 | BeforeCatch: 'false' 193 | BeforeElse: 'false' 194 | IndentBraces: 'false' 195 | SplitEmptyFunction: 'true' 196 | SplitEmptyRecord: 'true' 197 | BreakBeforeBinaryOperators: NonAssignment 198 | BreakBeforeBraces: Custom 199 | InsertBraces: 'true' 200 | BreakBeforeTernaryOperators: 'true' 201 | BreakStringLiterals: 'true' 202 | ColumnLimit: '160' 203 | ContinuationIndentWidth: '4' 204 | Cpp11BracedListStyle: 'true' 205 | DerivePointerAlignment: 'false' 206 | DisableFormat: 'false' 207 | ExperimentalAutoDetectBinPacking: 'false' 208 | ForEachMacros: 209 | [ 210 | 'foreach', 211 | 'FOREACH', 212 | 'hlist_for_each_entry_continue', 213 | 'hlist_for_each_entry', 214 | 'hlist_for_each_entry_from', 215 | 'hlist_for_each_entry_safe', 216 | 'hlist_for_each_safe', 217 | 'list_for_each_entry', 218 | 'list_for_each_entry_continue', 219 | 'list_for_each_entry_continue_reverse', 220 | 'list_for_each_entry_from', 221 | 'list_for_each_entry_reverse', 222 | 'list_for_each_entry_safe', 223 | 'list_for_each_entry_safe_continue', 224 | 'list_for_each_entry_safe_from', 225 | 'list_for_each_entry_safe_reverse', 226 | 'list_for_each_from', 227 | 'list_for_each_prev', 228 | 'list_for_each_prev_safe', 229 | 'list_for_each_safe' 230 | ] 231 | TypenameMacros: ['STACK_OF', 'LIST'] 232 | IncludeBlocks: Regroup 233 | IncludeIsMainRegex: '([-_](test|unittest))?$' 234 | IndentCaseLabels: 'true' 235 | IndentPPDirectives: AfterHash 236 | IndentWidth: '2' 237 | IndentWrappedFunctionNames: 'false' 238 | KeepEmptyLinesAtTheStartOfBlocks: 'false' 239 | MaxEmptyLinesToKeep: '3' 240 | PenaltyBreakAssignment: '2' 241 | PenaltyBreakBeforeFirstCallParameter: '1' 242 | PenaltyBreakComment: '300' 243 | PenaltyBreakFirstLessLess: '120' 244 | PenaltyBreakString: '1000' 245 | PenaltyExcessCharacter: '1000000' 246 | PenaltyReturnTypeOnItsOwnLine: '500' 247 | PointerAlignment: Right 248 | ReflowComments: 'true' 249 | SortIncludes: 'false' 250 | SpaceAfterCStyleCast: 'false' 251 | SpaceAfterLogicalNot: 'false' 252 | SpaceBeforeAssignmentOperators: 'true' 253 | SpaceBeforeParens: ControlStatements 254 | SpaceInEmptyParentheses: 'false' 255 | SpacesBeforeTrailingComments: '1' 256 | SpacesInCStyleCastParentheses: 'false' 257 | SpacesInContainerLiterals: 'false' 258 | SpacesInParentheses: 'false' 259 | SpacesInSquareBrackets: 'false' 260 | Standard: Auto 261 | StatementMacros: ['__maybe_unused'] 262 | TabWidth: '2' 263 | UseTab: Never 264 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 7 | BUILD_TYPE: Release 8 | 9 | jobs: 10 | build: 11 | # The CMake configure and build commands are platform agnostic and should work equally 12 | # well on Windows or Mac. You can convert this to a matrix build if you need 13 | # cross-platform coverage. 14 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Install requirements 21 | run: | 22 | sudo apt-get update -q -y 23 | sudo apt-get install -q -y gcc g++ cmake libgtest-dev 24 | 25 | - name: Configure CMake 26 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 27 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 28 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 29 | 30 | - name: Build 31 | # Build your program with the given configuration 32 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 33 | 34 | - name: Test 35 | working-directory: ${{github.workspace}}/build 36 | # Execute tests defined by the CMake configuration. 37 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 38 | run: ./tabulate-summary 39 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: coverage 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: [ubuntu-latest] 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | 12 | - name: Install requirements 13 | run: | 14 | sudo apt-get update -q -y 15 | sudo apt-get install -q -y gcc g++ cmake libgtest-dev lcov 16 | 17 | - name: Configure 18 | run: cmake -B ${{github.workspace}}/build -DCOV=ON -DCMAKE_BUILD_TYPE=Debug 19 | 20 | - name: Build 21 | run: cmake --build ${{github.workspace}}/build 22 | 23 | - name: Run Test 24 | working-directory: ${{github.workspace}}/build 25 | run: make test 26 | 27 | - name: Upload To CodeCov 28 | run: bash <(curl -s https://codecov.io/bash) 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # directories 35 | _*/ 36 | **/build* 37 | **/todo 38 | **/export 39 | **/.vscode 40 | **/generated 41 | **/.cache 42 | 43 | **/core.* 44 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project("table maker for modern c++") 3 | 4 | option(COV "Enable coverage" OFF) 5 | if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND COV) 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage") 7 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage") 8 | endif() 9 | 10 | enable_testing() 11 | 12 | add_library(tabulate tabulate.cc) 13 | target_sources(tabulate PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES tabulate.h) 14 | 15 | file(GLOB files samples/*.cc) 16 | add_custom_target(tabulate-all) 17 | foreach (file ${files}) 18 | get_filename_component(sample ${file} NAME_WE) 19 | add_executable(tabulate-${sample} ${file}) 20 | target_link_libraries(tabulate-${sample} tabulate gtest gtest_main) 21 | target_include_directories( 22 | tabulate-${sample} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} 23 | ) 24 | 25 | if (NOT EXISTS "${file}.skip") 26 | add_test( 27 | NAME tabulate-${sample} 28 | COMMAND tabulate-${sample} 29 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 30 | ) 31 | add_dependencies(tabulate-all tabulate-${sample}) 32 | endif () 33 | endforeach () 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Markdown 2 | 3 | # tabulate 4 | 5 | [![license](https://img.shields.io/badge/license-Apache-brightgreen.svg?style=flat)](https://github.com/tqolf/tabulate/blob/master/LICENSE) 6 | [![CI Status](https://github.com/tqolf/tabulate/workflows/ci/badge.svg)](https://github.com/tqolf/tabulate/actions) 7 | [![codecov](https://codecov.io/gh/tqolf/tabulate/branch/master/graph/badge.svg?token=BtMOpzpU1t)](https://codecov.io/gh/tqolf/tabulate) 8 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/tqolf/tabulate?color=red&label=release) 9 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/tqolf/tabulate/pulls) 10 | 11 | ![summary](images/summary.png) 12 | Source for the above image can be found [here](https://github.com/tqolf/tabulate/blob/master/samples/summary.cc) 13 | 14 | ## Table of Contents 15 | 16 | - [Markdown](#markdown) 17 | - [tabulate](#tabulate) 18 | - [Table of Contents](#table-of-contents) 19 | - [Quick Start](#quick-start) 20 | - [Formatting Options](#formatting-options) 21 | - [Word Wrapping](#word-wrapping) 22 | - [Font Alignment](#font-alignment) 23 | - [Font Styles](#font-styles) 24 | - [Cell Colors](#cell-colors) 25 | - [Borders and Corners](#borders-and-corners) 26 | - [Range-based Iteration](#range-based-iteration) 27 | - [Nested Tables](#nested-tables) 28 | - [UTF-8 Support](#utf-8-support) 29 | - [Exporters](#exporters) 30 | - [Markdown](#markdown-1) 31 | - [Building Samples](#building-samples) 32 | - [Contributing](#contributing) 33 | - [License](#license) 34 | - [Colors](#colors) 35 | - [Styles](#styles) 36 | - [Appendix](#appendix) 37 | - [Colors Table](#colors-table) 38 | - [Symbols](#symbols) 39 | 40 | ## Quick Start 41 | 42 | `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/`. 43 | 44 | **NOTE** Tabulate supports `>=C++11`. The rest of this README, however, assumes `C++17` support. 45 | 46 | Create a `Table` object and call `Table.add_rows` to add rows to your table. 47 | 48 | ```cpp 49 | #include "tabulate.h" 50 | 51 | using namespace tabulate; 52 | 53 | int main() 54 | { 55 | Table universal_constants; 56 | 57 | universal_constants.add("Quantity", "Value"); 58 | universal_constants.add("Characteristic impedance of vacuum", "376.730 313 461... Ω"); 59 | universal_constants.add("Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"); 60 | universal_constants.add("Magnetic constant (permeability of free space)", 61 | "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"); 62 | universal_constants.add("Gravitational constant (Newtonian constant of gravitation)", 63 | "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"); 64 | universal_constants.add("Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"); 65 | universal_constants.add("Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"); 66 | universal_constants.add("Speed of light in vacuum", "299 792 458 m·s⁻¹"); 67 | ``` 68 | 69 | You 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. 70 | 71 | ```cpp 72 | universal_constants.format() 73 | .styles(Style::bold) 74 | .border_top(" ") 75 | .border_bottom(" ") 76 | .border_left(" ") 77 | .border_right(" ") 78 | .corner(" "); 79 | ``` 80 | 81 | You 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. 82 | 83 | Now, 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. 84 | 85 | ```cpp 86 | universal_constants[0] 87 | .format() 88 | .border_top_padding(1) 89 | .border_bottom_padding(1) 90 | .align(Align::center) 91 | .styles(Style::underline) 92 | .background_color(Color::red); 93 | ``` 94 | 95 | Calling `Table.column(index)` will return a `Column` object. Similar to rows, you can use `Column.format()` to format all the cells in that column. 96 | 97 | Now, let's change the font color of the second column to yellow: 98 | 99 | ```cpp 100 | universal_constants.column(1).format().color(Color::yellow); 101 | } 102 | ``` 103 | 104 | You 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 105 | 106 | ```cpp 107 | universal_constants[0][1].format().background_color(Color::blue).color(Color::white); 108 | 109 | std::cout << universal_constants.xterm() << std::endl; 110 | } 111 | ``` 112 | 113 | ![universal_constants](images/universal_constants.png) 114 | 115 | ## Formatting Options 116 | 117 | ### Word Wrapping 118 | 119 | `tabulate` supports automatic word-wrapping when printing cells. 120 | 121 | Although 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. 122 | 123 | ```cpp 124 | #include "tabulate.h" 125 | using namespace tabulate; 126 | 127 | int main() 128 | { 129 | Table table; 130 | 131 | table.add("This paragraph contains a veryveryveryveryveryverylong word. The long word will " 132 | "break and word wrap to the next line.", 133 | "This paragraph \nhas embedded '\\n' \ncharacters and\n will break\n exactly " 134 | "where\n you want it\n to\n break."); 135 | 136 | table[0][0].format().width(20); 137 | table[0][1].format().width(50); 138 | 139 | std::cout << table.xterm() << std::endl; 140 | } 141 | ``` 142 | 143 | * The above table has 1 row and 2 columns. 144 | * The first cell has automatic word-wrapping. 145 | * 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. 146 | * **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. 147 | 148 | ![word_wrap](images/word_wrap.png) 149 | 150 | **NOTE**: Both columns in the above table are left-aligned by default. This, however, can be easily changed. 151 | 152 | ### Font Alignment 153 | 154 | `tabulate` supports three font alignment settings: `left`, `center`, and `right`. By default, all table content is left-aligned. To align cells, use `.format().align(alignment)`. 155 | 156 | ```cpp 157 | #include "tabulate.h" 158 | using namespace tabulate; 159 | 160 | int main() 161 | { 162 | tabulate::Table movies; 163 | 164 | movies.add("S/N", "Movie Name", "Director", "Estimated Budget", "Release Date"); 165 | movies.add("tt1979376", "Toy Story 4", "Josh Cooley", 200000000, "21 June 2019"); 166 | movies.add("tt3263904", "Sully", "Clint Eastwood", 60000000, "9 September 2016"); 167 | movies.add("tt1535109", "Captain Phillips", "Paul Greengrass", 55000000, " 11 October 2013"); 168 | 169 | // center align 'Director' column 170 | movies.column(2).format().align(Align::center); 171 | 172 | // right align 'Estimated Budget' column 173 | movies.column(3).format().align(Align::right); 174 | 175 | // right align 'Release Date' column 176 | movies.column(4).format().align(Align::right); 177 | 178 | // Color header cells 179 | for (size_t i = 0; i < movies.column_size(); ++i) { 180 | movies[0][i].format().color(Color::yellow).styles(Style::bold); 181 | } 182 | 183 | std::cout << movies.xterm() << std::endl; 184 | std::cout << "Markdown Table:\n" << movies.markdown() << std::endl; 185 | } 186 | ``` 187 | 188 | ![movies](images/movies.png) 189 | 190 | ### Font Styles 191 | 192 | `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. 193 | 194 | To 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***. 195 | 196 | ```cpp 197 | #include "tabulate.h" 198 | 199 | using namespace tabulate; 200 | 201 | int main() 202 | { 203 | Table table; 204 | table.add("Bold", "Italic", "Bold & Italic", "Blinking"); 205 | table.add("Underline", "Crossed", "faint", "Bold, Italic & Underlined"); 206 | table.add("Doubly Underline", "Invisable", "", ""); 207 | 208 | table[0][0].format().styles(Style::bold); 209 | 210 | table[0][1].format().styles(Style::italic); 211 | 212 | table[0][2].format().styles(Style::bold, Style::italic); 213 | 214 | table[0][3].format().styles(Style::blink); 215 | 216 | table[1][0].format().styles(Style::underline); 217 | 218 | table[1][1].format().styles(Style::crossed); 219 | 220 | table[1][2].format().styles(Style::faint); 221 | 222 | table[1][3].format().styles(Style::bold, Style::italic, Style::underline); 223 | 224 | table[2][0].format().styles(Style::doubly_underline); 225 | table[2][1].format().styles(Style::invisible); 226 | 227 | std::cout << table.xterm() << std::endl; 228 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 229 | } 230 | ``` 231 | 232 | ![styles](images/styles.png) 233 | 234 | **NOTE**: Font styles are applied to the entire cell. Unlike HTML, you cannot currently apply styles to specific words in a cell. 235 | 236 | ### Cell Colors 237 | 238 | There are a number of methods in the `Format` object to color cells - foreground and background - for font, borders, corners, and column separators. `tabulate` supports 8 colors: `grey`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, and `white`, and support **True Color** if possiable. The look of these colors vary depending on your terminal. 239 | 240 | For font, border, and corners, you can call `.format()._color(value)` to set the foreground color and `.format()._background_color(value)` to set the background color. Here's an example: 241 | 242 | ```cpp 243 | #include "tabulate.h" 244 | 245 | using namespace tabulate; 246 | 247 | int main() 248 | { 249 | Table colors; 250 | 251 | colors.add("Font Color is Red", "Font Color is Blue", "Font Color is Green"); 252 | colors.add("Everything is Red", "Everything is Blue", "Everything is Green"); 253 | colors.add("Font Background is Red", "Font Background is Blue", "Font Background is Green"); 254 | 255 | colors[0][0].format().color(Color::red).styles(Style::bold); 256 | colors[0][1].format().color(Color::blue).styles(Style::bold); 257 | colors[0][2].format().color(Color::green).styles(Style::bold); 258 | 259 | colors[1][0] 260 | .format() 261 | .border_left_color(Color::red) 262 | .border_left_background_color(Color::red) 263 | .background_color(Color::red) 264 | .color(Color::red) 265 | .border_right_color(Color::blue) 266 | .border_right_background_color(Color::blue); 267 | 268 | colors[1][1] 269 | .format() 270 | .background_color(Color::blue) 271 | .color(Color::blue) 272 | .border_right_color(Color::green) 273 | .border_right_background_color(Color::green); 274 | 275 | colors[1][2] 276 | .format() 277 | .background_color(Color::green) 278 | .color(Color::green) 279 | .border_right_color(Color::green) 280 | .border_right_background_color(Color::green); 281 | 282 | colors[2][0].format().background_color(Color::red).styles(Style::bold); 283 | colors[2][1].format().background_color(Color::blue).styles(Style::bold); 284 | colors[2][2].format().background_color(Color::green).styles(Style::bold); 285 | 286 | std::cout << colors.xterm() << std::endl; 287 | // std::cout << "Markdown Table:\n" << colors.markdown() << std::endl; 288 | } 289 | ``` 290 | 291 | ![colors](images/colors.png) 292 | 293 | ### Borders and Corners 294 | 295 | `tabulate` allows for fine control over borders and corners. For each border and corner, you can set the text, color, and background color. 296 | 297 | **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. 298 | 299 | **NOTE**: Note the use of `.format().multi_bytes_character(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. 300 | 301 | Here's an example where each border and corner is individually styled: 302 | 303 | ```cpp 304 | #include "tabulate.h" 305 | 306 | using namespace tabulate; 307 | 308 | int main() 309 | { 310 | Table table; 311 | 312 | table.add("ᛏᚺᛁᛊ ᛁᛊ ᚨ ᛊᛏᛟᚱy ᛟᚠᚨ ᛒᛖᚨᚱ ᚨᚾᛞ\n" 313 | "ᚨ ᚹᛟᛚᚠ, ᚹᚺᛟ ᚹᚨᚾᛞᛖᚱᛖᛞ ᛏᚺᛖ\n" 314 | "ᚱᛖᚨᛚᛗᛊ ᚾᛁᚾᛖ ᛏᛟ ᚠᚢᛚᚠᛁᛚᛚ ᚨ ᛈᚱᛟᛗᛁᛊᛖ\n" 315 | "ᛏᛟ ᛟᚾᛖ ᛒᛖᚠᛟᚱᛖ; ᛏᚺᛖy ᚹᚨᛚᚲ ᛏᚺᛖ\n" 316 | "ᛏᚹᛁᛚᛁᚷᚺᛏ ᛈᚨᛏᚺ, ᛞᛖᛊᛏᛁᚾᛖᛞ ᛏᛟ\n" 317 | "ᛞᛁᛊcᛟᚹᛖᚱ ᛏᚺᛖ ᛏᚱᚢᛏᚺ\nᛏᚺᚨᛏ ᛁᛊ ᛏᛟ cᛟᛗᛖ."); 318 | 319 | table[0][0] 320 | .format() 321 | .multi_bytes_character(true) 322 | // Font styling 323 | .styles(Style::bold, Style::faint) 324 | .align(Align::center) 325 | .color(Color::red) 326 | .background_color(Color::yellow) 327 | // Corners 328 | .corner_top_left("ᛰ") 329 | .corner_top_right("ᛯ") 330 | .corner_bottom_left("ᛮ") 331 | .corner_bottom_right("ᛸ") 332 | .corner_top_left_color(Color::cyan) 333 | .corner_top_right_color(Color::yellow) 334 | .corner_bottom_left_color(Color::green) 335 | .corner_bottom_right_color(Color::red) 336 | // Borders 337 | .border_top("ᛜ") 338 | .border_bottom("ᛜ") 339 | .border_left("ᚿ") 340 | .border_right("ᛆ") 341 | .border_left_color(Color::yellow) 342 | .border_right_color(Color::green) 343 | .border_top_color(Color::cyan) 344 | .border_bottom_color(Color::red); 345 | 346 | std::cout << table.xterm() << std::endl; 347 | } 348 | ``` 349 | 350 | ![runic](images/runic.png) 351 | 352 | ### Range-based Iteration 353 | 354 | Hand-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. 355 | 356 | ```cpp 357 | #include "tabulate.h" 358 | using namespace tabulate; 359 | 360 | int main() 361 | { 362 | Table table; 363 | 364 | table.add("Company", "Contact", "Country"); 365 | table.add("Alfreds Futterkiste", "Maria Anders", "Germany"); 366 | table.add("Centro comercial Moctezuma", "Francisco Chang", "Mexico"); 367 | table.add("Ernst Handel", "Roland Mendel", "Austria"); 368 | table.add("Island Trading", "Helen Bennett", "UK"); 369 | table.add("Laughing Bacchus Winecellars", "Yoshi Tannamuri", "Canada"); 370 | table.add("Magazzini Alimentari Riuniti", "Giovanni Rovelli", "Italy"); 371 | 372 | // Set width of cells in each column 373 | table.column(0).format().width(40); 374 | table.column(1).format().width(30); 375 | table.column(2).format().width(30); 376 | 377 | // Iterate over cells in the first row 378 | for (auto &cell : table[0]) { cell.format().styles(Style::underline).align(Align::center); } 379 | 380 | // Iterator over cells in the first column 381 | for (auto &cell : table.column(0)) { 382 | if (cell.get() != "Company") { cell.format().align(Align::right); } 383 | } 384 | 385 | // Iterate over rows in the table 386 | size_t index = 0; 387 | for (auto &row : table) { 388 | // row.format().styles(Style::bold); 389 | 390 | // Set blue background color for alternate rows 391 | if (index > 0 && index % 2 == 0) { 392 | for (auto &cell : row) { cell.format().background_color(Color::blue); } 393 | } 394 | index += 1; 395 | } 396 | 397 | std::cout << table.xterm() << std::endl; 398 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 399 | } 400 | ``` 401 | 402 | ![iterators](images/iterators.png) 403 | 404 | ### Nested Tables 405 | 406 | `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. 407 | 408 | ```cpp 409 | #include "tabulate.h" 410 | using namespace tabulate; 411 | 412 | int main() 413 | { 414 | Table class_diagram; 415 | 416 | // Animal class 417 | { 418 | Table animal; 419 | animal.add("Animal"); 420 | animal[0].format().align(Align::center); 421 | 422 | // Animal properties nested table 423 | { 424 | Table animal_properties; 425 | animal_properties.add("+age: Int"); 426 | animal_properties.add("+gender: String"); 427 | animal_properties.format().width(20); 428 | animal_properties[0].format().hide_border_bottom(); 429 | 430 | animal.add(animal_properties); 431 | } 432 | 433 | // Animal methods nested table 434 | { 435 | Table animal_methods; 436 | animal_methods.add("+isMammal()"); 437 | animal_methods.add("+mate()"); 438 | animal_methods.format().width(20); 439 | animal_methods[0].format().hide_border_bottom(); 440 | 441 | animal.add(animal_methods); 442 | } 443 | animal[1].format().hide_border_bottom(); 444 | 445 | class_diagram.add(animal); 446 | } 447 | 448 | // Add rows in the class diagram for the up-facing arrow 449 | // THanks to center alignment, these will align just fine 450 | class_diagram.add("▲"); 451 | class_diagram[1][0].format().hide_border_bottom().multi_bytes_character(true); 452 | class_diagram.add("|"); 453 | class_diagram[2].format().hide_border_bottom(); 454 | class_diagram.add("|"); 455 | class_diagram[3].format().hide_border_bottom(); 456 | 457 | // Duck class 458 | { 459 | Table duck; 460 | duck.add("Duck"); 461 | 462 | // Duck proeperties nested table 463 | { 464 | Table duck_properties; 465 | duck_properties.add("+beakColor: String = \"yellow\""); 466 | duck_properties.format().width(40); 467 | 468 | duck.add(duck_properties); 469 | } 470 | 471 | // Duck methods nested table 472 | { 473 | Table duck_methods; 474 | duck_methods.add("+swim()"); 475 | duck_methods.add("+quack()"); 476 | duck_methods.format().width(40); 477 | duck_methods[0].format().hide_border_bottom(); 478 | 479 | duck.add(duck_methods); 480 | } 481 | 482 | duck[0].format().align(Align::center); 483 | duck[1].format().hide_border_bottom(); 484 | 485 | class_diagram.add(duck); 486 | } 487 | 488 | // Global styling 489 | class_diagram.format().styles(Style::bold).align(Align::center).width(60).hide_border(); 490 | 491 | std::cout << class_diagram.xterm() << std::endl; 492 | } 493 | ``` 494 | 495 | ![class_diagram](images/class_diagram.png) 496 | 497 | ### UTF-8 Support 498 | 499 | In \*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. 500 | 501 | The following table prints the phrase `I love you` in different languages. Note the use of `.format().multi_bytes_character(true)` for the second column. Remember to do this when dealing with multi-byte characters. 502 | 503 | ```cpp 504 | #include "tabulate.h" 505 | using namespace tabulate; 506 | 507 | int main() 508 | { 509 | Table table; 510 | 511 | table.add("English", "I love you"); 512 | table.add("French", "Je t’aime"); 513 | table.add("Spanish", "Te amo"); 514 | table.add("German", "Ich liebe Dich"); 515 | table.add("Mandarin Chinese", "我爱你"); 516 | table.add("Japanese", "愛してる"); 517 | table.add("Korean", "사랑해 (Saranghae)"); 518 | table.add("Greek", "Σ΄αγαπώ (Se agapo)"); 519 | table.add("Italian", "Ti amo"); 520 | table.add("Russian", "Я тебя люблю (Ya tebya liubliu)"); 521 | table.add("Hebrew", "אני אוהב אותך (Ani ohev otakh)"); 522 | 523 | // Column 1 is using mult-byte characters 524 | table.column(1).format().multi_bytes_character(true); 525 | table.format().corner("♥").styles(Style::bold).corner_color(Color::magenta).border_color(Color::magenta); 526 | 527 | std::cout << table.xterm() << std::endl; 528 | } 529 | ``` 530 | 531 | ![unicode](images/unicode.png) 532 | 533 | You 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. 534 | 535 | ```cpp 536 | // Set English-US locale for first column 537 | table.column(0).format().locale("en_US.UTF-8"); 538 | table[0][1].format().locale("en_US.UTF-8"); 539 | 540 | // Set locale for individual cells 541 | table[1][1].format().locale("fr_FR.UTF-8"); // French 542 | table[2][1].format().locale("es_ES.UTF-8"); // Spanish 543 | table[3][1].format().locale("de_DE.UTF-8"); // German 544 | table[4][1].format().locale("zh_CN.UTF-8"); // Chinese 545 | table[5][1].format().locale("ja_JP.UTF-8"); // Japanese 546 | table[6][1].format().locale("ko_KR.UTF-8"); // Korean 547 | table[7][1].format().locale("el_GR.UTF-8"); // Greek 548 | table[8][1].format().locale("it_IT.UTF-8"); // Italian 549 | table[9][1].format().locale("ru_RU.UTF-8"); // Russian 550 | table[10][1].format().locale("he_IL.UTF-8"); // Hebrew 551 | ``` 552 | 553 | ## Exporters 554 | 555 | ### Markdown 556 | 557 | Tables can be exported to GitHub-flavored markdown using a `table.markdown()` to generate a Markdown-formatted `std::string`. 558 | 559 | ```cpp 560 | #include "tabulate.h" 561 | using namespace tabulate; 562 | 563 | int main() 564 | { 565 | tabulate::Table movies; 566 | 567 | movies.add("S/N", "Movie Name", "Director", "Estimated Budget", "Release Date"); 568 | movies.add("tt1979376", "Toy Story 4", "Josh Cooley", 200000000, "21 June 2019"); 569 | movies.add("tt3263904", "Sully", "Clint Eastwood", 60000000, "9 September 2016"); 570 | movies.add("tt1535109", "Captain Phillips", "Paul Greengrass", 55000000, " 11 October 2013"); 571 | 572 | // center align 'Director' column 573 | movies.column(2).format().align(Align::center); 574 | 575 | // right align 'Estimated Budget' column 576 | movies.column(3).format().align(Align::right); 577 | 578 | // right align 'Release Date' column 579 | movies.column(4).format().align(Align::right); 580 | 581 | // Color header cells 582 | for (size_t i = 0; i < movies.column_size(); ++i) { 583 | movies[0][i].format().color(Color::yellow).styles(Style::bold); 584 | } 585 | 586 | std::cout << movies.xterm() << std::endl; 587 | std::cout << "Markdown Table:\n" << movies.markdown() << std::endl; 588 | } 589 | ``` 590 | 591 | ![markdown_export](images/markdown_export.png) 592 | 593 | The above table renders in Markdown like below. 594 | 595 | **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 `markdown()` 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. **True Color** supported for markdown exporter. 596 | 597 | | **S/N** | **Movie Name** | **Director** | **Estimated Budget** | **Release Date** | 598 | | :------------------------------------------ | :------------------------------------------------- | :----------------------------------------------: | -------------------------------------------------------: | ---------------------------------------------------: | 599 | | tt1979376 | Toy Story 4 | Josh Cooley | 200000000 | 21 June 2019 | 600 | | tt3263904 | Sully | Clint Eastwood | 60000000 | 9 September 2016 | 601 | | tt1535109 | Captain Phillips | Paul Greengrass | 55000000 | 11 October 2013 | 602 | 603 | ## Building Samples 604 | 605 | There are a number of samples in the `samples/` directory. You can build these samples by running the following commands. 606 | 607 | ```bash 608 | cmake -B build 609 | cmake --build build 610 | ``` 611 | 612 | ## Contributing 613 | Contributions are welcome, have a look at the [CONTRIBUTING.md](CONTRIBUTING.md) document for more information. 614 | 615 | ## License 616 | The project is available under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) license. 617 | 618 | 619 | ## Colors 620 | 621 | - xterm 622 | - VT100: `\033[35;47m[magenta on white]\033[m` 623 | - Control Sequence 624 | | Code | Effect | Note | 625 | | :----------------------- | :-------: | :----------------------------------------- | 626 | | CSI n m | SGR | ANSI color code (Select Graphic Rendition) | 627 | | CSI 38 ; 5 ; n m | 256COLOR | Foreground 256 color code | 628 | | ESC 48 ; 5 ; n m | 256COLOR | Background 256 color code | 629 | | CSI 38 ; 2 ; r ; g ; b m | TRUECOLOR | Foreground 24 bit rgb color code | 630 | | ESC 48 ; 2 ; r ; g ; b m | TRUECOLOR | Background 24 bit rgb color code | 631 | 632 | - markdown 633 | - `[magenta on white]` 634 | - `[magenta on white]` 635 | 636 | ## Styles 637 | 638 | - xterm 639 | - https://tintin.mudhalla.net/info/xterm 640 | - https://invisible-island.net/xterm/ctlseqs/ctlseqs.html 641 | 642 | - markdown 643 | - **bold** 644 | - __bold__ 645 | - bold 646 | - faint 647 | - _italic_ 648 | - *italic* 649 | - italic 650 | - italic 651 | - italic 652 | - underline 653 | - underline 654 | - blink 655 | - inverse 656 | - invisible 657 | - ~~crossed~~ 658 | - crossed 659 | 660 | 661 | ## Appendix 662 | 663 | ### Colors Table 664 | 665 | | Name | HEX | RGB | 666 | | :------------------- | :---------------------------------------------------: | -----------------: | 667 | | AliceBlue | #F0F8FF | RGB(240, 248, 255) | 668 | | AntiqueWhite | #FAEBD7 | RGB(250, 235, 215) | 669 | | Aqua | #00FFFF | RGB(0, 255, 255) | 670 | | Aquamarine | #7FFFD4 | RGB(127, 255, 212) | 671 | | Azure | #F0FFFF | RGB(240, 255, 255) | 672 | | Beige | #F5F5DC | RGB(245, 245, 220) | 673 | | Bisque | #FFE4C4 | RGB(255, 228, 196) | 674 | | Black | #000000 | RGB(0, 0, 0) | 675 | | BlanchedAlmond | #FFEBCD | RGB(255, 235, 205) | 676 | | Blue | #0000FF | RGB(0, 0, 255) | 677 | | BlueViolet | #8A2BE2 | RGB(138, 43, 226) | 678 | | Brown | #A52A2A | RGB(165, 42, 42) | 679 | | BurlyWood | #DEB887 | RGB(222, 184, 135) | 680 | | CadetBlue | #5F9EA0 | RGB(95, 158, 160) | 681 | | Chartreuse | #7FFF00 | RGB(127, 255, 0) | 682 | | Chocolate | #D2691E | RGB(210, 105, 30) | 683 | | Coral | #FF7F50 | RGB(255, 127, 80) | 684 | | CornflowerBlue | #6495ED | RGB(100, 149, 237) | 685 | | Cornsilk | #FFF8DC | RGB(255, 248, 220) | 686 | | Crimson | #DC143C | RGB(220, 20, 60) | 687 | | Cyan | #00FFFF | RGB(0, 255, 255) | 688 | | DarkBlue | #00008B | RGB(0, 0, 139) | 689 | | DarkCyan | #008B8B | RGB(0, 139, 139) | 690 | | DarkGoldenRod | #B8860B | RGB(184, 134, 11) | 691 | | DarkGray | #A9A9A9 | RGB(169, 169, 169) | 692 | | DarkGreen | #006400 | RGB(0, 100, 0) | 693 | | DarkKhaki | #BDB76B | RGB(189, 183, 107) | 694 | | DarkMagenta | #8B008B | RGB(139, 0, 139) | 695 | | DarkOliveGreen | #556B2F | RGB(85, 107, 47) | 696 | | Darkorange | #FF8C00 | RGB(255, 140, 0) | 697 | | DarkOrchid | #9932CC | RGB(153, 50, 204) | 698 | | DarkRed | #8B0000 | RGB(139, 0, 0) | 699 | | DarkSalmon | #E9967A | RGB(233, 150, 122) | 700 | | DarkSeaGreen | #8FBC8F | RGB(143, 188, 143) | 701 | | DarkSlateBlue | #483D8B | RGB(72, 61, 139) | 702 | | DarkSlateGray | #2F4F4F | RGB(47, 79, 79) | 703 | | DarkTurquoise | #00CED1 | RGB(0, 206, 209) | 704 | | DarkViolet | #9400D3 | RGB(148, 0, 211) | 705 | | DeepPink | #FF1493 | RGB(255, 20, 147) | 706 | | DeepSkyBlue | #00BFFF | RGB(0, 191, 255) | 707 | | DimGray | #696969 | RGB(105, 105, 105) | 708 | | DodgerBlue | #1E90FF | RGB(30, 144, 255) | 709 | | Feldspar | #D19275 | RGB(209, 146, 117) | 710 | | FireBrick | #B22222 | RGB(178, 34, 34) | 711 | | FloralWhite | #FFFAF0 | RGB(255, 250, 240) | 712 | | ForestGreen | #228B22 | RGB(34, 139, 34) | 713 | | Fuchsia | #FF00FF | RGB(255, 0, 255) | 714 | | Gainsboro | #DCDCDC | RGB(220, 220, 220) | 715 | | GhostWhite | #F8F8FF | RGB(248, 248, 255) | 716 | | Gold | #FFD700 | RGB(255, 215, 0) | 717 | | GoldenRod | #DAA520 | RGB(218, 165, 32) | 718 | | Gray | #808080 | RGB(128, 128, 128) | 719 | | Green | #008000 | RGB(0, 128, 0) | 720 | | GreenYellow | #ADFF2F | RGB(173, 255, 47) | 721 | | HoneyDew | #F0FFF0 | RGB(240, 255, 240) | 722 | | HotPink | #FF69B4 | RGB(255, 105, 180) | 723 | | IndianRed | #CD5C5C | RGB(205, 92, 92) | 724 | | Indigo | #4B0082 | RGB(75, 0, 130) | 725 | | Ivory | #FFFFF0 | RGB(255, 255, 240) | 726 | | Khaki | #F0E68C | RGB(240, 230, 140) | 727 | | Lavender | #E6E6FA | RGB(230, 230, 250) | 728 | | LavenderBlush | #FFF0F5 | RGB(255, 240, 245) | 729 | | LawnGreen | #7CFC00 | RGB(124, 252, 0) | 730 | | LemonChiffon | #FFFACD | RGB(255, 250, 205) | 731 | | LightBlue | #ADD8E6 | RGB(173, 216, 230) | 732 | | LightCoral | #F08080 | RGB(240, 128, 128) | 733 | | LightCyan | #E0FFFF | RGB(224, 255, 255) | 734 | | LightGoldenRodYellow | #FAFAD2 | RGB(250, 250, 210) | 735 | | LightGrey | #D3D3D3 | RGB(211, 211, 211) | 736 | | LightGreen | #90EE90 | RGB(144, 238, 144) | 737 | | LightPink | #FFB6C1 | RGB(255, 182, 193) | 738 | | LightSalmon | #FFA07A | RGB(255, 160, 122) | 739 | | LightSeaGreen | #20B2AA | RGB(32, 178, 170) | 740 | | LightSkyBlue | #87CEFA | RGB(135, 206, 250) | 741 | | LightSlateBlue | #8470FF | RGB(132, 112, 255) | 742 | | LightSlateGray | #778899 | RGB(119, 136, 153) | 743 | | LightSteelBlue | #B0C4DE | RGB(176, 196, 222) | 744 | | LightYellow | #FFFFE0 | RGB(255, 255, 224) | 745 | | Lime | #00FF00 | RGB(0, 255, 0) | 746 | | LimeGreen | #32CD32 | RGB(50, 205, 50) | 747 | | Linen | #FAF0E6 | RGB(250, 240, 230) | 748 | | Magenta | #FF00FF | RGB(255, 0, 255) | 749 | | Maroon | #800000 | RGB(128, 0, 0) | 750 | | MediumAquaMarine | #66CDAA | RGB(102, 205, 170) | 751 | | MediumBlue | #0000CD | RGB(0, 0, 205) | 752 | | MediumOrchid | #BA55D3 | RGB(186, 85, 211) | 753 | | MediumPurple | #9370D8 | RGB(147, 112, 216) | 754 | | MediumSeaGreen | #3CB371 | RGB(60, 179, 113) | 755 | | MediumSlateBlue | #7B68EE | RGB(123, 104, 238) | 756 | | MediumSpringGreen | #00FA9A | RGB(0, 250, 154) | 757 | | MediumTurquoise | #48D1CC | RGB(72, 209, 204) | 758 | | MediumVioletRed | #C71585 | RGB(199, 21, 133) | 759 | | MidnightBlue | #191970 | RGB(25, 25, 112) | 760 | | MintCream | #F5FFFA | RGB(245, 255, 250) | 761 | | MistyRose | #FFE4E1 | RGB(255, 228, 225) | 762 | | Moccasin | #FFE4B5 | RGB(255, 228, 181) | 763 | | NavajoWhite | #FFDEAD | RGB(255, 222, 173) | 764 | | Navy | #000080 | RGB(0, 0, 128) | 765 | | OldLace | #FDF5E6 | RGB(253, 245, 230) | 766 | | Olive | #808000 | RGB(128, 128, 0) | 767 | | OliveDrab | #6B8E23 | RGB(107, 142, 35) | 768 | | Orange | #FFA500 | RGB(255, 165, 0) | 769 | | OrangeRed | #FF4500 | RGB(255, 69, 0) | 770 | | Orchid | #DA70D6 | RGB(218, 112, 214) | 771 | | PaleGoldenRod | #EEE8AA | RGB(238, 232, 170) | 772 | | PaleGreen | #98FB98 | RGB(152, 251, 152) | 773 | | PaleTurquoise | #AFEEEE | RGB(175, 238, 238) | 774 | | PaleVioletRed | #D87093 | RGB(216, 112, 147) | 775 | | PapayaWhip | #FFEFD5 | RGB(255, 239, 213) | 776 | | PeachPuff | #FFDAB9 | RGB(255, 218, 185) | 777 | | Peru | #CD853F | RGB(205, 133, 63) | 778 | | Pink | #FFC0CB | RGB(255, 192, 203) | 779 | | Plum | #DDA0DD | RGB(221, 160, 221) | 780 | | PowderBlue | #B0E0E6 | RGB(176, 224, 230) | 781 | | Purple | #800080 | RGB(128, 0, 128) | 782 | | Red | #FF0000 | RGB(255, 0, 0) | 783 | | RosyBrown | #BC8F8F | RGB(188, 143, 143) | 784 | | RoyalBlue | #4169E1 | RGB(65, 105, 225) | 785 | | SaddleBrown | #8B4513 | RGB(139, 69, 19) | 786 | | Salmon | #FA8072 | RGB(250, 128, 114) | 787 | | SandyBrown | #F4A460 | RGB(244, 164, 96) | 788 | | SeaGreen | #2E8B57 | RGB(46, 139, 87) | 789 | | SeaShell | #FFF5EE | RGB(255, 245, 238) | 790 | | Sienna | #A0522D | RGB(160, 82, 45) | 791 | | Silver | #C0C0C0 | RGB(192, 192, 192) | 792 | | SkyBlue | #87CEEB | RGB(135, 206, 235) | 793 | | SlateBlue | #6A5ACD | RGB(106, 90, 205) | 794 | | SlateGray | #708090 | RGB(112, 128, 144) | 795 | | Snow | #FFFAFA | RGB(255, 250, 250) | 796 | | SpringGreen | #00FF7F | RGB(0, 255, 127) | 797 | | SteelBlue | #4682B4 | RGB(70, 130, 180) | 798 | | Tan | #D2B48C | RGB(210, 180, 140) | 799 | | Teal | #008080 | RGB(0, 128, 128) | 800 | | Thistle | #D8BFD8 | RGB(216, 191, 216) | 801 | | Tomato | #FF6347 | RGB(255, 99, 71) | 802 | | Turquoise | #40E0D0 | RGB(64, 224, 208) | 803 | | Violet | #EE82EE | RGB(238, 130, 238) | 804 | | VioletRed | #D02090 | RGB(208, 32, 144) | 805 | | Wheat | #F5DEB3 | RGB(245, 222, 179) | 806 | | White | #FFFFFF | RGB(255, 255, 255) | 807 | | WhiteSmoke | #F5F5F5 | RGB(245, 245, 245) | 808 | | Yellow | #FFFF00 | RGB(255, 255, 0) | 809 | | YellowGreen | #9ACD32 | RGB(154, 205, 50) | 810 | 811 | 812 | ## Symbols 813 | | Name | Main | Fallback | 814 | | ------------------------------------------- | :---: | :------: | 815 | | tick | `✔` | `√` | 816 | | info | `ℹ` | `i` | 817 | | warning | `⚠` | `‼` | 818 | | cross | `✘` | `×` | 819 | | square | `█` | | 820 | | squareSmall | `◻` | `□` | 821 | | squareSmallFilled | `◼` | `■` | 822 | | squareDarkShade | `▓` | | 823 | | squareMediumShade | `▒` | | 824 | | squareLightShade | `░` | | 825 | | squareTop | `▀` | | 826 | | squareBottom | `▄` | | 827 | | squareLeft | `▌` | | 828 | | squareRight | `▐` | | 829 | | squareCenter | `■` | | 830 | | circle | `◯` | `( )` | 831 | | circleFilled | `◉` | `(*)` | 832 | | circleDotted | `◌` | `( )` | 833 | | circleDouble | `◎` | `( )` | 834 | | circleCircle | `ⓞ` | `(○)` | 835 | | circleCross | `ⓧ` | `(×)` | 836 | | circlePipe | `Ⓘ` | `(│)` | 837 | | circleQuestionMark | `?⃝ ` | `(?)` | 838 | | radioOn | `◉` | `(*)` | 839 | | radioOff | `◯` | `( )` | 840 | | checkboxOn | `☒` | `[×]` | 841 | | checkboxOff | `☐` | `[ ]` | 842 | | checkboxCircleOn | `ⓧ` | `(×)` | 843 | | checkboxCircleOff | `Ⓘ` | `( )` | 844 | | questionMarkPrefix | `?⃝ ` | `?` | 845 | | bullet | `●` | | 846 | | dot | `․` | | 847 | | ellipsis | `…` | | 848 | | pointer | `❯` | `>` | 849 | | pointerSmall | `›` | `›` | 850 | | triangleUp | `▲` | | 851 | | triangleUpSmall | `▴` | | 852 | | triangleUpOutline | `△` | `∆` | 853 | | triangleDown | `▼` | | 854 | | triangleDownSmall | `▾` | | 855 | | triangleLeft | `◀` | `◄` | 856 | | triangleLeftSmall | `◂` | | 857 | | triangleRight | `▶` | `►` | 858 | | triangleRightSmall | `▸` | | 859 | | lozenge | `◆` | `♦` | 860 | | lozengeOutline | `◇` | `◊` | 861 | | home | `⌂` | | 862 | | hamburger | `☰` | `≡` | 863 | | smiley | `㋡` | `☺` | 864 | | mustache | `෴` | `┌─┐` | 865 | | heart | `♥` | | 866 | | star | `★` | `✶` | 867 | | play | `▶` | `►` | 868 | | musicNote | `♪` | | 869 | | musicNoteBeamed | `♫` | | 870 | | nodejs | `⬢` | `♦` | 871 | | arrowUp | `↑` | | 872 | | arrowDown | `↓` | | 873 | | arrowLeft | `←` | | 874 | | arrowRight | `→` | | 875 | | arrowLeftRight | `↔` | | 876 | | arrowUpDown | `↕` | | 877 | | almostEqual | `≈` | | 878 | | notEqual | `≠` | | 879 | | lessOrEqual | `≤` | | 880 | | greaterOrEqual | `≥` | | 881 | | identical | `≡` | | 882 | | infinity | `∞` | | 883 | | subscriptZero | `₀` | | 884 | | subscriptOne | `₁` | | 885 | | subscriptTwo | `₂` | | 886 | | subscriptThree | `₃` | | 887 | | subscriptFour | `₄` | | 888 | | subscriptFive | `₅` | | 889 | | subscriptSix | `₆` | | 890 | | subscriptSeven | `₇` | | 891 | | subscriptEight | `₈` | | 892 | | subscriptNine | `₉` | | 893 | | oneHalf | `½` | | 894 | | oneThird | `⅓` | | 895 | | oneQuarter | `¼` | | 896 | | oneFifth | `⅕` | | 897 | | oneSixth | `⅙` | | 898 | | oneSeventh | `⅐` | `1/7` | 899 | | oneEighth | `⅛` | | 900 | | oneNinth | `⅑` | `1/9` | 901 | | oneTenth | `⅒` | `1/10` | 902 | | twoThirds | `⅔` | | 903 | | twoFifths | `⅖` | | 904 | | threeQuarters | `¾` | | 905 | | threeFifths | `⅗` | | 906 | | threeEighths | `⅜` | | 907 | | fourFifths | `⅘` | | 908 | | fiveSixths | `⅚` | | 909 | | fiveEighths | `⅝` | | 910 | | sevenEighths | `⅞` | | 911 | | line | `─` | | 912 | | lineBold | `━` | | 913 | | lineDouble | `═` | | 914 | | lineDashed0 | `┄` | | 915 | | lineDashed1 | `┅` | | 916 | | lineDashed2 | `┈` | | 917 | | lineDashed3 | `┉` | | 918 | | lineDashed4 | `╌` | | 919 | | lineDashed5 | `╍` | | 920 | | lineDashed6 | `╴` | | 921 | | lineDashed7 | `╶` | | 922 | | lineDashed8 | `╸` | | 923 | | lineDashed9 | `╺` | | 924 | | lineDashed10 | `╼` | | 925 | | lineDashed11 | `╾` | | 926 | | lineDashed12 | `−` | | 927 | | lineDashed13 | `–` | | 928 | | lineDashed14 | `‐` | | 929 | | lineDashed15 | `⁃` | | 930 | | lineVertical | `│` | | 931 | | lineVerticalBold | `┃` | | 932 | | lineVerticalDouble | `║` | | 933 | | lineVerticalDashed0 | `┆` | | 934 | | lineVerticalDashed1 | `┇` | | 935 | | lineVerticalDashed2 | `┊` | | 936 | | lineVerticalDashed3 | `┋` | | 937 | | lineVerticalDashed4 | `╎` | | 938 | | lineVerticalDashed5 | `╏` | | 939 | | lineVerticalDashed6 | `╵` | | 940 | | lineVerticalDashed7 | `╷` | | 941 | | lineVerticalDashed8 | `╹` | | 942 | | lineVerticalDashed9 | `╻` | | 943 | | lineVerticalDashed10 | `╽` | | 944 | | lineVerticalDashed11 | `╿` | | 945 | | lineDownLeft | `┐` | | 946 | | lineDownLeftArc | `╮` | | 947 | | lineDownBoldLeftBold | `┓` | | 948 | | lineDownBoldLeft | `┒` | | 949 | | lineDownLeftBold | `┑` | | 950 | | lineDownDoubleLeftDouble | `╗` | | 951 | | lineDownDoubleLeft | `╖` | | 952 | | lineDownLeftDouble | `╕` | | 953 | | lineDownRight | `┌` | | 954 | | lineDownRightArc | `╭` | | 955 | | lineDownBoldRightBold | `┏` | | 956 | | lineDownBoldRight | `┎` | | 957 | | lineDownRightBold | `┍` | | 958 | | lineDownDoubleRightDouble | `╔` | | 959 | | lineDownDoubleRight | `╓` | | 960 | | lineDownRightDouble | `╒` | | 961 | | lineUpLeft | `┘` | | 962 | | lineUpLeftArc | `╯` | | 963 | | lineUpBoldLeftBold | `┛` | | 964 | | lineUpBoldLeft | `┚` | | 965 | | lineUpLeftBold | `┙` | | 966 | | lineUpDoubleLeftDouble | `╝` | | 967 | | lineUpDoubleLeft | `╜` | | 968 | | lineUpLeftDouble | `╛` | | 969 | | lineUpRight | `└` | | 970 | | lineUpRightArc | `╰` | | 971 | | lineUpBoldRightBold | `┗` | | 972 | | lineUpBoldRight | `┖` | | 973 | | lineUpRightBold | `┕` | | 974 | | lineUpDoubleRightDouble | `╚` | | 975 | | lineUpDoubleRight | `╙` | | 976 | | lineUpRightDouble | `╘` | | 977 | | lineUpDownLeft | `┤` | | 978 | | lineUpBoldDownBoldLeftBold | `┫` | | 979 | | lineUpBoldDownBoldLeft | `┨` | | 980 | | lineUpDownLeftBold | `┥` | | 981 | | lineUpBoldDownLeftBold | `┩` | | 982 | | lineUpDownBoldLeftBold | `┪` | | 983 | | lineUpDownBoldLeft | `┧` | | 984 | | lineUpBoldDownLeft | `┦` | | 985 | | lineUpDoubleDownDoubleLeftDouble | `╣` | | 986 | | lineUpDoubleDownDoubleLeft | `╢` | | 987 | | lineUpDownLeftDouble | `╡` | | 988 | | lineUpDownRight | `├` | | 989 | | lineUpBoldDownBoldRightBold | `┣` | | 990 | | lineUpBoldDownBoldRight | `┠` | | 991 | | lineUpDownRightBold | `┝` | | 992 | | lineUpBoldDownRightBold | `┡` | | 993 | | lineUpDownBoldRightBold | `┢` | | 994 | | lineUpDownBoldRight | `┟` | | 995 | | lineUpBoldDownRight | `┞` | | 996 | | lineUpDoubleDownDoubleRightDouble | `╠` | | 997 | | lineUpDoubleDownDoubleRight | `╟` | | 998 | | lineUpDownRightDouble | `╞` | | 999 | | lineDownLeftRight | `┬` | | 1000 | | lineDownBoldLeftBoldRightBold | `┳` | | 1001 | | lineDownLeftBoldRightBold | `┯` | | 1002 | | lineDownBoldLeftRight | `┰` | | 1003 | | lineDownBoldLeftBoldRight | `┱` | | 1004 | | lineDownBoldLeftRightBold | `┲` | | 1005 | | lineDownLeftRightBold | `┮` | | 1006 | | lineDownLeftBoldRight | `┭` | | 1007 | | lineDownDoubleLeftDoubleRightDouble | `╦` | | 1008 | | lineDownDoubleLeftRight | `╥` | | 1009 | | lineDownLeftDoubleRightDouble | `╤` | | 1010 | | lineUpLeftRight | `┴` | | 1011 | | lineUpBoldLeftBoldRightBold | `┻` | | 1012 | | lineUpLeftBoldRightBold | `┷` | | 1013 | | lineUpBoldLeftRight | `┸` | | 1014 | | lineUpBoldLeftBoldRight | `┹` | | 1015 | | lineUpBoldLeftRightBold | `┺` | | 1016 | | lineUpLeftRightBold | `┶` | | 1017 | | lineUpLeftBoldRight | `┵` | | 1018 | | lineUpDoubleLeftDoubleRightDouble | `╩` | | 1019 | | lineUpDoubleLeftRight | `╨` | | 1020 | | lineUpLeftDoubleRightDouble | `╧` | | 1021 | | lineUpDownLeftRight | `┼` | | 1022 | | lineUpBoldDownBoldLeftBoldRightBold | `╋` | | 1023 | | lineUpDownBoldLeftBoldRightBold | `╈` | | 1024 | | lineUpBoldDownLeftBoldRightBold | `╇` | | 1025 | | lineUpBoldDownBoldLeftRightBold | `╊` | | 1026 | | lineUpBoldDownBoldLeftBoldRight | `╉` | | 1027 | | lineUpBoldDownLeftRight | `╀` | | 1028 | | lineUpDownBoldLeftRight | `╁` | | 1029 | | lineUpDownLeftBoldRight | `┽` | | 1030 | | lineUpDownLeftRightBold | `┾` | | 1031 | | lineUpBoldDownBoldLeftRight | `╂` | | 1032 | | lineUpDownLeftBoldRightBold | `┿` | | 1033 | | lineUpBoldDownLeftBoldRight | `╃` | | 1034 | | lineUpBoldDownLeftRightBold | `╄` | | 1035 | | lineUpDownBoldLeftBoldRight | `╅` | | 1036 | | lineUpDownBoldLeftRightBold | `╆` | | 1037 | | lineUpDoubleDownDoubleLeftDoubleRightDouble | `╬` | | 1038 | | lineUpDoubleDownDoubleLeftRight | `╫` | | 1039 | | lineUpDownLeftDoubleRightDouble | `╪` | | 1040 | | lineCross | `╳` | | 1041 | | lineBackslash | `╲` | | 1042 | | lineSlash | `╱` | | 1043 | -------------------------------------------------------------------------------- /doc/ANSI.md: -------------------------------------------------------------------------------- 1 | # ANSI Escape Sequences 2 | 3 | Standard escape codes are prefixed with `Escape`: 4 | 5 | - Ctrl-Key: `^[` 6 | - Octal: `\033` 7 | - Unicode: `\u001b` 8 | - Hexadecimal: `\x1B` 9 | - Decimal: `27` 10 | 11 | Followed by the command, somtimes delimited by opening square bracket (`[`), known as a Control Sequence Introducer (CSI), optionally followed by arguments and the command itself. 12 | 13 | Arguments are delimeted by semi colon (`;`). 14 | 15 | For example: 16 | 17 | ```sh 18 | \x1b[1;31m # Set style to bold, red foreground. 19 | ``` 20 | 21 | ## Sequences 22 | 23 | - `ESC` - sequence starting with `ESC` (`\x1B`) 24 | - `CSI` - Control Sequence Introducer: sequence starting with `ESC [` or CSI (`\x9B`) 25 | - `DCS` - Device Control String: sequence starting with `ESC P` or DCS (`\x90`) 26 | - `OSC` - Operating System Command: sequence starting with `ESC ]` or OSC (`\x9D`) 27 | 28 | Any whitespaces between sequences and arguments should be ignored. They are present for improved readability. 29 | 30 | ## General ASCII Codes 31 | 32 | | Name | decimal | octal | hex | C-escape | Ctrl-Key | Description | 33 | | ----- | ------- | ----- | ---- | ---------------- | -------- | ------------------------------ | 34 | | `BEL` | 7 | 007 | 0x07 | `\a` | `^G` | Terminal bell | 35 | | `BS` | 8 | 010 | 0x08 | `\b` | `^H` | Backspace | 36 | | `HT` | 9 | 011 | 0x09 | `\t` | `^I` | Horizontal TAB | 37 | | `LF` | 10 | 012 | 0x0A | `\n` | `^J` | Linefeed (newline) | 38 | | `VT` | 11 | 013 | 0x0B | `\v` | `^K` | Vertical TAB | 39 | | `FF` | 12 | 014 | 0x0C | `\f` | `^L` | Formfeed (also: New page `NP`) | 40 | | `CR` | 13 | 015 | 0x0D | `\r` | `^M` | Carriage return | 41 | | `ESC` | 27 | 033 | 0x1B | `\e`[*](#escape) | `^[` | Escape character | 42 | | `DEL` | 127 | 177 | 0x7F | `` | `` | Delete character | 43 | 44 |
45 | 46 | > **Note:** Some control escape sequences, like `\e` for `ESC`, are not guaranteed to work in all languages and compilers. It is recommended to use the decimal, octal or hex representation as escape code. 47 | 48 | 49 | 50 | > **Note:** The **Ctrl-Key** representation is simply associating the non-printable characters from ASCII code 1 with the printable (letter) characters from ASCII code 65 ("A"). ASCII code 1 would be `^A` (Ctrl-A), while ASCII code 7 (BEL) would be `^G` (Ctrl-G). This is a common representation (and input method) and historically comes from one of the VT series of terminals. 51 | 52 | ## Cursor Controls 53 | 54 | | ESC Code Sequence | Description | 55 | | :------------------------------------------------- | :----------------------------------------------------- | 56 | | `ESC[H` | moves cursor to home position (0, 0) | 57 | | `ESC[{line};{column}H`
`ESC[{line};{column}f` | moves cursor to line #, column # | 58 | | `ESC[#A` | moves cursor up # lines | 59 | | `ESC[#B` | moves cursor down # lines | 60 | | `ESC[#C` | moves cursor right # columns | 61 | | `ESC[#D` | moves cursor left # columns | 62 | | `ESC[#E` | moves cursor to beginning of next line, # lines down | 63 | | `ESC[#F` | moves cursor to beginning of previous line, # lines up | 64 | | `ESC[#G` | moves cursor to column # | 65 | | `ESC[6n` | request cursor position (reports as `ESC[#;#R`) | 66 | | `ESC M` | moves cursor one line up, scrolling if needed | 67 | | `ESC 7` | save cursor position (DEC) | 68 | | `ESC 8` | restores the cursor to the last saved position (DEC) | 69 | | `ESC[s` | save cursor position (SCO) | 70 | | `ESC[u` | restores the cursor to the last saved position (SCO) | 71 | 72 | > **Note:** Some sequences, like saving and restoring cursors, are private sequences and are not standardized. While some terminal emulators (i.e. xterm and derived) support both SCO and DEC sequences, they are likely to have different functionality. It is therefore recommended to use DEC sequences. 73 | 74 | ## Erase Functions 75 | 76 | | ESC Code Sequence | Description | 77 | | :---------------- | :--------------------------------------- | 78 | | `ESC[J` | erase in display (same as ESC\[0J) | 79 | | `ESC[0J` | erase from cursor until end of screen | 80 | | `ESC[1J` | erase from cursor to beginning of screen | 81 | | `ESC[2J` | erase entire screen | 82 | | `ESC[3J` | erase saved lines | 83 | | `ESC[K` | erase in line (same as ESC\[0K) | 84 | | `ESC[0K` | erase from cursor to end of line | 85 | | `ESC[1K` | erase start of line to the cursor | 86 | | `ESC[2K` | erase the entire line | 87 | 88 | > Note: Erasing the line won't move the cursor, meaning that the cursor will stay at the last position it was at before the line was erased. You can use `\r` after erasing the line, to return the cursor to the start of the current line. 89 | 90 | ## Colors / Graphics Mode 91 | 92 | | ESC Code Sequence | Reset Sequence | Description | 93 | | :---------------- | :------------- | :--------------------------------------------------------- | 94 | | `ESC[1;34;{...}m` | | Set graphics modes for cell, separated by semicolon (`;`). | 95 | | `ESC[0m` | | reset all modes (styles and colors) | 96 | | `ESC[1m` | `ESC[22m` | set bold mode. | 97 | | `ESC[2m` | `ESC[22m` | set dim/faint mode. | 98 | | `ESC[3m` | `ESC[23m` | set italic mode. | 99 | | `ESC[4m` | `ESC[24m` | set underline mode. | 100 | | `ESC[5m` | `ESC[25m` | set blinking mode | 101 | | `ESC[7m` | `ESC[27m` | set inverse/reverse mode | 102 | | `ESC[8m` | `ESC[28m` | set hidden/invisible mode | 103 | | `ESC[9m` | `ESC[29m` | set strikethrough mode. | 104 | 105 | > **Note:** Some terminals may not support some of the graphic mode sequences listed above. 106 | 107 | > **Note:** Both dim and bold modes are reset with the `ESC[22m` sequence. The `ESC[21m` sequence is a non-specified sequence for double underline mode and only work in some terminals and is reset with `ESC[24m`. 108 | 109 | ### Color codes 110 | 111 | Most terminals support 8 and 16 colors, as well as 256 (8-bit) colors. These colors are set by the user, but have commonly defined meanings. 112 | 113 | #### 8-16 Colors 114 | 115 | | Color Name | Foreground Color Code | Background Color Code | 116 | | :--------- | :-------------------- | :-------------------- | 117 | | Black | `30` | `40` | 118 | | Red | `31` | `41` | 119 | | Green | `32` | `42` | 120 | | Yellow | `33` | `43` | 121 | | Blue | `34` | `44` | 122 | | Magenta | `35` | `45` | 123 | | Cyan | `36` | `46` | 124 | | White | `37` | `47` | 125 | | Default | `39` | `49` | 126 | | Reset | `0` | `0` | 127 | 128 | > **Note:** the _Reset_ color is the reset code that resets _all_ colors and text effects, Use _Default_ color to reset colors only. 129 | 130 | Most terminals, apart from the basic set of 8 colors, also support the "bright" or "bold" colors. These have their own set of codes, mirroring the normal colors, but with an additional `;1` in their codes: 131 | 132 | ```sh 133 | # Set style to bold, red foreground. 134 | \x1b[1;31mHello 135 | # Set style to dimmed white foreground with red background. 136 | \x1b[2;37;41mWorld 137 | ``` 138 | 139 | Terminals that support the [aixterm specification](https://sites.ualberta.ca/dept/chemeng/AIX-43/share/man/info/C/a_doc_lib/cmds/aixcmds1/aixterm.htm) provides bright versions of the ISO colors, without the need to use the bold modifier: 140 | 141 | | Color Name | Foreground Color Code | Background Color Code | 142 | | :------------- | :-------------------- | :-------------------- | 143 | | Bright Black | `90` | `100` | 144 | | Bright Red | `91` | `101` | 145 | | Bright Green | `92` | `102` | 146 | | Bright Yellow | `93` | `103` | 147 | | Bright Blue | `94` | `104` | 148 | | Bright Magenta | `95` | `105` | 149 | | Bright Cyan | `96` | `106` | 150 | | Bright White | `97` | `107` | 151 | 152 | #### 256 Colors 153 | 154 | The following escape codes tells the terminal to use the given color ID: 155 | 156 | | ESC Code Sequence | Description | 157 | | :---------------- | :-------------------- | 158 | | `ESC[38;5;{ID}m` | Set foreground color. | 159 | | `ESC[48;5;{ID}m` | Set background color. | 160 | 161 | Where `{ID}` should be replaced with the color index from 0 to 255 of the following color table: 162 | 163 | ![256 Color table](https://user-images.githubusercontent.com/995050/47952855-ecb12480-df75-11e8-89d4-ac26c50e80b9.png) 164 | 165 | The table starts with the original 16 colors (0-15). 166 | 167 | The proceeding 216 colors (16-231) or formed by a 3bpc RGB value offset by 16, packed into a single value. 168 | 169 | The final 24 colors (232-255) are grayscale starting from a shade slighly lighter than black, ranging up to shade slightly darker than white. 170 | 171 | Some emulators interpret these steps as linear increments (`256 / 24`) on all three channels, although some emulators may explicitly define these values. 172 | 173 | #### RGB Colors 174 | 175 | More modern terminals supports [Truecolor](https://en.wikipedia.org/wiki/Color_depth#True_color_.2824-bit.29) (24-bit RGB), which allows you to set foreground and background colors using RGB. 176 | 177 | These escape sequences are usually not well documented. 178 | 179 | | ESC Code Sequence | Description | 180 | | :---------------------- | :--------------------------- | 181 | | `ESC[38;2;{r};{g};{b}m` | Set foreground color as RGB. | 182 | | `ESC[48;2;{r};{g};{b}m` | Set background color as RGB. | 183 | 184 | > Note that `;38` and `;48` corresponds to the 16 color sequence and is interpreted by the terminal to set the foreground and background color respectively. Where as `;2` and `;5` sets the color format. 185 | 186 | ## Screen Modes 187 | 188 | ### Set Mode 189 | 190 | | ESC Code Sequence | Description | 191 | | :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 192 | | `ESC[={value}h` | Changes the screen width or type to the mode specified by value. | 193 | | `ESC[=0h` | 40 x 25 monochrome (text) | 194 | | `ESC[=1h` | 40 x 25 color (text) | 195 | | `ESC[=2h` | 80 x 25 monochrome (text) | 196 | | `ESC[=3h` | 80 x 25 color (text) | 197 | | `ESC[=4h` | 320 x 200 4-color (graphics) | 198 | | `ESC[=5h` | 320 x 200 monochrome (graphics) | 199 | | `ESC[=6h` | 640 x 200 monochrome (graphics) | 200 | | `ESC[=7h` | Enables line wrapping | 201 | | `ESC[=13h` | 320 x 200 color (graphics) | 202 | | `ESC[=14h` | 640 x 200 color (16-color graphics) | 203 | | `ESC[=15h` | 640 x 350 monochrome (2-color graphics) | 204 | | `ESC[=16h` | 640 x 350 color (16-color graphics) | 205 | | `ESC[=17h` | 640 x 480 monochrome (2-color graphics) | 206 | | `ESC[=18h` | 640 x 480 color (16-color graphics) | 207 | | `ESC[=19h` | 320 x 200 color (256-color graphics) | 208 | | `ESC[={value}l` | Resets the mode by using the same values that Set Mode uses, except for 7, which disables line wrapping. The last character in this escape sequence is a lowercase L. | 209 | 210 | ### Common Private Modes 211 | 212 | These are some examples of private modes, which are not defined by the specification, but are implemented in most terminals. 213 | 214 | | ESC Code Sequence | Description | 215 | | :---------------- | :------------------------------ | 216 | | `ESC[?25l` | make cursor invisible | 217 | | `ESC[?25h` | make cursor visible | 218 | | `ESC[?47l` | restore screen | 219 | | `ESC[?47h` | save screen | 220 | | `ESC[?1049h` | enables the alternative buffer | 221 | | `ESC[?1049l` | disables the alternative buffer | 222 | 223 | Refer to the [XTerm Control Sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html) for a more in-depth list of private modes defined by XTerm. 224 | 225 | > Note: While these modes may be supported by the most terminals, some may not work in multiplexers like tmux. 226 | 227 | ### Keyboard Strings 228 | 229 | ```sh 230 | ESC[{code};{string};{...}p 231 | ``` 232 | 233 | Redefines a keyboard key to a specified string. 234 | 235 | The parameters for this escape sequence are defined as follows: 236 | 237 | - `code` is one or more of the values listed in the following table. These values represent keyboard keys and key combinations. When using these values in a command, you must type the semicolons shown in this table in addition to the semicolons required by the escape sequence. The codes in parentheses are not available on some keyboards. `ANSI.SYS` will not interpret the codes in parentheses for those keyboards unless you specify the `/X` switch in the `DEVICE` command for `ANSI.SYS`. 238 | 239 | - `string` is either the ASCII code for a single character or a string contained in quotation marks. For example, both 65 and "A" can be used to represent an uppercase A. 240 | 241 | > **IMPORTANT:** Some of the values in the following table are not valid for all computers. Check your computer's documentation for values that are different. 242 | 243 | #### List of keyboard strings 244 | 245 | | Key | Code | SHIFT+code | CTRL+code | ALT+code | 246 | | ------------------------ | -------- | ---------- | --------- | --------- | 247 | | F1 | 0;59 | 0;84 | 0;94 | 0;104 | 248 | | F2 | 0;60 | 0;85 | 0;95 | 0;105 | 249 | | F3 | 0;61 | 0;86 | 0;96 | 0;106 | 250 | | F4 | 0;62 | 0;87 | 0;97 | 0;107 | 251 | | F5 | 0;63 | 0;88 | 0;98 | 0;108 | 252 | | F6 | 0;64 | 0;89 | 0;99 | 0;109 | 253 | | F7 | 0;65 | 0;90 | 0;100 | 0;110 | 254 | | F8 | 0;66 | 0;91 | 0;101 | 0;111 | 255 | | F9 | 0;67 | 0;92 | 0;102 | 0;112 | 256 | | F10 | 0;68 | 0;93 | 0;103 | 0;113 | 257 | | F11 | 0;133 | 0;135 | 0;137 | 0;139 | 258 | | F12 | 0;134 | 0;136 | 0;138 | 0;140 | 259 | | HOME (num keypad) | 0;71 | 55 | 0;119 | \-- | 260 | | UP ARROW (num keypad) | 0;72 | 56 | (0;141) | \-- | 261 | | PAGE UP (num keypad) | 0;73 | 57 | 0;132 | \-- | 262 | | LEFT ARROW (num keypad) | 0;75 | 52 | 0;115 | \-- | 263 | | RIGHT ARROW (num keypad) | 0;77 | 54 | 0;116 | \-- | 264 | | END (num keypad) | 0;79 | 49 | 0;117 | \-- | 265 | | DOWN ARROW (num keypad) | 0;80 | 50 | (0;145) | \-- | 266 | | PAGE DOWN (num keypad) | 0;81 | 51 | 0;118 | \-- | 267 | | INSERT (num keypad) | 0;82 | 48 | (0;146) | \-- | 268 | | DELETE (num keypad) | 0;83 | 46 | (0;147) | \-- | 269 | | HOME | (224;71) | (224;71) | (224;119) | (224;151) | 270 | | UP ARROW | (224;72) | (224;72) | (224;141) | (224;152) | 271 | | PAGE UP | (224;73) | (224;73) | (224;132) | (224;153) | 272 | | LEFT ARROW | (224;75) | (224;75) | (224;115) | (224;155) | 273 | | RIGHT ARROW | (224;77) | (224;77) | (224;116) | (224;157) | 274 | | END | (224;79) | (224;79) | (224;117) | (224;159) | 275 | | DOWN ARROW | (224;80) | (224;80) | (224;145) | (224;154) | 276 | | PAGE DOWN | (224;81) | (224;81) | (224;118) | (224;161) | 277 | | INSERT | (224;82) | (224;82) | (224;146) | (224;162) | 278 | | DELETE | (224;83) | (224;83) | (224;147) | (224;163) | 279 | | PRINT SCREEN | \-- | \-- | 0;114 | \-- | 280 | | PAUSE/BREAK | \-- | \-- | 0;0 | \-- | 281 | | BACKSPACE | 8 | 8 | 127 | (0) | 282 | | ENTER | 13 | \-- | 10 | (0 | 283 | | TAB | 9 | 0;15 | (0;148) | (0;165) | 284 | | NULL | 0;3 | \-- | \-- | \-- | 285 | | A | 97 | 65 | 1 | 0;30 | 286 | | B | 98 | 66 | 2 | 0;48 | 287 | | C | 99 | 66 | 3 | 0;46 | 288 | | D | 100 | 68 | 4 | 0;32 | 289 | | E | 101 | 69 | 5 | 0;18 | 290 | | F | 102 | 70 | 6 | 0;33 | 291 | | G | 103 | 71 | 7 | 0;34 | 292 | | H | 104 | 72 | 8 | 0;35 | 293 | | I | 105 | 73 | 9 | 0;23 | 294 | | J | 106 | 74 | 10 | 0;36 | 295 | | K | 107 | 75 | 11 | 0;37 | 296 | | L | 108 | 76 | 12 | 0;38 | 297 | | M | 109 | 77 | 13 | 0;50 | 298 | | N | 110 | 78 | 14 | 0;49 | 299 | | O | 111 | 79 | 15 | 0;24 | 300 | | P | 112 | 80 | 16 | 0;25 | 301 | | Q | 113 | 81 | 17 | 0;16 | 302 | | R | 114 | 82 | 18 | 0;19 | 303 | | S | 115 | 83 | 19 | 0;31 | 304 | | T | 116 | 84 | 20 | 0;20 | 305 | | U | 117 | 85 | 21 | 0;22 | 306 | | V | 118 | 86 | 22 | 0;47 | 307 | | W | 119 | 87 | 23 | 0;17 | 308 | | X | 120 | 88 | 24 | 0;45 | 309 | | Y | 121 | 89 | 25 | 0;21 | 310 | | Z | 122 | 90 | 26 | 0;44 | 311 | | 1 | 49 | 33 | \-- | 0;120 | 312 | | 2 | 50 | 64 | 0 | 0;121 | 313 | | 3 | 51 | 35 | \-- | 0;122 | 314 | | 4 | 52 | 36 | \-- | 0;123 | 315 | | 5 | 53 | 37 | \-- | 0;124 | 316 | | 6 | 54 | 94 | 30 | 0;125 | 317 | | 7 | 55 | 38 | \-- | 0;126 | 318 | | 8 | 56 | 42 | \-- | 0;126 | 319 | | 9 | 57 | 40 | \-- | 0;127 | 320 | | 0 | 48 | 41 | \-- | 0;129 | 321 | | \- | 45 | 95 | 31 | 0;130 | 322 | | \= | 61 | 43 | \--- | 0;131 | 323 | | \[ | 91 | 123 | 27 | 0;26 | 324 | | \] | 93 | 125 | 29 | 0;27 | 325 | | | 92 | 124 | 28 | 0;43 | 326 | | ; | 59 | 58 | \-- | 0;39 | 327 | | ' | 39 | 34 | \-- | 0;40 | 328 | | , | 44 | 60 | \-- | 0;51 | 329 | | . | 46 | 62 | \-- | 0;52 | 330 | | / | 47 | 63 | \-- | 0;53 | 331 | | \` | 96 | 126 | \-- | (0;41) | 332 | | ENTER (keypad) | 13 | \-- | 10 | (0;166) | 333 | | / (keypad) | 47 | 47 | (0;142) | (0;74) | 334 | | \* (keypad) | 42 | (0;144) | (0;78) | \-- | 335 | | \- (keypad) | 45 | 45 | (0;149) | (0;164) | 336 | | \+ (keypad) | 43 | 43 | (0;150) | (0;55) | 337 | | 5 (keypad) | (0;76) | 53 | (0;143) | \-- | 338 | 339 | ## Resources 340 | 341 | - [Wikipedia: ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code) 342 | - [Build your own Command Line with ANSI escape codes](http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html) 343 | - [ascii-table: ANSI Escape sequences](http://ascii-table.com/ansi-escape-sequences.php) 344 | - [bluesock: ansi codes](https://bluesock.org/~willkg/dev/ansi.html) 345 | - [bash-hackers: Terminal Codes (ANSI/VT100) introduction](http://wiki.bash-hackers.org/scripting/terminalcodes) 346 | - [XTerm Control Sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html) 347 | - [VT100 – Various terminal manuals](https://vt100.net/) 348 | - [xterm.js – Supported Terminal Sequences](https://xtermjs.org/docs/api/vtfeatures/) 349 | -------------------------------------------------------------------------------- /doc/tabulate.md: -------------------------------------------------------------------------------- 1 | # Markdown 2 | 3 | # tabulate 4 | 5 | [![license](https://img.shields.io/badge/license-Apache-brightgreen.svg?style=flat)](https://github.com/tqolf/devkit/blob/master/LICENSE) 6 | [![CI Status](https://github.com/tqolf/devkit/workflows/ci/badge.svg)](https://github.com/tqolf/devkit/actions) 7 | [![codecov](https://codecov.io/gh/tqolf/devkit/branch/master/graph/badge.svg?token=BtMOpzpU1t)](https://codecov.io/gh/tqolf/devkit) 8 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/tqolf/devkit?color=red&label=release) 9 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/tqolf/devkit/pulls) 10 | 11 | ![logo](images/logo.jpg) 12 | 13 | ![summary](images/summary.png) 14 | Source for the above image can be found [here](https://github.com/tqolf/devkit/blob/master/samples/summary.cc) 15 | 16 | ## Table of Contents 17 | 18 | - [Markdown](#markdown) 19 | - [tabulate](#tabulate) 20 | - [Table of Contents](#table-of-contents) 21 | - [Quick Start](#quick-start) 22 | - [Formatting Options](#formatting-options) 23 | - [Word Wrapping](#word-wrapping) 24 | - [Font Alignment](#font-alignment) 25 | - [Font Styles](#font-styles) 26 | - [Cell Colors](#cell-colors) 27 | - [Borders and Corners](#borders-and-corners) 28 | - [Range-based Iteration](#range-based-iteration) 29 | - [Nested Tables](#nested-tables) 30 | - [UTF-8 Support](#utf-8-support) 31 | - [Exporters](#exporters) 32 | - [Markdown](#markdown-1) 33 | - [Building Samples](#building-samples) 34 | - [Contributing](#contributing) 35 | - [License](#license) 36 | - [Colors](#colors) 37 | - [Styles](#styles) 38 | - [Appendix](#appendix) 39 | - [Colors Table](#colors-table) 40 | 41 | ## Quick Start 42 | 43 | `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/`. 44 | 45 | **NOTE** Tabulate supports `>=C++11`. The rest of this README, however, assumes `C++17` support. 46 | 47 | Create a `Table` object and call `Table.add_rows` to add rows to your table. 48 | 49 | ```cpp 50 | #include "tabulate.h" 51 | 52 | using namespace tabulate; 53 | 54 | int main() 55 | { 56 | Table universal_constants; 57 | 58 | universal_constants.add("Quantity", "Value"); 59 | universal_constants.add("Characteristic impedance of vacuum", "376.730 313 461... Ω"); 60 | universal_constants.add("Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"); 61 | universal_constants.add("Magnetic constant (permeability of free space)", 62 | "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"); 63 | universal_constants.add("Gravitational constant (Newtonian constant of gravitation)", 64 | "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"); 65 | universal_constants.add("Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"); 66 | universal_constants.add("Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"); 67 | universal_constants.add("Speed of light in vacuum", "299 792 458 m·s⁻¹"); 68 | ``` 69 | 70 | You 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. 71 | 72 | ```cpp 73 | universal_constants.format() 74 | .styles(Style::bold) 75 | .border_top(" ") 76 | .border_bottom(" ") 77 | .border_left(" ") 78 | .border_right(" ") 79 | .corner(" "); 80 | ``` 81 | 82 | You 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. 83 | 84 | Now, 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. 85 | 86 | ```cpp 87 | universal_constants[0] 88 | .format() 89 | .border_top_padding(1) 90 | .border_bottom_padding(1) 91 | .align(Align::center) 92 | .styles(Style::underline) 93 | .background_color(Color::red); 94 | ``` 95 | 96 | Calling `Table.column(index)` will return a `Column` object. Similar to rows, you can use `Column.format()` to format all the cells in that column. 97 | 98 | Now, let's change the font color of the second column to yellow: 99 | 100 | ```cpp 101 | universal_constants.column(1).format().color(Color::yellow); 102 | } 103 | ``` 104 | 105 | You 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 106 | 107 | ```cpp 108 | universal_constants[0][1].format().background_color(Color::blue).color(Color::white); 109 | 110 | std::cout << universal_constants.xterm() << std::endl; 111 | } 112 | ``` 113 | 114 | ![universal_constants](images/universal_constants.png) 115 | 116 | ## Formatting Options 117 | 118 | ### Word Wrapping 119 | 120 | `tabulate` supports automatic word-wrapping when printing cells. 121 | 122 | Although 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. 123 | 124 | ```cpp 125 | #include "tabulate.h" 126 | using namespace tabulate; 127 | 128 | int main() 129 | { 130 | Table table; 131 | 132 | table.add("This paragraph contains a veryveryveryveryveryverylong word. The long word will " 133 | "break and word wrap to the next line.", 134 | "This paragraph \nhas embedded '\\n' \ncharacters and\n will break\n exactly " 135 | "where\n you want it\n to\n break."); 136 | 137 | table[0][0].format().width(20); 138 | table[0][1].format().width(50); 139 | 140 | std::cout << table.xterm() << std::endl; 141 | } 142 | ``` 143 | 144 | * The above table has 1 row and 2 columns. 145 | * The first cell has automatic word-wrapping. 146 | * 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. 147 | * **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. 148 | 149 | ![word_wrap](images/word_wrap.png) 150 | 151 | **NOTE**: Both columns in the above table are left-aligned by default. This, however, can be easily changed. 152 | 153 | ### Font Alignment 154 | 155 | `tabulate` supports three font alignment settings: `left`, `center`, and `right`. By default, all table content is left-aligned. To align cells, use `.format().align(alignment)`. 156 | 157 | ```cpp 158 | #include "tabulate.h" 159 | using namespace tabulate; 160 | 161 | int main() 162 | { 163 | tabulate::Table movies; 164 | 165 | movies.add("S/N", "Movie Name", "Director", "Estimated Budget", "Release Date"); 166 | movies.add("tt1979376", "Toy Story 4", "Josh Cooley", 200000000, "21 June 2019"); 167 | movies.add("tt3263904", "Sully", "Clint Eastwood", 60000000, "9 September 2016"); 168 | movies.add("tt1535109", "Captain Phillips", "Paul Greengrass", 55000000, " 11 October 2013"); 169 | 170 | // center align 'Director' column 171 | movies.column(2).format().align(Align::center); 172 | 173 | // right align 'Estimated Budget' column 174 | movies.column(3).format().align(Align::right); 175 | 176 | // right align 'Release Date' column 177 | movies.column(4).format().align(Align::right); 178 | 179 | // Color header cells 180 | for (size_t i = 0; i < movies.column_size(); ++i) { 181 | movies[0][i].format().color(Color::yellow).styles(Style::bold); 182 | } 183 | 184 | std::cout << movies.xterm() << std::endl; 185 | std::cout << "Markdown Table:\n" << movies.markdown() << std::endl; 186 | } 187 | ``` 188 | 189 | ![movies](images/movies.png) 190 | 191 | ### Font Styles 192 | 193 | `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. 194 | 195 | To 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***. 196 | 197 | ```cpp 198 | #include "tabulate.h" 199 | 200 | using namespace tabulate; 201 | 202 | int main() 203 | { 204 | Table table; 205 | table.add("Bold", "Italic", "Bold & Italic", "Blinking"); 206 | table.add("Underline", "Crossed", "faint", "Bold, Italic & Underlined"); 207 | table.add("Doubly Underline", "Invisable", "", ""); 208 | 209 | table[0][0].format().styles(Style::bold); 210 | 211 | table[0][1].format().styles(Style::italic); 212 | 213 | table[0][2].format().styles(Style::bold, Style::italic); 214 | 215 | table[0][3].format().styles(Style::blink); 216 | 217 | table[1][0].format().styles(Style::underline); 218 | 219 | table[1][1].format().styles(Style::crossed); 220 | 221 | table[1][2].format().styles(Style::faint); 222 | 223 | table[1][3].format().styles(Style::bold, Style::italic, Style::underline); 224 | 225 | table[2][0].format().styles(Style::doubly_underline); 226 | table[2][1].format().styles(Style::invisible); 227 | 228 | std::cout << table.xterm() << std::endl; 229 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 230 | } 231 | ``` 232 | 233 | ![styles](images/styles.png) 234 | 235 | **NOTE**: Font styles are applied to the entire cell. Unlike HTML, you cannot currently apply styles to specific words in a cell. 236 | 237 | ### Cell Colors 238 | 239 | There are a number of methods in the `Format` object to color cells - foreground and background - for font, borders, corners, and column separators. `tabulate` supports 8 colors: `grey`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, and `white`, and support **True Color** if possiable. The look of these colors vary depending on your terminal. 240 | 241 | For font, border, and corners, you can call `.format()._color(value)` to set the foreground color and `.format()._background_color(value)` to set the background color. Here's an example: 242 | 243 | ```cpp 244 | #include "tabulate.h" 245 | 246 | using namespace tabulate; 247 | 248 | int main() 249 | { 250 | Table colors; 251 | 252 | colors.add("Font Color is Red", "Font Color is Blue", "Font Color is Green"); 253 | colors.add("Everything is Red", "Everything is Blue", "Everything is Green"); 254 | colors.add("Font Background is Red", "Font Background is Blue", "Font Background is Green"); 255 | 256 | colors[0][0].format().color(Color::red).styles(Style::bold); 257 | colors[0][1].format().color(Color::blue).styles(Style::bold); 258 | colors[0][2].format().color(Color::green).styles(Style::bold); 259 | 260 | colors[1][0] 261 | .format() 262 | .border_left_color(Color::red) 263 | .border_left_background_color(Color::red) 264 | .background_color(Color::red) 265 | .color(Color::red) 266 | .border_right_color(Color::blue) 267 | .border_right_background_color(Color::blue); 268 | 269 | colors[1][1] 270 | .format() 271 | .background_color(Color::blue) 272 | .color(Color::blue) 273 | .border_right_color(Color::green) 274 | .border_right_background_color(Color::green); 275 | 276 | colors[1][2] 277 | .format() 278 | .background_color(Color::green) 279 | .color(Color::green) 280 | .border_right_color(Color::green) 281 | .border_right_background_color(Color::green); 282 | 283 | colors[2][0].format().background_color(Color::red).styles(Style::bold); 284 | colors[2][1].format().background_color(Color::blue).styles(Style::bold); 285 | colors[2][2].format().background_color(Color::green).styles(Style::bold); 286 | 287 | std::cout << colors.xterm() << std::endl; 288 | // std::cout << "Markdown Table:\n" << colors.markdown() << std::endl; 289 | } 290 | ``` 291 | 292 | ![colors](images/colors.png) 293 | 294 | ### Borders and Corners 295 | 296 | `tabulate` allows for fine control over borders and corners. For each border and corner, you can set the text, color, and background color. 297 | 298 | **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. 299 | 300 | **NOTE**: Note the use of `.format().multi_bytes_character(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. 301 | 302 | Here's an example where each border and corner is individually styled: 303 | 304 | ```cpp 305 | #include "tabulate.h" 306 | 307 | using namespace tabulate; 308 | 309 | int main() 310 | { 311 | Table table; 312 | 313 | table.add("ᛏᚺᛁᛊ ᛁᛊ ᚨ ᛊᛏᛟᚱy ᛟᚠᚨ ᛒᛖᚨᚱ ᚨᚾᛞ\n" 314 | "ᚨ ᚹᛟᛚᚠ, ᚹᚺᛟ ᚹᚨᚾᛞᛖᚱᛖᛞ ᛏᚺᛖ\n" 315 | "ᚱᛖᚨᛚᛗᛊ ᚾᛁᚾᛖ ᛏᛟ ᚠᚢᛚᚠᛁᛚᛚ ᚨ ᛈᚱᛟᛗᛁᛊᛖ\n" 316 | "ᛏᛟ ᛟᚾᛖ ᛒᛖᚠᛟᚱᛖ; ᛏᚺᛖy ᚹᚨᛚᚲ ᛏᚺᛖ\n" 317 | "ᛏᚹᛁᛚᛁᚷᚺᛏ ᛈᚨᛏᚺ, ᛞᛖᛊᛏᛁᚾᛖᛞ ᛏᛟ\n" 318 | "ᛞᛁᛊcᛟᚹᛖᚱ ᛏᚺᛖ ᛏᚱᚢᛏᚺ\nᛏᚺᚨᛏ ᛁᛊ ᛏᛟ cᛟᛗᛖ."); 319 | 320 | table[0][0] 321 | .format() 322 | .multi_bytes_character(true) 323 | // Font styling 324 | .styles(Style::bold, Style::faint) 325 | .align(Align::center) 326 | .color(Color::red) 327 | .background_color(Color::yellow) 328 | // Corners 329 | .corner_top_left("ᛰ") 330 | .corner_top_right("ᛯ") 331 | .corner_bottom_left("ᛮ") 332 | .corner_bottom_right("ᛸ") 333 | .corner_top_left_color(Color::cyan) 334 | .corner_top_right_color(Color::yellow) 335 | .corner_bottom_left_color(Color::green) 336 | .corner_bottom_right_color(Color::red) 337 | // Borders 338 | .border_top("ᛜ") 339 | .border_bottom("ᛜ") 340 | .border_left("ᚿ") 341 | .border_right("ᛆ") 342 | .border_left_color(Color::yellow) 343 | .border_right_color(Color::green) 344 | .border_top_color(Color::cyan) 345 | .border_bottom_color(Color::red); 346 | 347 | std::cout << table.xterm() << std::endl; 348 | } 349 | ``` 350 | 351 | ![runic](images/runic.png) 352 | 353 | ### Range-based Iteration 354 | 355 | Hand-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. 356 | 357 | ```cpp 358 | #include "tabulate.h" 359 | using namespace tabulate; 360 | 361 | int main() 362 | { 363 | Table table; 364 | 365 | table.add("Company", "Contact", "Country"); 366 | table.add("Alfreds Futterkiste", "Maria Anders", "Germany"); 367 | table.add("Centro comercial Moctezuma", "Francisco Chang", "Mexico"); 368 | table.add("Ernst Handel", "Roland Mendel", "Austria"); 369 | table.add("Island Trading", "Helen Bennett", "UK"); 370 | table.add("Laughing Bacchus Winecellars", "Yoshi Tannamuri", "Canada"); 371 | table.add("Magazzini Alimentari Riuniti", "Giovanni Rovelli", "Italy"); 372 | 373 | // Set width of cells in each column 374 | table.column(0).format().width(40); 375 | table.column(1).format().width(30); 376 | table.column(2).format().width(30); 377 | 378 | // Iterate over cells in the first row 379 | for (auto &cell : table[0]) { cell.format().styles(Style::underline).align(Align::center); } 380 | 381 | // Iterator over cells in the first column 382 | for (auto &cell : table.column(0)) { 383 | if (cell.get() != "Company") { cell.format().align(Align::right); } 384 | } 385 | 386 | // Iterate over rows in the table 387 | size_t index = 0; 388 | for (auto &row : table) { 389 | // row.format().styles(Style::bold); 390 | 391 | // Set blue background color for alternate rows 392 | if (index > 0 && index % 2 == 0) { 393 | for (auto &cell : row) { cell.format().background_color(Color::blue); } 394 | } 395 | index += 1; 396 | } 397 | 398 | std::cout << table.xterm() << std::endl; 399 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 400 | } 401 | ``` 402 | 403 | ![iterators](images/iterators.png) 404 | 405 | ### Nested Tables 406 | 407 | `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. 408 | 409 | ```cpp 410 | #include "tabulate.h" 411 | using namespace tabulate; 412 | 413 | int main() 414 | { 415 | Table class_diagram; 416 | 417 | // Animal class 418 | { 419 | Table animal; 420 | animal.add("Animal"); 421 | animal[0].format().align(Align::center); 422 | 423 | // Animal properties nested table 424 | { 425 | Table animal_properties; 426 | animal_properties.add("+age: Int"); 427 | animal_properties.add("+gender: String"); 428 | animal_properties.format().width(20); 429 | animal_properties[0].format().hide_border_bottom(); 430 | 431 | animal.add(animal_properties); 432 | } 433 | 434 | // Animal methods nested table 435 | { 436 | Table animal_methods; 437 | animal_methods.add("+isMammal()"); 438 | animal_methods.add("+mate()"); 439 | animal_methods.format().width(20); 440 | animal_methods[0].format().hide_border_bottom(); 441 | 442 | animal.add(animal_methods); 443 | } 444 | animal[1].format().hide_border_bottom(); 445 | 446 | class_diagram.add(animal); 447 | } 448 | 449 | // Add rows in the class diagram for the up-facing arrow 450 | // THanks to center alignment, these will align just fine 451 | class_diagram.add("▲"); 452 | class_diagram[1][0].format().hide_border_bottom().multi_bytes_character(true); 453 | class_diagram.add("|"); 454 | class_diagram[2].format().hide_border_bottom(); 455 | class_diagram.add("|"); 456 | class_diagram[3].format().hide_border_bottom(); 457 | 458 | // Duck class 459 | { 460 | Table duck; 461 | duck.add("Duck"); 462 | 463 | // Duck proeperties nested table 464 | { 465 | Table duck_properties; 466 | duck_properties.add("+beakColor: String = \"yellow\""); 467 | duck_properties.format().width(40); 468 | 469 | duck.add(duck_properties); 470 | } 471 | 472 | // Duck methods nested table 473 | { 474 | Table duck_methods; 475 | duck_methods.add("+swim()"); 476 | duck_methods.add("+quack()"); 477 | duck_methods.format().width(40); 478 | duck_methods[0].format().hide_border_bottom(); 479 | 480 | duck.add(duck_methods); 481 | } 482 | 483 | duck[0].format().align(Align::center); 484 | duck[1].format().hide_border_bottom(); 485 | 486 | class_diagram.add(duck); 487 | } 488 | 489 | // Global styling 490 | class_diagram.format().styles(Style::bold).align(Align::center).width(60).hide_border(); 491 | 492 | std::cout << class_diagram.xterm() << std::endl; 493 | } 494 | ``` 495 | 496 | ![class_diagram](images/class_diagram.png) 497 | 498 | ### UTF-8 Support 499 | 500 | In \*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. 501 | 502 | The following table prints the phrase `I love you` in different languages. Note the use of `.format().multi_bytes_character(true)` for the second column. Remember to do this when dealing with multi-byte characters. 503 | 504 | ```cpp 505 | #include "tabulate.h" 506 | using namespace tabulate; 507 | 508 | int main() 509 | { 510 | Table table; 511 | 512 | table.add("English", "I love you"); 513 | table.add("French", "Je t’aime"); 514 | table.add("Spanish", "Te amo"); 515 | table.add("German", "Ich liebe Dich"); 516 | table.add("Mandarin Chinese", "我爱你"); 517 | table.add("Japanese", "愛してる"); 518 | table.add("Korean", "사랑해 (Saranghae)"); 519 | table.add("Greek", "Σ΄αγαπώ (Se agapo)"); 520 | table.add("Italian", "Ti amo"); 521 | table.add("Russian", "Я тебя люблю (Ya tebya liubliu)"); 522 | table.add("Hebrew", "אני אוהב אותך (Ani ohev otakh)"); 523 | 524 | // Column 1 is using mult-byte characters 525 | table.column(1).format().multi_bytes_character(true); 526 | table.format().corner("♥").styles(Style::bold).corner_color(Color::magenta).border_color(Color::magenta); 527 | 528 | std::cout << table.xterm() << std::endl; 529 | } 530 | ``` 531 | 532 | ![unicode](images/unicode.png) 533 | 534 | You 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. 535 | 536 | ```cpp 537 | // Set English-US locale for first column 538 | table.column(0).format().locale("en_US.UTF-8"); 539 | table[0][1].format().locale("en_US.UTF-8"); 540 | 541 | // Set locale for individual cells 542 | table[1][1].format().locale("fr_FR.UTF-8"); // French 543 | table[2][1].format().locale("es_ES.UTF-8"); // Spanish 544 | table[3][1].format().locale("de_DE.UTF-8"); // German 545 | table[4][1].format().locale("zh_CN.UTF-8"); // Chinese 546 | table[5][1].format().locale("ja_JP.UTF-8"); // Japanese 547 | table[6][1].format().locale("ko_KR.UTF-8"); // Korean 548 | table[7][1].format().locale("el_GR.UTF-8"); // Greek 549 | table[8][1].format().locale("it_IT.UTF-8"); // Italian 550 | table[9][1].format().locale("ru_RU.UTF-8"); // Russian 551 | table[10][1].format().locale("he_IL.UTF-8"); // Hebrew 552 | ``` 553 | 554 | ## Exporters 555 | 556 | ### Markdown 557 | 558 | Tables can be exported to GitHub-flavored markdown using a `table.markdown()` to generate a Markdown-formatted `std::string`. 559 | 560 | ```cpp 561 | #include "tabulate.h" 562 | using namespace tabulate; 563 | 564 | int main() 565 | { 566 | tabulate::Table movies; 567 | 568 | movies.add("S/N", "Movie Name", "Director", "Estimated Budget", "Release Date"); 569 | movies.add("tt1979376", "Toy Story 4", "Josh Cooley", 200000000, "21 June 2019"); 570 | movies.add("tt3263904", "Sully", "Clint Eastwood", 60000000, "9 September 2016"); 571 | movies.add("tt1535109", "Captain Phillips", "Paul Greengrass", 55000000, " 11 October 2013"); 572 | 573 | // center align 'Director' column 574 | movies.column(2).format().align(Align::center); 575 | 576 | // right align 'Estimated Budget' column 577 | movies.column(3).format().align(Align::right); 578 | 579 | // right align 'Release Date' column 580 | movies.column(4).format().align(Align::right); 581 | 582 | // Color header cells 583 | for (size_t i = 0; i < movies.column_size(); ++i) { 584 | movies[0][i].format().color(Color::yellow).styles(Style::bold); 585 | } 586 | 587 | std::cout << movies.xterm() << std::endl; 588 | std::cout << "Markdown Table:\n" << movies.markdown() << std::endl; 589 | } 590 | ``` 591 | 592 | ![markdown_export](images/markdown_export.png) 593 | 594 | The above table renders in Markdown like below. 595 | 596 | **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 `markdown()` 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. **True Color** supported for markdown exporter. 597 | 598 | | **S/N** | **Movie Name** | **Director** | **Estimated Budget** | **Release Date** | 599 | | :------------------------------------------ | :------------------------------------------------- | :----------------------------------------------: | -------------------------------------------------------: | ---------------------------------------------------: | 600 | | tt1979376 | Toy Story 4 | Josh Cooley | 200000000 | 21 June 2019 | 601 | | tt3263904 | Sully | Clint Eastwood | 60000000 | 9 September 2016 | 602 | | tt1535109 | Captain Phillips | Paul Greengrass | 55000000 | 11 October 2013 | 603 | 604 | ## Building Samples 605 | 606 | There are a number of samples in the `samples/` directory. You can build these samples by running the following commands. 607 | 608 | ```bash 609 | cmake -B build 610 | cmake --build build 611 | ``` 612 | 613 | ## Contributing 614 | Contributions are welcome, have a look at the [CONTRIBUTING.md](CONTRIBUTING.md) document for more information. 615 | 616 | ## License 617 | The project is available under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) license. 618 | 619 | 620 | ## Colors 621 | 622 | - xterm 623 | - VT100: `\033[35;47m[magenta on white]\033[m` 624 | - Control Sequence 625 | | Code | Effect | Note | 626 | | :----------------------- | :-------: | :----------------------------------------- | 627 | | CSI n m | SGR | ANSI color code (Select Graphic Rendition) | 628 | | CSI 38 ; 5 ; n m | 256COLOR | Foreground 256 color code | 629 | | ESC 48 ; 5 ; n m | 256COLOR | Background 256 color code | 630 | | CSI 38 ; 2 ; r ; g ; b m | TRUECOLOR | Foreground 24 bit rgb color code | 631 | | ESC 48 ; 2 ; r ; g ; b m | TRUECOLOR | Background 24 bit rgb color code | 632 | 633 | - markdown 634 | - `[magenta on white]` 635 | - `[magenta on white]` 636 | 637 | ## Styles 638 | 639 | - xterm 640 | - https://tintin.mudhalla.net/info/xterm 641 | - https://invisible-island.net/xterm/ctlseqs/ctlseqs.html 642 | 643 | - markdown 644 | - **bold** 645 | - __bold__ 646 | - bold 647 | - faint 648 | - _italic_ 649 | - *italic* 650 | - italic 651 | - italic 652 | - italic 653 | - underline 654 | - underline 655 | - blink 656 | - inverse 657 | - invisible 658 | - ~~crossed~~ 659 | - crossed 660 | 661 | 662 | ## Appendix 663 | 664 | ### Colors Table 665 | 666 | | Name | HEX | RGB | 667 | | :------------------- | :---------------------------------------------------: | -----------------: | 668 | | AliceBlue | #F0F8FF | RGB(240, 248, 255) | 669 | | AntiqueWhite | #FAEBD7 | RGB(250, 235, 215) | 670 | | Aqua | #00FFFF | RGB(0, 255, 255) | 671 | | Aquamarine | #7FFFD4 | RGB(127, 255, 212) | 672 | | Azure | #F0FFFF | RGB(240, 255, 255) | 673 | | Beige | #F5F5DC | RGB(245, 245, 220) | 674 | | Bisque | #FFE4C4 | RGB(255, 228, 196) | 675 | | Black | #000000 | RGB(0, 0, 0) | 676 | | BlanchedAlmond | #FFEBCD | RGB(255, 235, 205) | 677 | | Blue | #0000FF | RGB(0, 0, 255) | 678 | | BlueViolet | #8A2BE2 | RGB(138, 43, 226) | 679 | | Brown | #A52A2A | RGB(165, 42, 42) | 680 | | BurlyWood | #DEB887 | RGB(222, 184, 135) | 681 | | CadetBlue | #5F9EA0 | RGB(95, 158, 160) | 682 | | Chartreuse | #7FFF00 | RGB(127, 255, 0) | 683 | | Chocolate | #D2691E | RGB(210, 105, 30) | 684 | | Coral | #FF7F50 | RGB(255, 127, 80) | 685 | | CornflowerBlue | #6495ED | RGB(100, 149, 237) | 686 | | Cornsilk | #FFF8DC | RGB(255, 248, 220) | 687 | | Crimson | #DC143C | RGB(220, 20, 60) | 688 | | Cyan | #00FFFF | RGB(0, 255, 255) | 689 | | DarkBlue | #00008B | RGB(0, 0, 139) | 690 | | DarkCyan | #008B8B | RGB(0, 139, 139) | 691 | | DarkGoldenRod | #B8860B | RGB(184, 134, 11) | 692 | | DarkGray | #A9A9A9 | RGB(169, 169, 169) | 693 | | DarkGreen | #006400 | RGB(0, 100, 0) | 694 | | DarkKhaki | #BDB76B | RGB(189, 183, 107) | 695 | | DarkMagenta | #8B008B | RGB(139, 0, 139) | 696 | | DarkOliveGreen | #556B2F | RGB(85, 107, 47) | 697 | | Darkorange | #FF8C00 | RGB(255, 140, 0) | 698 | | DarkOrchid | #9932CC | RGB(153, 50, 204) | 699 | | DarkRed | #8B0000 | RGB(139, 0, 0) | 700 | | DarkSalmon | #E9967A | RGB(233, 150, 122) | 701 | | DarkSeaGreen | #8FBC8F | RGB(143, 188, 143) | 702 | | DarkSlateBlue | #483D8B | RGB(72, 61, 139) | 703 | | DarkSlateGray | #2F4F4F | RGB(47, 79, 79) | 704 | | DarkTurquoise | #00CED1 | RGB(0, 206, 209) | 705 | | DarkViolet | #9400D3 | RGB(148, 0, 211) | 706 | | DeepPink | #FF1493 | RGB(255, 20, 147) | 707 | | DeepSkyBlue | #00BFFF | RGB(0, 191, 255) | 708 | | DimGray | #696969 | RGB(105, 105, 105) | 709 | | DodgerBlue | #1E90FF | RGB(30, 144, 255) | 710 | | Feldspar | #D19275 | RGB(209, 146, 117) | 711 | | FireBrick | #B22222 | RGB(178, 34, 34) | 712 | | FloralWhite | #FFFAF0 | RGB(255, 250, 240) | 713 | | ForestGreen | #228B22 | RGB(34, 139, 34) | 714 | | Fuchsia | #FF00FF | RGB(255, 0, 255) | 715 | | Gainsboro | #DCDCDC | RGB(220, 220, 220) | 716 | | GhostWhite | #F8F8FF | RGB(248, 248, 255) | 717 | | Gold | #FFD700 | RGB(255, 215, 0) | 718 | | GoldenRod | #DAA520 | RGB(218, 165, 32) | 719 | | Gray | #808080 | RGB(128, 128, 128) | 720 | | Green | #008000 | RGB(0, 128, 0) | 721 | | GreenYellow | #ADFF2F | RGB(173, 255, 47) | 722 | | HoneyDew | #F0FFF0 | RGB(240, 255, 240) | 723 | | HotPink | #FF69B4 | RGB(255, 105, 180) | 724 | | IndianRed | #CD5C5C | RGB(205, 92, 92) | 725 | | Indigo | #4B0082 | RGB(75, 0, 130) | 726 | | Ivory | #FFFFF0 | RGB(255, 255, 240) | 727 | | Khaki | #F0E68C | RGB(240, 230, 140) | 728 | | Lavender | #E6E6FA | RGB(230, 230, 250) | 729 | | LavenderBlush | #FFF0F5 | RGB(255, 240, 245) | 730 | | LawnGreen | #7CFC00 | RGB(124, 252, 0) | 731 | | LemonChiffon | #FFFACD | RGB(255, 250, 205) | 732 | | LightBlue | #ADD8E6 | RGB(173, 216, 230) | 733 | | LightCoral | #F08080 | RGB(240, 128, 128) | 734 | | LightCyan | #E0FFFF | RGB(224, 255, 255) | 735 | | LightGoldenRodYellow | #FAFAD2 | RGB(250, 250, 210) | 736 | | LightGrey | #D3D3D3 | RGB(211, 211, 211) | 737 | | LightGreen | #90EE90 | RGB(144, 238, 144) | 738 | | LightPink | #FFB6C1 | RGB(255, 182, 193) | 739 | | LightSalmon | #FFA07A | RGB(255, 160, 122) | 740 | | LightSeaGreen | #20B2AA | RGB(32, 178, 170) | 741 | | LightSkyBlue | #87CEFA | RGB(135, 206, 250) | 742 | | LightSlateBlue | #8470FF | RGB(132, 112, 255) | 743 | | LightSlateGray | #778899 | RGB(119, 136, 153) | 744 | | LightSteelBlue | #B0C4DE | RGB(176, 196, 222) | 745 | | LightYellow | #FFFFE0 | RGB(255, 255, 224) | 746 | | Lime | #00FF00 | RGB(0, 255, 0) | 747 | | LimeGreen | #32CD32 | RGB(50, 205, 50) | 748 | | Linen | #FAF0E6 | RGB(250, 240, 230) | 749 | | Magenta | #FF00FF | RGB(255, 0, 255) | 750 | | Maroon | #800000 | RGB(128, 0, 0) | 751 | | MediumAquaMarine | #66CDAA | RGB(102, 205, 170) | 752 | | MediumBlue | #0000CD | RGB(0, 0, 205) | 753 | | MediumOrchid | #BA55D3 | RGB(186, 85, 211) | 754 | | MediumPurple | #9370D8 | RGB(147, 112, 216) | 755 | | MediumSeaGreen | #3CB371 | RGB(60, 179, 113) | 756 | | MediumSlateBlue | #7B68EE | RGB(123, 104, 238) | 757 | | MediumSpringGreen | #00FA9A | RGB(0, 250, 154) | 758 | | MediumTurquoise | #48D1CC | RGB(72, 209, 204) | 759 | | MediumVioletRed | #C71585 | RGB(199, 21, 133) | 760 | | MidnightBlue | #191970 | RGB(25, 25, 112) | 761 | | MintCream | #F5FFFA | RGB(245, 255, 250) | 762 | | MistyRose | #FFE4E1 | RGB(255, 228, 225) | 763 | | Moccasin | #FFE4B5 | RGB(255, 228, 181) | 764 | | NavajoWhite | #FFDEAD | RGB(255, 222, 173) | 765 | | Navy | #000080 | RGB(0, 0, 128) | 766 | | OldLace | #FDF5E6 | RGB(253, 245, 230) | 767 | | Olive | #808000 | RGB(128, 128, 0) | 768 | | OliveDrab | #6B8E23 | RGB(107, 142, 35) | 769 | | Orange | #FFA500 | RGB(255, 165, 0) | 770 | | OrangeRed | #FF4500 | RGB(255, 69, 0) | 771 | | Orchid | #DA70D6 | RGB(218, 112, 214) | 772 | | PaleGoldenRod | #EEE8AA | RGB(238, 232, 170) | 773 | | PaleGreen | #98FB98 | RGB(152, 251, 152) | 774 | | PaleTurquoise | #AFEEEE | RGB(175, 238, 238) | 775 | | PaleVioletRed | #D87093 | RGB(216, 112, 147) | 776 | | PapayaWhip | #FFEFD5 | RGB(255, 239, 213) | 777 | | PeachPuff | #FFDAB9 | RGB(255, 218, 185) | 778 | | Peru | #CD853F | RGB(205, 133, 63) | 779 | | Pink | #FFC0CB | RGB(255, 192, 203) | 780 | | Plum | #DDA0DD | RGB(221, 160, 221) | 781 | | PowderBlue | #B0E0E6 | RGB(176, 224, 230) | 782 | | Purple | #800080 | RGB(128, 0, 128) | 783 | | Red | #FF0000 | RGB(255, 0, 0) | 784 | | RosyBrown | #BC8F8F | RGB(188, 143, 143) | 785 | | RoyalBlue | #4169E1 | RGB(65, 105, 225) | 786 | | SaddleBrown | #8B4513 | RGB(139, 69, 19) | 787 | | Salmon | #FA8072 | RGB(250, 128, 114) | 788 | | SandyBrown | #F4A460 | RGB(244, 164, 96) | 789 | | SeaGreen | #2E8B57 | RGB(46, 139, 87) | 790 | | SeaShell | #FFF5EE | RGB(255, 245, 238) | 791 | | Sienna | #A0522D | RGB(160, 82, 45) | 792 | | Silver | #C0C0C0 | RGB(192, 192, 192) | 793 | | SkyBlue | #87CEEB | RGB(135, 206, 235) | 794 | | SlateBlue | #6A5ACD | RGB(106, 90, 205) | 795 | | SlateGray | #708090 | RGB(112, 128, 144) | 796 | | Snow | #FFFAFA | RGB(255, 250, 250) | 797 | | SpringGreen | #00FF7F | RGB(0, 255, 127) | 798 | | SteelBlue | #4682B4 | RGB(70, 130, 180) | 799 | | Tan | #D2B48C | RGB(210, 180, 140) | 800 | | Teal | #008080 | RGB(0, 128, 128) | 801 | | Thistle | #D8BFD8 | RGB(216, 191, 216) | 802 | | Tomato | #FF6347 | RGB(255, 99, 71) | 803 | | Turquoise | #40E0D0 | RGB(64, 224, 208) | 804 | | Violet | #EE82EE | RGB(238, 130, 238) | 805 | | VioletRed | #D02090 | RGB(208, 32, 144) | 806 | | Wheat | #F5DEB3 | RGB(245, 222, 179) | 807 | | White | #FFFFFF | RGB(255, 255, 255) | 808 | | WhiteSmoke | #F5F5F5 | RGB(245, 245, 245) | 809 | | Yellow | #FFFF00 | RGB(255, 255, 0) | 810 | | YellowGreen | #9ACD32 | RGB(154, 205, 50) | 811 | 812 | 813 | ## Symbols 814 | | Name | Main | Fallback | 815 | | ------------------------------------------- | :---: | :------: | 816 | | tick | `✔` | `√` | 817 | | info | `ℹ` | `i` | 818 | | warning | `⚠` | `‼` | 819 | | cross | `✘` | `×` | 820 | | square | `█` | | 821 | | squareSmall | `◻` | `□` | 822 | | squareSmallFilled | `◼` | `■` | 823 | | squareDarkShade | `▓` | | 824 | | squareMediumShade | `▒` | | 825 | | squareLightShade | `░` | | 826 | | squareTop | `▀` | | 827 | | squareBottom | `▄` | | 828 | | squareLeft | `▌` | | 829 | | squareRight | `▐` | | 830 | | squareCenter | `■` | | 831 | | circle | `◯` | `( )` | 832 | | circleFilled | `◉` | `(*)` | 833 | | circleDotted | `◌` | `( )` | 834 | | circleDouble | `◎` | `( )` | 835 | | circleCircle | `ⓞ` | `(○)` | 836 | | circleCross | `ⓧ` | `(×)` | 837 | | circlePipe | `Ⓘ` | `(│)` | 838 | | circleQuestionMark | `?⃝ ` | `(?)` | 839 | | radioOn | `◉` | `(*)` | 840 | | radioOff | `◯` | `( )` | 841 | | checkboxOn | `☒` | `[×]` | 842 | | checkboxOff | `☐` | `[ ]` | 843 | | checkboxCircleOn | `ⓧ` | `(×)` | 844 | | checkboxCircleOff | `Ⓘ` | `( )` | 845 | | questionMarkPrefix | `?⃝ ` | `?` | 846 | | bullet | `●` | | 847 | | dot | `․` | | 848 | | ellipsis | `…` | | 849 | | pointer | `❯` | `>` | 850 | | pointerSmall | `›` | `›` | 851 | | triangleUp | `▲` | | 852 | | triangleUpSmall | `▴` | | 853 | | triangleUpOutline | `△` | `∆` | 854 | | triangleDown | `▼` | | 855 | | triangleDownSmall | `▾` | | 856 | | triangleLeft | `◀` | `◄` | 857 | | triangleLeftSmall | `◂` | | 858 | | triangleRight | `▶` | `►` | 859 | | triangleRightSmall | `▸` | | 860 | | lozenge | `◆` | `♦` | 861 | | lozengeOutline | `◇` | `◊` | 862 | | home | `⌂` | | 863 | | hamburger | `☰` | `≡` | 864 | | smiley | `㋡` | `☺` | 865 | | mustache | `෴` | `┌─┐` | 866 | | heart | `♥` | | 867 | | star | `★` | `✶` | 868 | | play | `▶` | `►` | 869 | | musicNote | `♪` | | 870 | | musicNoteBeamed | `♫` | | 871 | | nodejs | `⬢` | `♦` | 872 | | arrowUp | `↑` | | 873 | | arrowDown | `↓` | | 874 | | arrowLeft | `←` | | 875 | | arrowRight | `→` | | 876 | | arrowLeftRight | `↔` | | 877 | | arrowUpDown | `↕` | | 878 | | almostEqual | `≈` | | 879 | | notEqual | `≠` | | 880 | | lessOrEqual | `≤` | | 881 | | greaterOrEqual | `≥` | | 882 | | identical | `≡` | | 883 | | infinity | `∞` | | 884 | | subscriptZero | `₀` | | 885 | | subscriptOne | `₁` | | 886 | | subscriptTwo | `₂` | | 887 | | subscriptThree | `₃` | | 888 | | subscriptFour | `₄` | | 889 | | subscriptFive | `₅` | | 890 | | subscriptSix | `₆` | | 891 | | subscriptSeven | `₇` | | 892 | | subscriptEight | `₈` | | 893 | | subscriptNine | `₉` | | 894 | | oneHalf | `½` | | 895 | | oneThird | `⅓` | | 896 | | oneQuarter | `¼` | | 897 | | oneFifth | `⅕` | | 898 | | oneSixth | `⅙` | | 899 | | oneSeventh | `⅐` | `1/7` | 900 | | oneEighth | `⅛` | | 901 | | oneNinth | `⅑` | `1/9` | 902 | | oneTenth | `⅒` | `1/10` | 903 | | twoThirds | `⅔` | | 904 | | twoFifths | `⅖` | | 905 | | threeQuarters | `¾` | | 906 | | threeFifths | `⅗` | | 907 | | threeEighths | `⅜` | | 908 | | fourFifths | `⅘` | | 909 | | fiveSixths | `⅚` | | 910 | | fiveEighths | `⅝` | | 911 | | sevenEighths | `⅞` | | 912 | | line | `─` | | 913 | | lineBold | `━` | | 914 | | lineDouble | `═` | | 915 | | lineDashed0 | `┄` | | 916 | | lineDashed1 | `┅` | | 917 | | lineDashed2 | `┈` | | 918 | | lineDashed3 | `┉` | | 919 | | lineDashed4 | `╌` | | 920 | | lineDashed5 | `╍` | | 921 | | lineDashed6 | `╴` | | 922 | | lineDashed7 | `╶` | | 923 | | lineDashed8 | `╸` | | 924 | | lineDashed9 | `╺` | | 925 | | lineDashed10 | `╼` | | 926 | | lineDashed11 | `╾` | | 927 | | lineDashed12 | `−` | | 928 | | lineDashed13 | `–` | | 929 | | lineDashed14 | `‐` | | 930 | | lineDashed15 | `⁃` | | 931 | | lineVertical | `│` | | 932 | | lineVerticalBold | `┃` | | 933 | | lineVerticalDouble | `║` | | 934 | | lineVerticalDashed0 | `┆` | | 935 | | lineVerticalDashed1 | `┇` | | 936 | | lineVerticalDashed2 | `┊` | | 937 | | lineVerticalDashed3 | `┋` | | 938 | | lineVerticalDashed4 | `╎` | | 939 | | lineVerticalDashed5 | `╏` | | 940 | | lineVerticalDashed6 | `╵` | | 941 | | lineVerticalDashed7 | `╷` | | 942 | | lineVerticalDashed8 | `╹` | | 943 | | lineVerticalDashed9 | `╻` | | 944 | | lineVerticalDashed10 | `╽` | | 945 | | lineVerticalDashed11 | `╿` | | 946 | | lineDownLeft | `┐` | | 947 | | lineDownLeftArc | `╮` | | 948 | | lineDownBoldLeftBold | `┓` | | 949 | | lineDownBoldLeft | `┒` | | 950 | | lineDownLeftBold | `┑` | | 951 | | lineDownDoubleLeftDouble | `╗` | | 952 | | lineDownDoubleLeft | `╖` | | 953 | | lineDownLeftDouble | `╕` | | 954 | | lineDownRight | `┌` | | 955 | | lineDownRightArc | `╭` | | 956 | | lineDownBoldRightBold | `┏` | | 957 | | lineDownBoldRight | `┎` | | 958 | | lineDownRightBold | `┍` | | 959 | | lineDownDoubleRightDouble | `╔` | | 960 | | lineDownDoubleRight | `╓` | | 961 | | lineDownRightDouble | `╒` | | 962 | | lineUpLeft | `┘` | | 963 | | lineUpLeftArc | `╯` | | 964 | | lineUpBoldLeftBold | `┛` | | 965 | | lineUpBoldLeft | `┚` | | 966 | | lineUpLeftBold | `┙` | | 967 | | lineUpDoubleLeftDouble | `╝` | | 968 | | lineUpDoubleLeft | `╜` | | 969 | | lineUpLeftDouble | `╛` | | 970 | | lineUpRight | `└` | | 971 | | lineUpRightArc | `╰` | | 972 | | lineUpBoldRightBold | `┗` | | 973 | | lineUpBoldRight | `┖` | | 974 | | lineUpRightBold | `┕` | | 975 | | lineUpDoubleRightDouble | `╚` | | 976 | | lineUpDoubleRight | `╙` | | 977 | | lineUpRightDouble | `╘` | | 978 | | lineUpDownLeft | `┤` | | 979 | | lineUpBoldDownBoldLeftBold | `┫` | | 980 | | lineUpBoldDownBoldLeft | `┨` | | 981 | | lineUpDownLeftBold | `┥` | | 982 | | lineUpBoldDownLeftBold | `┩` | | 983 | | lineUpDownBoldLeftBold | `┪` | | 984 | | lineUpDownBoldLeft | `┧` | | 985 | | lineUpBoldDownLeft | `┦` | | 986 | | lineUpDoubleDownDoubleLeftDouble | `╣` | | 987 | | lineUpDoubleDownDoubleLeft | `╢` | | 988 | | lineUpDownLeftDouble | `╡` | | 989 | | lineUpDownRight | `├` | | 990 | | lineUpBoldDownBoldRightBold | `┣` | | 991 | | lineUpBoldDownBoldRight | `┠` | | 992 | | lineUpDownRightBold | `┝` | | 993 | | lineUpBoldDownRightBold | `┡` | | 994 | | lineUpDownBoldRightBold | `┢` | | 995 | | lineUpDownBoldRight | `┟` | | 996 | | lineUpBoldDownRight | `┞` | | 997 | | lineUpDoubleDownDoubleRightDouble | `╠` | | 998 | | lineUpDoubleDownDoubleRight | `╟` | | 999 | | lineUpDownRightDouble | `╞` | | 1000 | | lineDownLeftRight | `┬` | | 1001 | | lineDownBoldLeftBoldRightBold | `┳` | | 1002 | | lineDownLeftBoldRightBold | `┯` | | 1003 | | lineDownBoldLeftRight | `┰` | | 1004 | | lineDownBoldLeftBoldRight | `┱` | | 1005 | | lineDownBoldLeftRightBold | `┲` | | 1006 | | lineDownLeftRightBold | `┮` | | 1007 | | lineDownLeftBoldRight | `┭` | | 1008 | | lineDownDoubleLeftDoubleRightDouble | `╦` | | 1009 | | lineDownDoubleLeftRight | `╥` | | 1010 | | lineDownLeftDoubleRightDouble | `╤` | | 1011 | | lineUpLeftRight | `┴` | | 1012 | | lineUpBoldLeftBoldRightBold | `┻` | | 1013 | | lineUpLeftBoldRightBold | `┷` | | 1014 | | lineUpBoldLeftRight | `┸` | | 1015 | | lineUpBoldLeftBoldRight | `┹` | | 1016 | | lineUpBoldLeftRightBold | `┺` | | 1017 | | lineUpLeftRightBold | `┶` | | 1018 | | lineUpLeftBoldRight | `┵` | | 1019 | | lineUpDoubleLeftDoubleRightDouble | `╩` | | 1020 | | lineUpDoubleLeftRight | `╨` | | 1021 | | lineUpLeftDoubleRightDouble | `╧` | | 1022 | | lineUpDownLeftRight | `┼` | | 1023 | | lineUpBoldDownBoldLeftBoldRightBold | `╋` | | 1024 | | lineUpDownBoldLeftBoldRightBold | `╈` | | 1025 | | lineUpBoldDownLeftBoldRightBold | `╇` | | 1026 | | lineUpBoldDownBoldLeftRightBold | `╊` | | 1027 | | lineUpBoldDownBoldLeftBoldRight | `╉` | | 1028 | | lineUpBoldDownLeftRight | `╀` | | 1029 | | lineUpDownBoldLeftRight | `╁` | | 1030 | | lineUpDownLeftBoldRight | `┽` | | 1031 | | lineUpDownLeftRightBold | `┾` | | 1032 | | lineUpBoldDownBoldLeftRight | `╂` | | 1033 | | lineUpDownLeftBoldRightBold | `┿` | | 1034 | | lineUpBoldDownLeftBoldRight | `╃` | | 1035 | | lineUpBoldDownLeftRightBold | `╄` | | 1036 | | lineUpDownBoldLeftBoldRight | `╅` | | 1037 | | lineUpDownBoldLeftRightBold | `╆` | | 1038 | | lineUpDoubleDownDoubleLeftDoubleRightDouble | `╬` | | 1039 | | lineUpDoubleDownDoubleLeftRight | `╫` | | 1040 | | lineUpDownLeftDoubleRightDouble | `╪` | | 1041 | | lineCross | `╳` | | 1042 | | lineBackslash | `╲` | | 1043 | | lineSlash | `╱` | | 1044 | -------------------------------------------------------------------------------- /images/class_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/class_diagram.png -------------------------------------------------------------------------------- /images/colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/colors.png -------------------------------------------------------------------------------- /images/iterators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/iterators.png -------------------------------------------------------------------------------- /images/mario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/mario.png -------------------------------------------------------------------------------- /images/markdown_export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/markdown_export.png -------------------------------------------------------------------------------- /images/movies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/movies.png -------------------------------------------------------------------------------- /images/runic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/runic.png -------------------------------------------------------------------------------- /images/styles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/styles.png -------------------------------------------------------------------------------- /images/summary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/summary.png -------------------------------------------------------------------------------- /images/unicode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/unicode.png -------------------------------------------------------------------------------- /images/universal_constants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/universal_constants.png -------------------------------------------------------------------------------- /images/word_wrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/images/word_wrap.png -------------------------------------------------------------------------------- /samples/class-diagram.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table class_diagram; 23 | 24 | // Animal class 25 | { 26 | Table animal; 27 | animal.add("Animal"); 28 | animal[0].format().align(Align::center); 29 | 30 | // Animal properties nested table 31 | { 32 | Table animal_properties; 33 | animal_properties.add("+age: Int"); 34 | animal_properties.add("+gender: String"); 35 | animal_properties.format().width(20); 36 | animal_properties[0].format().hide_border_bottom(); 37 | 38 | animal.add(animal_properties); 39 | } 40 | 41 | // Animal methods nested table 42 | { 43 | Table animal_methods; 44 | animal_methods.add("+isMammal()"); 45 | animal_methods.add("+mate()"); 46 | animal_methods.format().width(20); 47 | animal_methods[0].format().hide_border_bottom(); 48 | 49 | animal.add(animal_methods); 50 | } 51 | animal[1].format().hide_border_bottom(); 52 | 53 | class_diagram.add(animal); 54 | } 55 | 56 | // Add rows in the class diagram for the up-facing arrow 57 | // THanks to center alignment, these will align just fine 58 | class_diagram.add("▲"); 59 | class_diagram[1][0].format().hide_border_bottom().multi_bytes_character(true); 60 | class_diagram.add("|"); 61 | class_diagram[2].format().hide_border_bottom(); 62 | class_diagram.add("|"); 63 | class_diagram[3].format().hide_border_bottom(); 64 | 65 | // Duck class 66 | { 67 | Table duck; 68 | duck.add("Duck"); 69 | 70 | // Duck proeperties nested table 71 | { 72 | Table duck_properties; 73 | duck_properties.add("+beakColor: String = \"yellow\""); 74 | duck_properties.format().width(40); 75 | 76 | duck.add(duck_properties); 77 | } 78 | 79 | // Duck methods nested table 80 | { 81 | Table duck_methods; 82 | duck_methods.add("+swim()"); 83 | duck_methods.add("+quack()"); 84 | duck_methods.format().width(40); 85 | duck_methods[0].format().hide_border_bottom(); 86 | 87 | duck.add(duck_methods); 88 | } 89 | 90 | duck[0].format().align(Align::center); 91 | duck[1].format().hide_border_bottom(); 92 | 93 | class_diagram.add(duck); 94 | } 95 | 96 | // Global styling 97 | class_diagram.format().styles(Style::bold).align(Align::center).width(60).hide_border(); 98 | 99 | std::cout << class_diagram.xterm() << std::endl; 100 | } 101 | -------------------------------------------------------------------------------- /samples/colors.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table colors; 23 | 24 | colors.add("Font Color is Red", "Font Color is Blue", "Font Color is Green"); 25 | colors.add("Everything is Red", "Everything is Blue", "Everything is Green"); 26 | colors.add("Font Background is Red", "Font Background is Blue", "Font Background is Green"); 27 | 28 | colors[0][0].format().color(Color::red).styles(Style::bold); 29 | colors[0][1].format().color(Color::blue).styles(Style::bold); 30 | colors[0][2].format().color(Color::green).styles(Style::bold); 31 | 32 | colors[1][0] 33 | .format() 34 | .border_left_color(Color::red) 35 | .border_left_background_color(Color::red) 36 | .background_color(Color::red) 37 | .color(Color::red) 38 | .border_right_color(Color::blue) 39 | .border_right_background_color(Color::blue); 40 | 41 | colors[1][1].format().background_color(Color::blue).color(Color::blue).border_right_color(Color::green).border_right_background_color(Color::green); 42 | 43 | colors[1][2].format().background_color(Color::green).color(Color::green).border_right_color(Color::green).border_right_background_color(Color::green); 44 | 45 | colors[2][0].format().background_color(Color::red).styles(Style::bold); 46 | colors[2][1].format().background_color(Color::blue).styles(Style::bold); 47 | colors[2][2].format().background_color(Color::green).styles(Style::bold); 48 | 49 | std::cout << colors.xterm() << std::endl; 50 | // std::cout << "Markdown Table:\n" << colors.markdown() << std::endl; 51 | } 52 | -------------------------------------------------------------------------------- /samples/iterators.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table table; 23 | 24 | table.add("Company", "Contact", "Country"); 25 | table.add("Alfreds Futterkiste", "Maria Anders", "Germany"); 26 | table.add("Centro comercial Moctezuma", "Francisco Chang", "Mexico"); 27 | table.add("Ernst Handel", "Roland Mendel", "Austria"); 28 | table.add("Island Trading", "Helen Bennett", "UK"); 29 | table.add("Laughing Bacchus Winecellars", "Yoshi Tannamuri", "Canada"); 30 | table.add("Magazzini Alimentari Riuniti", "Giovanni Rovelli", "Italy"); 31 | 32 | // Set width of cells in each column 33 | table.column(0).format().width(40); 34 | table.column(1).format().width(30); 35 | table.column(2).format().width(30); 36 | 37 | // Iterate over cells in the first row 38 | for (auto &cell : table[0]) { 39 | cell.format().styles(Style::underline).align(Align::center); 40 | } 41 | 42 | // Iterator over cells in the first column 43 | for (auto &cell : table.column(0)) { 44 | if (cell.get() != "Company") { 45 | cell.format().align(Align::right); 46 | } 47 | } 48 | 49 | // Iterate over rows in the table 50 | size_t index = 0; 51 | for (auto &row : table) { 52 | // row.format().styles(Style::bold); 53 | 54 | // Set blue background color for alternate rows 55 | if (index > 0 && index % 2 == 0) { 56 | for (auto &cell : row) { 57 | cell.format().background_color(Color::blue); 58 | } 59 | } 60 | index += 1; 61 | } 62 | 63 | std::cout << table.xterm() << std::endl; 64 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 65 | } 66 | -------------------------------------------------------------------------------- /samples/mario.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table mario; 23 | size_t rows = 16; 24 | for (size_t i = 0; i < rows; ++i) { 25 | mario.add("█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", "█", 26 | "█"); 27 | } 28 | mario.format().color(Color::white).border("").corner("").border_padding(0).hide_border(); 29 | 30 | // Row 0 31 | for (size_t i = 7; i < 20; ++i) { 32 | mario[0][i].format().color(Color::red); 33 | } 34 | // Row 1 35 | for (size_t i = 5; i < 26; ++i) { 36 | mario[1][i].format().color(Color::red); 37 | } 38 | // Row 2 39 | for (size_t i = 5; i < 13; ++i) { 40 | mario[2][i].format().color(Color::green).styles(Style::faint); 41 | } 42 | for (size_t i = 13; i < 18; ++i) { 43 | mario[2][i].format().color(Color::yellow); 44 | } 45 | for (size_t i = 18; i < 20; ++i) { 46 | mario[2][i].format().color(Color::green).styles(Style::faint); 47 | } 48 | for (size_t i = 20; i < 22; ++i) { 49 | mario[2][i].format().color(Color::yellow); 50 | } 51 | // Row 3 52 | for (size_t i = 3; i < 7; ++i) { 53 | mario[3][i].format().color(Color::green).styles(Style::faint); 54 | } 55 | for (size_t i = 7; i < 9; ++i) { 56 | mario[3][i].format().color(Color::yellow); 57 | } 58 | for (size_t i = 9; i < 11; ++i) { 59 | mario[3][i].format().color(Color::green).styles(Style::faint); 60 | } 61 | for (size_t i = 11; i < 18; ++i) { 62 | mario[3][i].format().color(Color::yellow); 63 | } 64 | for (size_t i = 18; i < 20; ++i) { 65 | mario[3][i].format().color(Color::green).styles(Style::faint); 66 | } 67 | for (size_t i = 20; i < 26; ++i) { 68 | mario[3][i].format().color(Color::yellow); 69 | } 70 | // Row 4 71 | for (size_t i = 3; i < 7; ++i) { 72 | mario[4][i].format().color(Color::green).styles(Style::faint); 73 | } 74 | for (size_t i = 7; i < 9; ++i) { 75 | mario[4][i].format().color(Color::yellow); 76 | } 77 | for (size_t i = 9; i < 13; ++i) { 78 | mario[4][i].format().color(Color::green).styles(Style::faint); 79 | } 80 | for (size_t i = 13; i < 20; ++i) { 81 | mario[4][i].format().color(Color::yellow); 82 | } 83 | for (size_t i = 20; i < 22; ++i) { 84 | mario[4][i].format().color(Color::green).styles(Style::faint); 85 | } 86 | for (size_t i = 22; i < 28; ++i) { 87 | mario[4][i].format().color(Color::yellow); 88 | } 89 | // Row 5 90 | for (size_t i = 3; i < 9; ++i) { 91 | mario[5][i].format().color(Color::green).styles(Style::faint); 92 | } 93 | for (size_t i = 9; i < 18; ++i) { 94 | mario[5][i].format().color(Color::yellow); 95 | } 96 | for (size_t i = 18; i < 26; ++i) { 97 | mario[5][i].format().color(Color::green).styles(Style::faint); 98 | } 99 | // Row 6 100 | for (size_t i = 7; i < 24; ++i) { 101 | mario[6][i].format().color(Color::yellow); 102 | } 103 | // Row 7 104 | for (size_t i = 5; i < 11; ++i) { 105 | mario[7][i].format().color(Color::green).styles(Style::faint); 106 | } 107 | for (size_t i = 11; i < 13; ++i) { 108 | mario[7][i].format().color(Color::red); 109 | } 110 | for (size_t i = 13; i < 20; ++i) { 111 | mario[7][i].format().color(Color::green).styles(Style::faint); 112 | } 113 | // Row 8 114 | for (size_t i = 3; i < 11; ++i) { 115 | mario[8][i].format().color(Color::green).styles(Style::faint); 116 | } 117 | for (size_t i = 11; i < 13; ++i) { 118 | mario[8][i].format().color(Color::red); 119 | } 120 | for (size_t i = 13; i < 18; ++i) { 121 | mario[8][i].format().color(Color::green).styles(Style::faint); 122 | } 123 | for (size_t i = 18; i < 20; ++i) { 124 | mario[8][i].format().color(Color::red); 125 | } 126 | for (size_t i = 20; i < 26; ++i) { 127 | mario[8][i].format().color(Color::green).styles(Style::faint); 128 | } 129 | // Row 9 130 | for (size_t i = 1; i < 11; ++i) { 131 | mario[9][i].format().color(Color::green).styles(Style::faint); 132 | } 133 | for (size_t i = 11; i < 20; ++i) { 134 | mario[9][i].format().color(Color::red); 135 | } 136 | for (size_t i = 20; i < 29; ++i) { 137 | mario[9][i].format().color(Color::green).styles(Style::faint); 138 | } 139 | // Row 10 140 | for (size_t i = 1; i < 7; ++i) { 141 | mario[10][i].format().color(Color::yellow); 142 | } 143 | for (size_t i = 7; i < 9; ++i) { 144 | mario[10][i].format().color(Color::green).styles(Style::faint); 145 | } 146 | for (size_t i = 9; i < 11; ++i) { 147 | mario[10][i].format().color(Color::red); 148 | } 149 | for (size_t i = 11; i < 13; ++i) { 150 | mario[10][i].format().color(Color::yellow); 151 | } 152 | for (size_t i = 13; i < 18; ++i) { 153 | mario[10][i].format().color(Color::red); 154 | } 155 | for (size_t i = 18; i < 20; ++i) { 156 | mario[10][i].format().color(Color::yellow); 157 | } 158 | for (size_t i = 20; i < 22; ++i) { 159 | mario[10][i].format().color(Color::red); 160 | } 161 | for (size_t i = 22; i < 24; ++i) { 162 | mario[10][i].format().color(Color::green).styles(Style::faint); 163 | } 164 | for (size_t i = 24; i < 29; ++i) { 165 | mario[10][i].format().color(Color::yellow); 166 | } 167 | // Row 11 168 | for (size_t i = 1; i < 9; ++i) { 169 | mario[11][i].format().color(Color::yellow); 170 | } 171 | for (size_t i = 9; i < 22; ++i) { 172 | mario[11][i].format().color(Color::red); 173 | } 174 | for (size_t i = 22; i < 29; ++i) { 175 | mario[11][i].format().color(Color::yellow); 176 | } 177 | // Row 12 178 | for (size_t i = 1; i < 7; ++i) { 179 | mario[12][i].format().color(Color::yellow); 180 | } 181 | for (size_t i = 24; i < 29; ++i) { 182 | mario[12][i].format().color(Color::yellow); 183 | } 184 | for (size_t i = 7; i < 24; ++i) { 185 | mario[12][i].format().color(Color::red); 186 | } 187 | // Row 13 188 | for (size_t i = 5; i < 14; ++i) { 189 | mario[13][i].format().color(Color::red); 190 | } 191 | for (size_t i = 16; i < 24; ++i) { 192 | mario[13][i].format().color(Color::red); 193 | } 194 | // Row 14 195 | for (size_t i = 3; i < 12; ++i) { 196 | mario[14][i].format().color(Color::green).styles(Style::faint); 197 | } 198 | for (size_t i = 18; i < 26; ++i) { 199 | mario[14][i].format().color(Color::green).styles(Style::faint); 200 | } 201 | // Row 15 202 | for (size_t i = 1; i < 12; ++i) { 203 | mario[15][i].format().color(Color::green).styles(Style::faint); 204 | } 205 | for (size_t i = 18; i < 29; ++i) { 206 | mario[15][i].format().color(Color::green).styles(Style::faint); 207 | } 208 | mario.format().multi_bytes_character(true); 209 | 210 | std::cout << mario.xterm() << "\n"; 211 | } 212 | -------------------------------------------------------------------------------- /samples/moives.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | 19 | int main() 20 | { 21 | tabulate::Table movies; 22 | 23 | movies.add("S/N", "Movie Name", "Director", "Estimated Budget", "Release Date"); 24 | movies.add("tt1979376", "Toy Story 4", "Josh Cooley", 200000000, "21 June 2019"); 25 | movies.add("tt3263904", "Sully", "Clint Eastwood", 60000000, "9 September 2016"); 26 | movies.add("tt1535109", "Captain Phillips", "Paul Greengrass", 55000000, " 11 October 2013"); 27 | 28 | // center align 'Director' column 29 | movies.column(2).format().align(tabulate::Align::center); 30 | 31 | // right align 'Estimated Budget' column 32 | movies.column(3).format().align(tabulate::Align::right); 33 | 34 | // right align 'Release Date' column 35 | movies.column(4).format().align(tabulate::Align::right); 36 | 37 | // Color header cells 38 | for (size_t i = 0; i < movies.column_size(); ++i) { 39 | movies[0][i].format().color(tabulate::Color::yellow).styles(tabulate::Style::bold); 40 | } 41 | 42 | /** 43 | * output all supported format, and you can catch one or more via 44 | * 45 | * awk '/BEGIN/{ f = 1; next } /END/{ f = 0 } f' all-formats.txt 46 | * 47 | */ 48 | std::cout << "-----BEGIN XTERM TABLE-----" << std::endl; 49 | std::cout << movies.xterm() << std::endl; 50 | std::cout << "-----END XTERM TABLE-----" << std::endl; 51 | 52 | std::cout << "-----BEGIN ANSI TABLE-----" << std::endl; 53 | std::cout << movies.xterm(true) << std::endl; 54 | std::cout << "-----END ANSI TABLE-----" << std::endl; 55 | 56 | std::cout << "-----BEGIN MARKDOWN TABLE-----" << std::endl; 57 | std::cout << movies.markdown() << std::endl; 58 | std::cout << "-----END MARKDOWN TABLE-----" << std::endl; 59 | 60 | std::cout << "-----BEGIN LATEX TABLE-----" << std::endl; 61 | std::cout << movies.latex() << std::endl; 62 | std::cout << "-----END LATEX TABLE-----" << std::endl; 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /samples/refresh-table.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "tabulate.h" 25 | using namespace tabulate; 26 | 27 | int getch_noblocking(void) 28 | { 29 | fd_set rfds; 30 | FD_ZERO(&rfds); 31 | FD_SET(STDIN_FILENO, &rfds); 32 | 33 | struct timeval tv = {.tv_sec = 0, .tv_usec = 0}; 34 | return select(1, &rfds, NULL, NULL, &tv) >= 1 ? getchar() : -1; 35 | } 36 | 37 | int main() 38 | { 39 | std::cout << "\x1b[s"; 40 | while (true) { 41 | Table process_table; 42 | std::random_device rd; 43 | std::mt19937 gen(rd()); 44 | std::uniform_real_distribution<> dis(0, 1); 45 | 46 | process_table.add("PID", "%CPU", "%MEM", "User", "NI"); 47 | process_table.add("4297", round(dis(gen) * 100), round(dis(gen) * 100), "ubuntu", "20"); 48 | process_table.add("12671", round(dis(gen) * 100), round(dis(gen) * 100), "root", "0"); 49 | process_table.add("810", round(dis(gen) * 100), round(dis(gen) * 100), "root", "-20"); 50 | 51 | process_table.column(2).format().align(Align::center); 52 | process_table.column(3).format().align(Align::right); 53 | process_table.column(4).format().align(Align::right); 54 | 55 | for (size_t i = 0; i < 5; ++i) { 56 | process_table[0][i].format().color(Color::yellow).align(Align::center).styles(Style::bold); 57 | } 58 | 59 | std::cout << "\x1b[u"; 60 | std::cout << process_table.xterm() << std::endl; 61 | std::cout << "\nPress ENTER to exit..." << std::endl; 62 | 63 | if (getch_noblocking() == '\n') { 64 | break; 65 | } 66 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /samples/refresh-table.cc.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tqolf/tabulate/8d9aee3156eb6048a8398cb919e5d58f8d9fd084/samples/refresh-table.cc.skip -------------------------------------------------------------------------------- /samples/runic.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table table; 23 | 24 | /* 25 | This is a story of a bear and 26 | a wolf, who wandered the 27 | realms nine to fulfill a promise 28 | to one before; they walk the 29 | twilight path, destined to 30 | discower the truth 31 | that is to come. 32 | */ 33 | table.add("ᛏᚺᛁᛊ ᛁᛊ ᚨ ᛊᛏᛟᚱy ᛟᚠᚨ ᛒᛖᚨᚱ ᚨᚾᛞ\n" 34 | "ᚨ ᚹᛟᛚᚠ, ᚹᚺᛟ ᚹᚨᚾᛞᛖᚱᛖᛞ ᛏᚺᛖ\n" 35 | "ᚱᛖᚨᛚᛗᛊ ᚾᛁᚾᛖ ᛏᛟ ᚠᚢᛚᚠᛁᛚᛚ ᚨ ᛈᚱᛟᛗᛁᛊᛖ\n" 36 | "ᛏᛟ ᛟᚾᛖ ᛒᛖᚠᛟᚱᛖ; ᛏᚺᛖy ᚹᚨᛚᚲ ᛏᚺᛖ\n" 37 | "ᛏᚹᛁᛚᛁᚷᚺᛏ ᛈᚨᛏᚺ, ᛞᛖᛊᛏᛁᚾᛖᛞ ᛏᛟ\n" 38 | "ᛞᛁᛊcᛟᚹᛖᚱ ᛏᚺᛖ ᛏᚱᚢᛏᚺ\nᛏᚺᚨᛏ ᛁᛊ ᛏᛟ cᛟᛗᛖ."); 39 | 40 | table[0][0] 41 | .format() 42 | .multi_bytes_character(true) 43 | // Font styling 44 | .styles(Style::bold, Style::faint) 45 | .align(Align::center) 46 | .color(Color::red) 47 | .background_color(Color::yellow) 48 | // Corners 49 | .corner_top_left("ᛰ") 50 | .corner_top_right("ᛯ") 51 | .corner_bottom_left("ᛮ") 52 | .corner_bottom_right("ᛸ") 53 | .corner_top_left_color(Color::cyan) 54 | .corner_top_right_color(Color::yellow) 55 | .corner_bottom_left_color(Color::green) 56 | .corner_bottom_right_color(Color::red) 57 | // Borders 58 | .border_top("ᛜ") 59 | .border_bottom("ᛜ") 60 | .border_left("ᚿ") 61 | .border_right("ᛆ") 62 | .border_left_color(Color::yellow) 63 | .border_right_color(Color::green) 64 | .border_top_color(Color::cyan) 65 | .border_bottom_color(Color::red); 66 | 67 | std::cout << table.xterm() << std::endl; 68 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 69 | } 70 | -------------------------------------------------------------------------------- /samples/styles.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table table; 23 | table.add("Bold", "Italic", "Bold & Italic", "Blinking"); 24 | table.add("Underline", "Crossed", "faint", "Bold, Italic & Underlined"); 25 | table.add("Doubly Underline", "Invisable", "", ""); 26 | 27 | table[0][0].format().styles(Style::bold); 28 | 29 | table[0][1].format().styles(Style::italic); 30 | 31 | table[0][2].format().styles(Style::bold, Style::italic); 32 | 33 | table[0][3].format().styles(Style::blink); 34 | 35 | table[1][0].format().styles(Style::underline); 36 | 37 | table[1][1].format().styles(Style::crossed); 38 | 39 | table[1][2].format().styles(Style::faint); 40 | 41 | table[1][3].format().styles(Style::bold, Style::italic, Style::underline); 42 | 43 | table[2][0].format().styles(Style::doubly_underline); 44 | table[2][1].format().styles(Style::invisible); 45 | 46 | std::cout << table.xterm() << std::endl; 47 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 48 | } 49 | -------------------------------------------------------------------------------- /samples/summary.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table readme; 23 | readme.set_title("tabulate for Modern C++"); 24 | { 25 | Row &row = readme.add("https://github.com/tqolf/tabulate"); 26 | row.format().color(Color::white).align(Align::center).styles(Style::underline, Style::italic); 27 | } 28 | 29 | { 30 | Row &row = readme.add("Tabulate is a header-only library for printing aligned, formatted, and " 31 | "colorized tables in Modern C++"); 32 | row.format().styles(Style::italic).color(Color::magenta); 33 | } 34 | 35 | { 36 | Table highlights; 37 | highlights.add("Header-only Library", "Requires C++11", "Apache License"); 38 | Row &row = readme.add(highlights); 39 | row.format().align(Align::center).hide_border_top(); 40 | } 41 | 42 | Table empty_row; 43 | empty_row.format().hide_border(); 44 | 45 | { 46 | Row &row = readme.add(empty_row); 47 | row.format().hide_border_left().hide_border_right(); 48 | } 49 | 50 | { 51 | Row &row = readme.add("Easily format and align content within cells"); 52 | row.format().align(Align::center); 53 | 54 | row.format().color(Color::cyan).styles(Style::underline).border_color(Color::green).border_top_padding(0).border_bottom_padding(0); 55 | } 56 | 57 | { 58 | Table format; 59 | { 60 | Row &row = format.add("Horizontal Alignment", "Left aligned", "Center aligned", "Right aligned"); 61 | row.format().align(Align::center); 62 | row[0].format().color(Color::green); //.column_separator(":") 63 | } 64 | 65 | { 66 | Row &row = 67 | format.add("Word-Wrapping algorithm taking shamelessly from StackOverflow", "Long sentences automatically word-wrap based on the width of the column", 68 | "Word-wrapping also plays nicely with alignment rules. For instance, this cell is center " 69 | "aligned.", 70 | "Enforce \ncustom word-wrapping \nby embedding '\\n' \ncharacters in your cell\n content."); 71 | format.column(1).format().width(25).align(Align::left); 72 | format.column(2).format().width(25).align(Align::center); 73 | format.column(3).format().width(25).align(Align::right); 74 | 75 | row[0].format().align(Align::center); 76 | row[2].format().align(Align::center); 77 | row[3].format().align(Align::right); 78 | } 79 | 80 | format.column(0).format().width(23); 81 | format.column(1).format().border_left(":"); 82 | 83 | Row &row = readme.add(format); 84 | row.format().hide_border_top().border_top_padding(0); 85 | } 86 | 87 | { 88 | Row &row = readme.add(empty_row); 89 | row.format().hide_border_left().hide_border_right(); 90 | } 91 | 92 | { 93 | // clang-format off 94 | Table embedded_table( 95 | "You can even\n embed tables...", 96 | Table( 97 | "within tables", 98 | Table( 99 | "within tables", 100 | Table( 101 | "within tables", 102 | Table("within tables ...") 103 | ) 104 | ) 105 | ) 106 | ); 107 | embedded_table.format().align(Align::center); 108 | // clang-format on 109 | 110 | { 111 | Row &row = readme.add("Nested Representations"); 112 | row.format().align(Align::center); 113 | } 114 | 115 | Row &row = readme.add(embedded_table); 116 | row.format().hide_border_top().border_color(Color::white).color(Color::yellow); 117 | } 118 | 119 | { 120 | Row &row = readme.add("ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ " 121 | "ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ"); 122 | row.format().background_color(Color::red).hide_border_top().multi_bytes_character(true); 123 | } 124 | 125 | // Print the table 126 | readme.format().border_color(Color::yellow).align(Align::center); 127 | std::cout << readme.xterm() << std::endl; 128 | 129 | { 130 | Table chart; 131 | 132 | // row 0 - 9 133 | for (size_t i = 0; i < 9; ++i) { 134 | std::vector values; 135 | values.push_back(to_string(90 - i * 10)); 136 | for (size_t j = 0; j <= 50; ++j) { 137 | values.push_back(" "); 138 | } 139 | 140 | chart.add_multiple(values); 141 | } 142 | 143 | // row 10 144 | { 145 | std::vector values; 146 | for (int i = 0; i <= 12; ++i) { 147 | if ((i + 1) % 4 == 0) { 148 | values.push_back(to_string(i + 1)); 149 | } else { 150 | values.push_back(" "); 151 | } 152 | } 153 | chart.add_multiple(values); 154 | } 155 | chart.add(); 156 | chart.format().color(Color::white).border_left_padding(0).border_right_padding(0).hide_border(); 157 | chart.column(0).format().border_left_padding(1).border_right_padding(1).border_left(" "); 158 | 159 | // chart.format().width(2).hide_border(); 160 | for (size_t i = 0; i <= 18; ++i) { 161 | chart.column(i).format().width(2); 162 | } 163 | 164 | chart.column(2).format().border_color(Color::white).border_left("|").border_top("-"); 165 | chart.column(2).format(7, 8).background_color(Color::red); 166 | chart.column(3).format(5, 8).background_color(Color::yellow); 167 | chart.column(6).format(5, 8).background_color(Color::red); 168 | chart.column(7).format(4, 8).background_color(Color::yellow); 169 | chart.column(10).format(3, 8).background_color(Color::red); 170 | chart.column(11).format(1, 8).background_color(Color::yellow); 171 | 172 | chart[2][15].format().background_color(Color::red); 173 | chart[2][16].set("Batch 1"); 174 | 175 | chart.column(16).format().border_left_padding(1).width(20); 176 | 177 | chart[4][15].format().background_color(Color::yellow); 178 | chart[4][16].set("Batch 2"); 179 | 180 | chart.column(17).format().width(50); 181 | 182 | chart[4][17].set("Cells, rows, and columns"); 183 | chart[5][17].set("can be independently formatted."); 184 | chart[7][17].set("This cell is green and italic"); 185 | chart[7][17].format().color(Color::green).styles(Style::italic); 186 | 187 | chart[8][17].set("This one's yellow and right-aligned"); 188 | chart[8][17].format().color(Color::yellow).align(Align::right); 189 | 190 | chart[9][17].set("This one's on 🔥🔥🔥"); 191 | 192 | chart.format().align(Align::center); 193 | chart.column(0).format().border_left_padding(1).border_right_padding(1).border_left(" "); 194 | 195 | std::cout << chart.xterm() << std::endl; 196 | 197 | { 198 | Table legend; 199 | legend.add("Batch 1", "10", "40", "50", "20", "10", "50"); 200 | legend.add("Batch 2", "30", "60", "(70)", "50", "40", "30"); 201 | 202 | legend[0].format().align(Align::center); 203 | legend[1].format().align(Align::center); 204 | 205 | legend.column(0).format().align(Align::right).color(Color::green).background_color(Color::black); 206 | 207 | legend.column(2).format().color(Color::white).background_color(Color::red); 208 | 209 | legend[1][3].format().styles(Style::italic).color(Color::yellow); 210 | 211 | std::cout << legend.xterm() << "\n\n"; 212 | } 213 | } 214 | 215 | return 0; 216 | } 217 | -------------------------------------------------------------------------------- /samples/unicode.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table table; 23 | 24 | table.add("English", "I love you"); 25 | table.add("French", "Je t’aime"); 26 | table.add("Spanish", "Te amo"); 27 | table.add("German", "Ich liebe Dich"); 28 | table.add("Mandarin Chinese", "我爱你"); 29 | table.add("Japanese", "愛してる"); 30 | table.add("Korean", "사랑해 (Saranghae)"); 31 | table.add("Greek", "Σ΄αγαπώ (Se agapo)"); 32 | table.add("Italian", "Ti amo"); 33 | table.add("Russian", "Я тебя люблю (Ya tebya liubliu)"); 34 | table.add("Hebrew", "אני אוהב אותך (Ani ohev otakh)"); 35 | 36 | // Column 1 is using mult-byte characters 37 | table.column(1).format().multi_bytes_character(true); 38 | table.format().corner("♥").styles(Style::bold).corner_color(Color::magenta).border_color(Color::magenta); 39 | 40 | std::cout << table.xterm() << std::endl; 41 | } 42 | -------------------------------------------------------------------------------- /samples/universal-constants.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table universal_constants; 23 | 24 | universal_constants.add("Quantity", "Value"); 25 | universal_constants.add("Characteristic impedance of vacuum", "376.730 313 461... Ω"); 26 | universal_constants.add("Electric constant (permittivity of free space)", "8.854 187 817... × 10⁻¹²F·m⁻¹"); 27 | universal_constants.add("Magnetic constant (permeability of free space)", "4π × 10⁻⁷ N·A⁻² = 1.2566 370 614... × 10⁻⁶ N·A⁻²"); 28 | universal_constants.add("Gravitational constant (Newtonian constant of gravitation)", "6.6742(10) × 10⁻¹¹m³·kg⁻¹·s⁻²"); 29 | universal_constants.add("Planck's constant", "6.626 0693(11) × 10⁻³⁴ J·s"); 30 | universal_constants.add("Dirac's constant", "1.054 571 68(18) × 10⁻³⁴ J·s"); 31 | universal_constants.add("Speed of light in vacuum", "299 792 458 m·s⁻¹"); 32 | 33 | universal_constants.format().styles(Style::bold).border_top(" ").border_bottom(" ").border_left(" ").border_right(" ").corner(" "); 34 | 35 | universal_constants[0].format().border_top_padding(1).border_bottom_padding(1).align(Align::center).styles(Style::underline).background_color(Color::red); 36 | 37 | universal_constants.column(1).format().color(Color::yellow); 38 | 39 | universal_constants[0][1].format().background_color(Color::blue).color(Color::white); 40 | 41 | std::cout << universal_constants.xterm() << std::endl; 42 | // std::cout << "Markdown Table:\n" << universal_constants.markdown() << std::endl; 43 | } 44 | -------------------------------------------------------------------------------- /samples/word-wrap.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2022 Kiran Nowak(kiran.nowak@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "tabulate.h" 18 | using namespace tabulate; 19 | 20 | int main() 21 | { 22 | Table table; 23 | 24 | table.add("This paragraph contains a veryveryveryveryveryverylong word. The long word will " 25 | "break and word wrap to the next line.", 26 | "This paragraph \nhas embedded '\\n' \ncharacters and\n will break\n exactly " 27 | "where\n you want it\n to\n break."); 28 | 29 | table[0][0].format().width(20); 30 | table[0][1].format().width(50); 31 | 32 | std::cout << table.xterm() << std::endl; 33 | // std::cout << "Markdown Table:\n" << table.markdown() << std::endl; 34 | } 35 | -------------------------------------------------------------------------------- /scripts/24-bit-color.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This file echoes four gradients with 24-bit color codes 4 | # to the terminal to demonstrate their functionality. 5 | # The foreground escape sequence is ^[38;2;;;m 6 | # The background escape sequence is ^[48;2;;;m 7 | # range from 0 to 255 inclusive. 8 | # The escape sequence ^[0m returns output to default 9 | 10 | SEPARATOR=':' 11 | 12 | setBackgroundColor() 13 | { 14 | echo -en "\x1b[48${SEPARATOR}2${SEPARATOR}$1${SEPARATOR}$2${SEPARATOR}$3""m" 15 | } 16 | 17 | resetOutput() 18 | { 19 | echo -en "\x1b[0m\n" 20 | } 21 | 22 | # Gives a color $1/255 % along HSV 23 | # Who knows what happens when $1 is outside 0-255 24 | # Echoes "$red $green $blue" where 25 | # $red $green and $blue are integers 26 | # ranging between 0 and 255 inclusive 27 | rainbowColor() 28 | { 29 | let h=$1/43 30 | let f=$1-43*$h 31 | let t=$f*255/43 32 | let q=255-t 33 | 34 | if [ $h -eq 0 ] 35 | then 36 | echo "255 $t 0" 37 | elif [ $h -eq 1 ] 38 | then 39 | echo "$q 255 0" 40 | elif [ $h -eq 2 ] 41 | then 42 | echo "0 255 $t" 43 | elif [ $h -eq 3 ] 44 | then 45 | echo "0 $q 255" 46 | elif [ $h -eq 4 ] 47 | then 48 | echo "$t 0 255" 49 | elif [ $h -eq 5 ] 50 | then 51 | echo "255 0 $q" 52 | else 53 | # execution should never reach here 54 | echo "0 0 0" 55 | fi 56 | } 57 | 58 | for i in `seq 0 127`; do 59 | setBackgroundColor $i 0 0 60 | echo -en " " 61 | done 62 | resetOutput 63 | for i in `seq 255 128`; do 64 | setBackgroundColor $i 0 0 65 | echo -en " " 66 | done 67 | resetOutput 68 | 69 | for i in `seq 0 127`; do 70 | setBackgroundColor 0 $i 0 71 | echo -n " " 72 | done 73 | resetOutput 74 | for i in `seq 255 128`; do 75 | setBackgroundColor 0 $i 0 76 | echo -n " " 77 | done 78 | resetOutput 79 | 80 | for i in `seq 0 127`; do 81 | setBackgroundColor 0 0 $i 82 | echo -n " " 83 | done 84 | resetOutput 85 | for i in `seq 255 128`; do 86 | setBackgroundColor 0 0 $i 87 | echo -n " " 88 | done 89 | resetOutput 90 | 91 | for i in `seq 0 127`; do 92 | setBackgroundColor `rainbowColor $i` 93 | echo -n " " 94 | done 95 | resetOutput 96 | for i in `seq 255 128`; do 97 | setBackgroundColor `rainbowColor $i` 98 | echo -n " " 99 | done 100 | resetOutput 101 | --------------------------------------------------------------------------------