pax_global_header00006660000000000000000000000064141010054410014500gustar00rootroot0000000000000052 comment=09f2f05bea29d61b1df99e4b36f63d961156a580 rang-3.2/000077500000000000000000000000001410100544100122735ustar00rootroot00000000000000rang-3.2/.clang-format000066400000000000000000000033201410100544100146440ustar00rootroot00000000000000--- Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: false AlignOperands: false AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BreakBeforeBinaryOperators: All BreakBeforeBraces: WebKit BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false ColumnLimit: 80 ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 2 Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IndentCaseLabels: true IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MaxEmptyLinesToKeep: 2 NamespaceIndentation: Inner PointerAlignment: Right ReflowComments: true SortIncludes: false SpaceAfterCStyleCast: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 4 UseTab: Never ... rang-3.2/.editorconfig000066400000000000000000000004621410100544100147520ustar00rootroot00000000000000# editorconfig.org root = true [*] indent_style = space indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.{html,ejs,css,sass,scss,js,yml}] indent_size = 2 [*.md] trim_trailing_whitespace = false [{package.json,.travis.yml}] indent_size = 2 rang-3.2/.gitignore000066400000000000000000000004031410100544100142600ustar00rootroot00000000000000# Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app build/ .vscode/ rang-3.2/CMakeLists.txt000066400000000000000000000044561410100544100150440ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.1) project(rang VERSION 3.2.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(cmake/CMakeUtilities.cmake) include(GNUInstallDirs) set_verbose(RANG_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING "Installation directory for include files, a relative path that " "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.") set(RANG_HEADERS include/rang.hpp) add_library(${PROJECT_NAME} INTERFACE) target_include_directories(rang INTERFACE $ $ ) include(CMakePackageConfigHelpers) set_verbose(RANG_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/rang CACHE STRING "Installation directory for cmake files, a relative path that " "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute " "path.") set(version_config ${PROJECT_BINARY_DIR}/rang-config-version.cmake) set(project_config ${PROJECT_BINARY_DIR}/rang-config.cmake) set(pkgconfig ${PROJECT_BINARY_DIR}/rang.pc) set(targets_export_name rang-targets) set_verbose(RANG_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH "Installation directory for pkgconfig (.pc) files, a relative " "path that will be joined with ${CMAKE_INSTALL_PREFIX} or an " "absolute path.") write_basic_package_version_file( ${version_config} VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion ) join_paths(includedir_for_pc_file "\${prefix}" "${RANG_INC_DIR}") # Configure the PkgConfig configure_file( "${PROJECT_SOURCE_DIR}/cmake/rang.pc.in" "${pkgconfig}" @ONLY ) # Configuring the CMake Installer Helper configure_package_config_file( ${PROJECT_SOURCE_DIR}/cmake/rang-config.cmake.in ${project_config} INSTALL_DESTINATION ${RANG_CMAKE_DIR} ) set(INSTALL_TARGETS rang) # Use a namespace because CMake provides better diagnostics for namespaced # imported targets. export(TARGETS ${INSTALL_TARGETS} NAMESPACE rang:: FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake ) # Install version, config and target files. install( FILES ${project_config} ${version_config} DESTINATION ${RANG_CMAKE_DIR} ) install(FILES ${RANG_HEADERS} DESTINATION "${RANG_INC_DIR}") install(FILES "${pkgconfig}" DESTINATION "${RANG_PKGCONFIG_DIR}") rang-3.2/LICENSE000066400000000000000000000022721410100544100133030ustar00rootroot00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to rang-3.2/README.md000066400000000000000000000145321410100544100135570ustar00rootroot00000000000000# rang [![Build Status](https://travis-ci.org/agauniyal/rang.svg?branch=master)](https://travis-ci.org/agauniyal/rang) [![Build status](https://ci.appveyor.com/api/projects/status/jqpdoelli38h2a7w?svg=true)](https://ci.appveyor.com/project/agauniyal/rang) [![codecov](https://codecov.io/gh/agauniyal/rang/branch/master/graph/badge.svg)](https://codecov.io/gh/agauniyal/rang) [ ![Download](https://api.bintray.com/packages/agauniyal/rang/rang%3Arang/images/download.svg) ](https://bintray.com/agauniyal/rang/rang%3Arang/_latestVersion) ##### Colors for your Terminal. ![rang-demo](https://cloud.githubusercontent.com/assets/7630575/13501282/0bd00074-e18c-11e5-9848-5bd1f20566d9.gif)
Windows Demo ![rang-windows-demo](https://cloud.githubusercontent.com/assets/11349690/19836886/8134975e-9ebe-11e6-9ee4-c4657784ff3b.gif)
Example usage ------------- ```c++ #include "rang.hpp" using namespace std; using namespace rang; int main() { cout << "Plain old text" << style::bold << "Rang styled text!!" << style::reset << endl; } ``` Dependencies ------------ *rang* only depends on [C++ standard library](http://en.cppreference.com/w/cpp/header), `unistd.h` system header on unix and `windows.h` & `io.h` system headers on windows based systems. In other words, you don't need any 3rd party dependencies. Installation ------------ *rang* is a single header-only library. Put `rang.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project. Or, if you use the [conan package manager](https://www.conan.io/), follow these steps: 1. Add a reference to *rang* to the *requires* section of your project's `conanfile.txt` file: [requires] rang/3.1.0@rang/stable 2. Run conan's install command: conan install ## How to use *Rang* uses iostream objects - `cout`/`clog`/`cerr` to apply attributes to output text. Since *rang* aims to support both windows and unix like systems, it takes care of the os specific details and tries to provide a uniform interface. Due to incompatiblities b/w different OS versions, not all kinds of attributes are supported on every system so rang will try to skip the ones which might produce garbage(instead of pushing random ANSI escape codes on your streams). Detection of tty is also handled internally so you don't need to check if application user might redirect output to a file. > **Need support for non-ansi terminals? Check out [Termdb](https://github.com/agauniyal/termdb) which supports virtually all terminals and their capablities.** Apart from setting text attributes, you can also ask rang to override its default behaviour through these methods - ```cpp void rang::setControlMode(rang::control); ``` where `rang::control` takes - `control::Auto` - Automatically detects whether terminal supports color or not(**Default**) - `control::Off` - Turn off colors completely - `control::Force` - Force colors even if terminal doesn't supports them or output is redirected to non-terminal ```cpp void rang::setWinTermMode(rang::winTerm); ``` where `rang::winTerm` takes - `winTerm::Auto` - Checks for newer windows and picks Ansi otherwise falls back to Native(**Default**) - `winTerm::Native` - This method is supported in all versions of windows but supports less attributes - `winTerm::Ansi` - This method is supported in newer versions of windows and supports rich variety of attributes Supported attributes with their compatiblity are listed below - **Text Styles**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::style::bold` | yes | yes | | `rang::style::dim` | yes | no | | `rang::style::italic` | yes | no | | `rang::style::underline` | yes | no | | `rang::style::blink` | no | no | | `rang::style::rblink` | no | no | | `rang::style::reversed` | yes | yes | | `rang::style::conceal` | maybe | yes | | `rang::style::crossed` | yes | no | **Text Color**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::fg::black` | yes | yes | | `rang::fg::red` | yes | yes | | `rang::fg::green` | yes | yes | | `rang::fg::yellow` | yes | yes | | `rang::fg::blue` | yes | yes | | `rang::fg::magenta` | yes | yes | | `rang::fg::cyan` | yes | yes | | `rang::fg::gray` | yes | yes | **Background Color**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::bg::black` | yes | yes | | `rang::bg::red` | yes | yes | | `rang::bg::green` | yes | yes | | `rang::bg::yellow` | yes | yes | | `rang::bg::blue` | yes | yes | | `rang::bg::magenta` | yes | yes | | `rang::bg::cyan` | yes | yes | | `rang::bg::gray` | yes | yes | **Bright Foreground Color**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::fgB::black` | yes | yes | | `rang::fgB::red` | yes | yes | | `rang::fgB::green` | yes | yes | | `rang::fgB::yellow` | yes | yes | | `rang::fgB::blue` | yes | yes | | `rang::fgB::magenta` | yes | yes | | `rang::fgB::cyan` | yes | yes | | `rang::fgB::gray` | yes | yes | **Bright Background Color**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::bgB::black` | yes | yes | | `rang::bgB::red` | yes | yes | | `rang::bgB::green` | yes | yes | | `rang::bgB::yellow` | yes | yes | | `rang::bgB::blue` | yes | yes | | `rang::bgB::magenta` | yes | yes | | `rang::bgB::cyan` | yes | yes | | `rang::bgB::gray` | yes | yes | **Reset Styles/Colors**: | Code | Linux/Win/Others | Old Win | ---- | --------- | ------ | | `rang::style::reset` | yes | yes | | `rang::fg::reset` | yes | yes | | `rang::bg::reset` | yes | yes | ----- ## My terminal is not detected/gets garbage output! Check your env variable `TERM`'s value. Then open an issue [here](https://github.com/agauniyal/rang/issues/new) and make sure to mention `TERM`'s value along with your terminal name. ## Redirecting `cout`/`cerr`/`clog` rdbuf? Rang doesn't interfere if you try to redirect `cout`/`cerr`/`clog` to somewhere else and leaves the decision to the library user. Make sure you've read this [conversation](https://github.com/agauniyal/rang/pull/77#issuecomment-360991652) and check out the example code [here](https://gist.github.com/kingseva/a918ec66079a9475f19642ec31276a21). rang-3.2/appveyor.yml000066400000000000000000000054201410100544100146640ustar00rootroot00000000000000environment: matrix: - arch: x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 compiler: msvc2017 - arch: x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 compiler: msvc2015 install: - ps: wget 'https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip' -OutFile ninja.zip - cmd: 7z x ninja.zip -oC:\ninja > nul - cmd: set PATH=C:\ninja;%PATH% - cmd: set MESON_PYTHON_PATH=C:\python35-x64 - cmd: set PATH=%MESON_PYTHON_PATH%;%MESON_PYTHON_PATH%\Scripts;%PATH% - ps: $PKG_CONFIG_URL="http://ftp.gnome.org/pub/gnome/binaries/win64/dependencies/pkg-config_0.23-2_win64.zip"; - ps: $GLIB_URL="http://ftp.gnome.org/pub/gnome/binaries/win64/glib/2.26/glib_2.26.1-1_win64.zip"; - ps: $GETTEXT_URL="http://ftp.gnome.org/pub/gnome/binaries/win64/dependencies/gettext-runtime_0.18.1.1-2_win64.zip"; - ps: wget $GLIB_URL -OutFile glib.zip - ps: wget $GETTEXT_URL -OutFile gettext.zip - ps: wget $PKG_CONFIG_URL -OutFile pkg_config.zip - ps: wget 'https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.6.1/OpenCppCoverageSetup-x64-0.9.6.1.exe' -OutFile coverage_setup.exe - cmd: coverage_setup.exe /VERYSILENT - cmd: 7z x glib.zip -oC:\glib > nul - cmd: 7z x gettext.zip -oC:\gettext > nul - cmd: 7z x pkg_config.zip -oC:\pkg_config > nul - cmd: set OPENCPPPATH="C:\\Program Files\\OpenCppCoverage" - cmd: set PATH=C:\glib\bin\;C:\gettext\bin\;C:\pkg_config\bin\;%OPENCPPPATH%;%PATH% - cmd: python -m pip install meson conan codecov - cmd: if %compiler%==msvc2015 ( call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch% ) - cmd: if %compiler%==msvc2017 ( if %arch%==x64 ( call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat")) - cmd: conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan build_script: - cmd: mkdir build && cd build - cmd: conan install .. - cmd: conan build .. - cmd: meson configure -Dbuildtype=debug - cmd: meson configure -Dwarning_level=3 - cmd: ninja - cmd: cd test - cmd: mainTest.exe - cmd: colorTest.exe - cmd: envTermMissing.exe - cmd: OpenCppCoverage --sources C:\projects\rang --export_type=binary:envTermMissingReport.bin -- envTermMissing.exe - cmd: OpenCppCoverage --sources C:\projects\rang --export_type=binary:mainTestReport.bin -- mainTest.exe - cmd: OpenCppCoverage --sources C:\projects\rang --export_type=binary:colorTestReport.bin -- colorTest.exe - cmd: OpenCppCoverage --sources C:\projects\rang --export_type=cobertura:overallReport.xml --input_coverage=mainTestReport.bin --input_coverage=envTermMissingReport.bin --input_coverage=colorTestReport.bin - cmd: codecov --root ../.. --no-color --disable gcov -f overallReport.xml rang-3.2/cmake/000077500000000000000000000000001410100544100133535ustar00rootroot00000000000000rang-3.2/cmake/CMakeUtilities.cmake000066400000000000000000000036241410100544100172360ustar00rootroot00000000000000# This module provides function for joining paths # known from from most languages # # Original license: # SPDX-License-Identifier: (MIT OR CC0-1.0) # Explicit permission given to distribute this module under # the terms of the project as described in /LICENSE.rst. # Copyright 2020 Jan Tojnar # https://github.com/jtojnar/cmake-snips # # Modelled after Python’s os.path.join # https://docs.python.org/3.7/library/os.path.html#os.path.join # Windows not supported function(join_paths joined_path first_path_segment) set(temp_path "${first_path_segment}") foreach(current_segment IN LISTS ARGN) if(NOT ("${current_segment}" STREQUAL "")) if(IS_ABSOLUTE "${current_segment}") set(temp_path "${current_segment}") else() set(temp_path "${temp_path}/${current_segment}") endif() endif() endforeach() set(${joined_path} "${temp_path}" PARENT_SCOPE) endfunction() # Joins arguments and places the results in ${result_var}. function(join result_var) set(result "") foreach (arg ${ARGN}) set(result "${result}${arg}") endforeach () set(${result_var} "${result}" PARENT_SCOPE) endfunction() function(enable_module target) if (MSVC) set(BMI ${CMAKE_CURRENT_BINARY_DIR}/${target}.ifc) target_compile_options(${target} PRIVATE /interface /ifcOutput ${BMI} INTERFACE /reference fmt=${BMI}) endif () set_target_properties(${target} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI}) set_source_files_properties(${BMI} PROPERTIES GENERATED ON) endfunction() function(set_verbose) # cmake_parse_arguments is broken in CMake 3.4 (cannot parse CACHE) so use # list instead. list(GET ARGN 0 var) list(REMOVE_AT ARGN 0) list(GET ARGN 0 val) list(REMOVE_AT ARGN 0) list(REMOVE_AT ARGN 0) list(GET ARGN 0 type) list(REMOVE_AT ARGN 0) join(doc ${ARGN}) set(${var} ${val} CACHE ${type} ${doc}) endfunction()rang-3.2/cmake/rang-config.cmake.in000066400000000000000000000001561410100544100171560ustar00rootroot00000000000000@PACKAGE_INIT@ include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake) check_required_components(rang)rang-3.2/cmake/rang.pc.in000066400000000000000000000003601410100544100152320ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ includedir=@includedir_for_pc_file@ Name: rang Description: A Minimal, Header only Modern c++ library for terminal goodies Version: @PROJECT_VERSION@ Cflags: -I${includedir} rang-3.2/conanfile.py000066400000000000000000000013141410100544100146020ustar00rootroot00000000000000from conans import ConanFile, Meson class RangConan(ConanFile): name = "rang" version = "3.2.0" license = "The Unlicense" url = "https://github.com/agauniyal/rang" description = "A Minimal, Header only Modern c++ library for colors in your terminal" generators = "pkg_config" build_requires = "doctest/1.2.6@bincrafters/stable" exports_sources = "*" settings = "build_type" def build(self): meson = Meson(self) meson.configure(cache_build_folder="build") meson.build() def package(self): self.copy("*.hpp") self.copy(pattern="LICENSE", dst="licenses", keep_path=False) def package_id(self): self.info.header_only() rang-3.2/include/000077500000000000000000000000001410100544100137165ustar00rootroot00000000000000rang-3.2/include/rang.hpp000066400000000000000000000357351410100544100153730ustar00rootroot00000000000000#ifndef RANG_DOT_HPP #define RANG_DOT_HPP #if defined(__unix__) || defined(__unix) || defined(__linux__) #define OS_LINUX #elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) #define OS_WIN #elif defined(__APPLE__) || defined(__MACH__) #define OS_MAC #else #error Unknown Platform #endif #if defined(OS_LINUX) || defined(OS_MAC) #include #elif defined(OS_WIN) #if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600) #error \ "Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA" #elif !defined(_WIN32_WINNT) #define _WIN32_WINNT _WIN32_WINNT_VISTA #endif #include #include #include // Only defined in windows 10 onwards, redefining in lower windows since it // doesn't gets used in lower versions // https://docs.microsoft.com/en-us/windows/console/getconsolemode #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #endif #endif #include #include #include #include #include namespace rang { /* For better compability with most of terminals do not use any style settings * except of reset, bold and reversed. * Note that on Windows terminals bold style is same as fgB color. */ enum class style { reset = 0, bold = 1, dim = 2, italic = 3, underline = 4, blink = 5, rblink = 6, reversed = 7, conceal = 8, crossed = 9 }; enum class fg { black = 30, red = 31, green = 32, yellow = 33, blue = 34, magenta = 35, cyan = 36, gray = 37, reset = 39 }; enum class bg { black = 40, red = 41, green = 42, yellow = 43, blue = 44, magenta = 45, cyan = 46, gray = 47, reset = 49 }; enum class fgB { black = 90, red = 91, green = 92, yellow = 93, blue = 94, magenta = 95, cyan = 96, gray = 97 }; enum class bgB { black = 100, red = 101, green = 102, yellow = 103, blue = 104, magenta = 105, cyan = 106, gray = 107 }; enum class control { // Behaviour of rang function calls Off = 0, // toggle off rang style/color calls Auto = 1, // (Default) autodect terminal and colorize if needed Force = 2 // force ansi color output to non terminal streams }; // Use rang::setControlMode to set rang control mode enum class winTerm { // Windows Terminal Mode Auto = 0, // (Default) automatically detects wheter Ansi or Native API Ansi = 1, // Force use Ansi API Native = 2 // Force use Native API }; // Use rang::setWinTermMode to explicitly set terminal API for Windows // Calling rang::setWinTermMode have no effect on other OS namespace rang_implementation { inline std::atomic &controlMode() noexcept { static std::atomic value(control::Auto); return value; } inline std::atomic &winTermMode() noexcept { static std::atomic termMode(winTerm::Auto); return termMode; } inline bool supportsColor() noexcept { #if defined(OS_LINUX) || defined(OS_MAC) static const bool result = [] { const char *Terms[] = { "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm" }; const char *env_p = std::getenv("TERM"); if (env_p == nullptr) { return false; } return std::any_of(std::begin(Terms), std::end(Terms), [&](const char *term) { return std::strstr(env_p, term) != nullptr; }); }(); #elif defined(OS_WIN) // All windows versions support colors through native console methods static constexpr bool result = true; #endif return result; } #ifdef OS_WIN inline bool isMsysPty(int fd) noexcept { // Dynamic load for binary compability with old Windows const auto ptrGetFileInformationByHandleEx = reinterpret_cast( GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetFileInformationByHandleEx")); if (!ptrGetFileInformationByHandleEx) { return false; } HANDLE h = reinterpret_cast(_get_osfhandle(fd)); if (h == INVALID_HANDLE_VALUE) { return false; } // Check that it's a pipe: if (GetFileType(h) != FILE_TYPE_PIPE) { return false; } // POD type is binary compatible with FILE_NAME_INFO from WinBase.h // It have the same alignment and used to avoid UB in caller code struct MY_FILE_NAME_INFO { DWORD FileNameLength; WCHAR FileName[MAX_PATH]; }; auto pNameInfo = std::unique_ptr( new (std::nothrow) MY_FILE_NAME_INFO()); if (!pNameInfo) { return false; } // Check pipe name is template of // {"cygwin-","msys-"}XXXXXXXXXXXXXXX-ptyX-XX if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(), sizeof(MY_FILE_NAME_INFO))) { return false; } std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR)); if ((name.find(L"msys-") == std::wstring::npos && name.find(L"cygwin-") == std::wstring::npos) || name.find(L"-pty") == std::wstring::npos) { return false; } return true; } #endif inline bool isTerminal(const std::streambuf *osbuf) noexcept { using std::cerr; using std::clog; using std::cout; #if defined(OS_LINUX) || defined(OS_MAC) if (osbuf == cout.rdbuf()) { static const bool cout_term = isatty(fileno(stdout)) != 0; return cout_term; } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { static const bool cerr_term = isatty(fileno(stderr)) != 0; return cerr_term; } #elif defined(OS_WIN) if (osbuf == cout.rdbuf()) { static const bool cout_term = (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout))); return cout_term; } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { static const bool cerr_term = (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr))); return cerr_term; } #endif return false; } template using enableStd = typename std::enable_if< std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value, std::ostream &>::type; #ifdef OS_WIN struct SGR { // Select Graphic Rendition parameters for Windows console BYTE fgColor; // foreground color (0-15) lower 3 rgb bits + intense bit BYTE bgColor; // background color (0-15) lower 3 rgb bits + intense bit BYTE bold; // emulated as FOREGROUND_INTENSITY bit BYTE underline; // emulated as BACKGROUND_INTENSITY bit BOOLEAN inverse; // swap foreground/bold & background/underline BOOLEAN conceal; // set foreground/bold to background/underline }; enum class AttrColor : BYTE { // Color attributes for console screen buffer black = 0, red = 4, green = 2, yellow = 6, blue = 1, magenta = 5, cyan = 3, gray = 7 }; inline HANDLE getConsoleHandle(const std::streambuf *osbuf) noexcept { if (osbuf == std::cout.rdbuf()) { static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); return hStdout; } else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) { static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE); return hStderr; } return INVALID_HANDLE_VALUE; } inline bool setWinTermAnsiColors(const std::streambuf *osbuf) noexcept { HANDLE h = getConsoleHandle(osbuf); if (h == INVALID_HANDLE_VALUE) { return false; } DWORD dwMode = 0; if (!GetConsoleMode(h, &dwMode)) { return false; } dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(h, dwMode)) { return false; } return true; } inline bool supportsAnsi(const std::streambuf *osbuf) noexcept { using std::cerr; using std::clog; using std::cout; if (osbuf == cout.rdbuf()) { static const bool cout_ansi = (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf)); return cout_ansi; } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) { static const bool cerr_ansi = (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf)); return cerr_ansi; } return false; } inline const SGR &defaultState() noexcept { static const SGR defaultSgr = []() -> SGR { CONSOLE_SCREEN_BUFFER_INFO info; WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) || GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &info)) { attrib = info.wAttributes; } SGR sgr = { 0, 0, 0, 0, FALSE, FALSE }; sgr.fgColor = attrib & 0x0F; sgr.bgColor = (attrib & 0xF0) >> 4; return sgr; }(); return defaultSgr; } inline BYTE ansi2attr(BYTE rgb) noexcept { static const AttrColor rev[8] = { AttrColor::black, AttrColor::red, AttrColor::green, AttrColor::yellow, AttrColor::blue, AttrColor::magenta, AttrColor::cyan, AttrColor::gray }; return static_cast(rev[rgb]); } inline void setWinSGR(rang::bg col, SGR &state) noexcept { if (col != rang::bg::reset) { state.bgColor = ansi2attr(static_cast(col) - 40); } else { state.bgColor = defaultState().bgColor; } } inline void setWinSGR(rang::fg col, SGR &state) noexcept { if (col != rang::fg::reset) { state.fgColor = ansi2attr(static_cast(col) - 30); } else { state.fgColor = defaultState().fgColor; } } inline void setWinSGR(rang::bgB col, SGR &state) noexcept { state.bgColor = (BACKGROUND_INTENSITY >> 4) | ansi2attr(static_cast(col) - 100); } inline void setWinSGR(rang::fgB col, SGR &state) noexcept { state.fgColor = FOREGROUND_INTENSITY | ansi2attr(static_cast(col) - 90); } inline void setWinSGR(rang::style style, SGR &state) noexcept { switch (style) { case rang::style::reset: state = defaultState(); break; case rang::style::bold: state.bold = FOREGROUND_INTENSITY; break; case rang::style::underline: case rang::style::blink: state.underline = BACKGROUND_INTENSITY; break; case rang::style::reversed: state.inverse = TRUE; break; case rang::style::conceal: state.conceal = TRUE; break; default: break; } } inline SGR ¤t_state() noexcept { static SGR state = defaultState(); return state; } inline WORD SGR2Attr(const SGR &state) noexcept { WORD attrib = 0; if (state.conceal) { if (state.inverse) { attrib = (state.fgColor << 4) | state.fgColor; if (state.bold) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } else { attrib = (state.bgColor << 4) | state.bgColor; if (state.underline) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; } } else if (state.inverse) { attrib = (state.fgColor << 4) | state.bgColor; if (state.bold) attrib |= BACKGROUND_INTENSITY; if (state.underline) attrib |= FOREGROUND_INTENSITY; } else { attrib = state.fgColor | (state.bgColor << 4) | state.bold | state.underline; } return attrib; } template inline void setWinColorAnsi(std::ostream &os, T const value) { os << "\033[" << static_cast(value) << "m"; } template inline void setWinColorNative(std::ostream &os, T const value) { const HANDLE h = getConsoleHandle(os.rdbuf()); if (h != INVALID_HANDLE_VALUE) { setWinSGR(value, current_state()); // Out all buffered text to console with previous settings: os.flush(); SetConsoleTextAttribute(h, SGR2Attr(current_state())); } } template inline enableStd setColor(std::ostream &os, T const value) { if (winTermMode() == winTerm::Auto) { if (supportsAnsi(os.rdbuf())) { setWinColorAnsi(os, value); } else { setWinColorNative(os, value); } } else if (winTermMode() == winTerm::Ansi) { setWinColorAnsi(os, value); } else { setWinColorNative(os, value); } return os; } #else template inline enableStd setColor(std::ostream &os, T const value) { return os << "\033[" << static_cast(value) << "m"; } #endif } // namespace rang_implementation template inline rang_implementation::enableStd operator<<(std::ostream &os, const T value) { const control option = rang_implementation::controlMode(); switch (option) { case control::Auto: return rang_implementation::supportsColor() && rang_implementation::isTerminal(os.rdbuf()) ? rang_implementation::setColor(os, value) : os; case control::Force: return rang_implementation::setColor(os, value); default: return os; } } inline void setWinTermMode(const rang::winTerm value) noexcept { rang_implementation::winTermMode() = value; } inline void setControlMode(const control value) noexcept { rang_implementation::controlMode() = value; } } // namespace rang #undef OS_LINUX #undef OS_WIN #undef OS_MAC #endif /* ifndef RANG_DOT_HPP */ rang-3.2/meson.build000066400000000000000000000004441410100544100144370ustar00rootroot00000000000000project('rang', 'cpp', version : '3.2.0', default_options : ['cpp_std=c++11']) inc = include_directories('include') doctest = dependency('doctest') subdir('test') run_target('cppcheck', command : ['cppcheck', '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]) rang-3.2/test/000077500000000000000000000000001410100544100132525ustar00rootroot00000000000000rang-3.2/test/CMakeLists.txt000066400000000000000000000016441410100544100160170ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.12) project(rang-test) set(CMAKE_CXX_STANDARD 11 ) set(CMAKE_CXX_STANDARD_REQUIRED ON ) set(CMAKE_CXX_EXTENSIONS OFF) function(rang_add_test file_name) add_executable("${file_name}" "${file_name}.cpp") target_link_libraries("${file_name}" rang) endfunction() # simple tests ################################################################# rang_add_test(colorTest) rang_add_test(envTermMissing) # test that uses doctest ####################################################### set(doctest_DIR "" CACHE PATH "Directory containing doctestConfig.cmake") find_package(doctest) if (${doctest_FOUND} EQUAL 1) add_executable(all_rang_tests "test.cpp") target_link_libraries(all_rang_tests rang doctest::doctest) enable_testing() # cd build_dir && ctest --test-command all_tests add_test(NAME all_tests COMMAND "$") endif() rang-3.2/test/colorTest.cpp000066400000000000000000000114241410100544100157360ustar00rootroot00000000000000#include "rang.hpp" #include using namespace std; using namespace rang; void printHeading(const string &heading) { cout << '\n' << style::reset << heading << style::reset << bg::reset << fg::reset << endl; } void test_colors(ostream &os, const winTerm opt) { setWinTermMode(opt); printHeading("Text Style Test:"); os << style::bold << " Bold " << style::reset; os << style::italic << " Italic " << style::reset; os << style::underline << " Underlined " << style::reset; os << style::dim << " Dim " << style::reset; os << style::conceal << " Conceal " << style::reset; os << style::reversed << " Reversed " << style::reset; os << style::blink << " Blink " << style::reset; os << style::rblink << " rBlink " << style::reset; os << style::crossed << " Crossed " << style::reset << endl; printHeading("Background Test:"); os << bg::green << " Green " << bg::reset; os << bg::red << " Red " << bg::reset; os << bg::black << " Black " << bg::reset; os << bg::yellow << " Yellow " << bg::reset; os << bg::blue << " Blue " << bg::reset; os << bg::magenta << " Magenta " << bg::reset; os << bg::cyan << " Cyan " << bg::reset; os << bg::gray << " Grey " << bg::reset << endl; printHeading("Foreground Test:"); os << fg::green << " Green " << fg::reset; os << fg::red << " Red " << fg::reset; os << fg::black << " Black " << fg::reset; os << fg::yellow << " Yellow " << fg::reset; os << fg::blue << " Blue " << fg::reset; os << fg::magenta << " Magenta " << fg::reset; os << fg::cyan << " Cyan " << fg::reset; os << fg::gray << " Grey " << fg::reset << endl; printHeading("Bright Background Test:"); os << bgB::green << " Green " << bg::reset; os << bgB::red << " Red " << bg::reset; os << bgB::black << " Black " << bg::reset; os << bgB::yellow << " Yellow " << bg::reset; os << bgB::blue << " Blue " << bg::reset; os << bgB::magenta << " Magenta " << bg::reset; os << bgB::cyan << " Cyan " << bg::reset; os << bgB::gray << " Grey " << bg::reset << endl; printHeading("Bright Foreground Test:"); os << fgB::green << " Green " << fg::reset; os << fgB::red << " Red " << fg::reset; os << fgB::black << " Black " << fg::reset; os << fgB::yellow << " Yellow " << fg::reset; os << fgB::blue << " Blue " << fg::reset; os << fgB::magenta << " Magenta " << fg::reset; os << fgB::cyan << " Cyan " << fg::reset; os << fgB::gray << " Grey " << fg::reset << endl; } void enumerateWinTerms() { cout << endl; cout << "_________________________________________________________________"; cout << "\n\n" << style::reset << style::bold << "Printing for WinTerm = Auto" << style::reset << bg::reset << fg::reset << '\n'; cout << "_________________________________________________________________"; test_colors(cout, winTerm::Auto); test_colors(clog, winTerm::Auto); test_colors(cerr, winTerm::Auto); cout << "-------------------------------------------------------------\n\n"; cout << endl; cout << "_________________________________________________________________"; cout << "\n\n" << style::reset << style::bold << "Printing for WinTerm = Ansi" << style::reset << bg::reset << fg::reset << '\n'; cout << "_________________________________________________________________"; test_colors(cout, winTerm::Ansi); test_colors(clog, winTerm::Ansi); test_colors(cerr, winTerm::Ansi); cout << "-------------------------------------------------------------\n\n"; cout << endl; cout << "_________________________________________________________________"; cout << "\n\n" << style::reset << style::bold << "Printing for WinTerm = Native" << style::reset << bg::reset << fg::reset << '\n'; cout << "_________________________________________________________________"; test_colors(cout, winTerm::Native); test_colors(clog, winTerm::Native); test_colors(cerr, winTerm::Native); cout << "-------------------------------------------------------------\n\n"; } int main() { cout << "\n\n\n" << style::reset << style::underline << style::bold << "Control = Auto" << style::reset << bg::reset << fg::reset << endl; setControlMode(control::Auto); enumerateWinTerms(); cout << "\n\n\n" << style::reset << style::underline << style::bold << "Control = Force " << style::reset << bg::reset << fg::reset << endl; setControlMode(control::Force); enumerateWinTerms(); cout << "\n\n\n" << style::reset << style::underline << style::bold << "Control = Off " << style::reset << bg::reset << fg::reset << endl; setControlMode(control::Off); enumerateWinTerms(); } rang-3.2/test/envTermMissing.cpp000066400000000000000000000010221410100544100167230ustar00rootroot00000000000000#include "rang.hpp" #include using std::cout; using std::endl; using std::getenv; int main() { #if defined(WIN32) || defined(_WIN32) || defined(_WIN64) return 0; #else const auto TERM = getenv("TERM"); if (TERM != nullptr) { cout << "Unsetting $PATH: " << TERM << '\n'; unsetenv("TERM"); } cout << rang::fg::green << "===NO COLORS AS FALLBACK===" << endl; if (TERM != nullptr) { cout << "Setting $PATH: " << TERM << '\n'; setenv("TERM", TERM, 1); } #endif } rang-3.2/test/meson.build000066400000000000000000000005711410100544100154170ustar00rootroot00000000000000mainTest = executable('mainTest', 'test.cpp', include_directories : inc, dependencies : doctest) test('mainTest', mainTest) colorTest = executable('colorTest', 'colorTest.cpp', include_directories : inc) test('colorTest', colorTest) envTermMissing = executable('envTermMissing', 'envTermMissing.cpp', include_directories : inc) test('envTermMissing', envTermMissing) rang-3.2/test/test.cpp000066400000000000000000000177431410100544100147510ustar00rootroot00000000000000#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "doctest.h" #include "rang.hpp" #include #include using namespace std; using namespace rang; #if defined(__unix__) || defined(__unix) || defined(__linux__) #define OS_LINUX #elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) #define OS_WIN #elif defined(__APPLE__) || defined(__MACH__) #define OS_MAC #else #error Unknown Platform #endif TEST_CASE("Rang printing with control::Off and cout") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Off); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *coutbuf = cout.rdbuf(); cout.rdbuf(out.rdbuf()); cout << fg::blue << s << style::reset; cout.rdbuf(coutbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Auto") { setWinTermMode(winTerm::Auto); ofstream out(fileName); streambuf *coutbuf = cout.rdbuf(); cout.rdbuf(out.rdbuf()); cout << fg::blue << s << style::reset; cout.rdbuf(coutbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *coutbuf = cout.rdbuf(); cout.rdbuf(out.rdbuf()); cout << fg::blue << s << style::reset; cout.rdbuf(coutbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } } TEST_CASE("Rang printing with control::Force and cout") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Force); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *coutbuf = cout.rdbuf(); cout.rdbuf(out.rdbuf()); cout << fg::blue << s << style::reset; cout.rdbuf(coutbuf); out.close(); ifstream in(fileName); string output; getline(in, output); #if defined(OS_LINUX) || defined(OS_MAC) REQUIRE(s != output); REQUIRE(s.size() < output.size()); #elif defined(OS_WIN) REQUIRE(s == output); #endif } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *coutbuf = cout.rdbuf(); cout.rdbuf(out.rdbuf()); cout << fg::blue << s << style::reset; cout.rdbuf(coutbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s != output); REQUIRE(s.size() < output.size()); } } TEST_CASE("Rang printing with control::Off and cerr") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Off); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *cerrbuf = cerr.rdbuf(); cerr.rdbuf(out.rdbuf()); cerr << fg::blue << s << style::reset; cerr.rdbuf(cerrbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Auto") { setWinTermMode(winTerm::Auto); ofstream out(fileName); streambuf *cerrbuf = cerr.rdbuf(); cerr.rdbuf(out.rdbuf()); cerr << fg::blue << s << style::reset; cerr.rdbuf(cerrbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *cerrbuf = cerr.rdbuf(); cerr.rdbuf(out.rdbuf()); cerr << fg::blue << s << style::reset; cerr.rdbuf(cerrbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } } TEST_CASE("Rang printing with control::Force and cerr") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Force); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *cerrbuf = cerr.rdbuf(); cerr.rdbuf(out.rdbuf()); cerr << fg::blue << s << style::reset; cerr.rdbuf(cerrbuf); out.close(); ifstream in(fileName); string output; getline(in, output); #if defined(OS_LINUX) || defined(OS_MAC) REQUIRE(s != output); REQUIRE(s.size() < output.size()); #elif defined(OS_WIN) REQUIRE(s == output); #endif } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *cerrbuf = cerr.rdbuf(); cerr.rdbuf(out.rdbuf()); cerr << fg::blue << s << style::reset; cerr.rdbuf(cerrbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s != output); REQUIRE(s.size() < output.size()); } } TEST_CASE("Rang printing with control::Off and clog") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Off); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *clogbuf = clog.rdbuf(); clog.rdbuf(out.rdbuf()); clog << fg::blue << s << style::reset; clog.rdbuf(clogbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Auto") { setWinTermMode(winTerm::Auto); ofstream out(fileName); streambuf *clogbuf = clog.rdbuf(); clog.rdbuf(out.rdbuf()); clog << fg::blue << s << style::reset; clog.rdbuf(clogbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *clogbuf = clog.rdbuf(); clog.rdbuf(out.rdbuf()); clog << fg::blue << s << style::reset; clog.rdbuf(clogbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s == output); } } TEST_CASE("Rang printing with control::Force and clog") { const string s = "Hello World"; const string fileName = "outoutoutout.txt"; setControlMode(control::Force); SUBCASE("WinTerm = Native") { setWinTermMode(winTerm::Native); ofstream out(fileName); streambuf *clogbuf = clog.rdbuf(); clog.rdbuf(out.rdbuf()); clog << fg::blue << s << style::reset; clog.rdbuf(clogbuf); out.close(); ifstream in(fileName); string output; getline(in, output); #if defined(OS_LINUX) || defined(OS_MAC) REQUIRE(s != output); REQUIRE(s.size() < output.size()); #elif defined(OS_WIN) REQUIRE(s == output); #endif } SUBCASE("WinTerm = Ansi") { setWinTermMode(winTerm::Ansi); ofstream out(fileName); streambuf *clogbuf = clog.rdbuf(); clog.rdbuf(out.rdbuf()); clog << fg::blue << s << style::reset; clog.rdbuf(clogbuf); out.close(); ifstream in(fileName); string output; getline(in, output); REQUIRE(s != output); REQUIRE(s.size() < output.size()); } } rang-3.2/test_package/000077500000000000000000000000001410100544100147255ustar00rootroot00000000000000rang-3.2/test_package/conanfile.py000066400000000000000000000005301410100544100172330ustar00rootroot00000000000000from conans import ConanFile, Meson import os class RangConan(ConanFile): generators = "pkg_config" exports_sources = "*" def build(self): meson = Meson(self) meson.configure() meson.build() def imports(self): self.copy("*.hpp") def test(self): self.run(".%svisualTest" % os.sep) rang-3.2/test_package/meson.build000066400000000000000000000003521410100544100170670ustar00rootroot00000000000000project('rang', 'cpp', version : '3.2.0', default_options : ['cpp_std=c++11']) inc = include_directories('include') visualTest = executable('visualTest', 'visualTest.cpp', include_directories : inc) test('visualTest', visualTest) rang-3.2/test_package/visualTest.cpp000066400000000000000000000004241410100544100175740ustar00rootroot00000000000000#include "rang.hpp" #include using namespace std; using namespace rang; int main() { cout << endl << style::reset << bg::green << fg::gray << style::bold << " Rang works! " << bg::reset << fg::reset << style::reset << '\n' << endl; }