forked from Alepha/Alepha
Update and consolidate the console and colors code.
This introduces a subset of SGR-Name syntax.
This commit is contained in:
@ -13,7 +13,7 @@ main( const int argcnt, const char *const argvec[] )
|
||||
|
||||
static auto tests= Alepha::Utility::enroll <=[]
|
||||
{
|
||||
using namespace Alepha::exports::auto_raii;
|
||||
using namespace Alepha::Hydrogen::exports::auto_raii;
|
||||
using namespace Alepha::Testing::exports::literals;
|
||||
|
||||
using Alepha::Testing::exports::TestState;
|
||||
|
182
Console.cpp
182
Console.cpp
@ -39,7 +39,7 @@ static_assert( __cplusplus > 2020'00 );
|
||||
// universally supported for effectively all cases modern users will care about.
|
||||
|
||||
|
||||
namespace Alepha::Cavorite ::detail:: console
|
||||
namespace Alepha::Hydrogen ::detail:: console
|
||||
{
|
||||
namespace
|
||||
{
|
||||
@ -87,6 +87,7 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
auto screenWidthEnvLimit() { return applicationName() + "_SCREEN_WIDTH_LIMIT"; }
|
||||
auto disableColorsEnv() { return applicationName() + "_DISABLE_COLOR_TEXT"; }
|
||||
auto colorsEnv() { return applicationName() + "_COLORS"; }
|
||||
auto sgr_nameEnv() { return applicationName() + "_SGR_NAMES"; }
|
||||
|
||||
// TODO: Put this in a library
|
||||
int
|
||||
@ -113,7 +114,7 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
bool
|
||||
colorEnabled()
|
||||
{
|
||||
if( not colorState.has_value() ) return getenv( disableColorsEnv().c_str() );
|
||||
if( not colorState.has_value() ) return not ::getenv( disableColorsEnv().c_str() );
|
||||
|
||||
if( colorState.value() == "never"_value ) return false;
|
||||
if( colorState.value() == "always"_value ) return true;
|
||||
@ -124,6 +125,98 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
|
||||
StaticValue< std::map< Style, SGR_String > > colorVariables;
|
||||
|
||||
|
||||
SGR_String
|
||||
parse( const std::string &token )
|
||||
{
|
||||
const std::map< std::string, std::function< SGR_String () > > simple=
|
||||
{
|
||||
{ "reset", resetTextEffects },
|
||||
{ "bold", setBold },
|
||||
{ "dim", setFaint },
|
||||
{ "faint", setFaint },
|
||||
{ "italic", setItalic },
|
||||
{ "underline", setUnderline },
|
||||
{ "under", setUnderline },
|
||||
{ "blink", setBlink },
|
||||
{ "strike", setStrike },
|
||||
{ "strikethrough", setStrike },
|
||||
{ "strikethru", setStrike },
|
||||
{ "doubleunderline", setDoubleUnderline },
|
||||
{ "doubleunder", setDoubleUnderline },
|
||||
{ "framed", setFramed },
|
||||
{ "encircled", setEncircled },
|
||||
{ "overline", setOverline },
|
||||
};
|
||||
if( simple.contains( token ) ) return simple.at( token )();
|
||||
|
||||
// The `fg:` is optional in "SGR Name"...
|
||||
if( token.starts_with( "fg:" ) ) return parse( token.substr( 2 ) );
|
||||
|
||||
if( token.starts_with( "ansi:" ) ) return { '3' + token.substr( 5 ) };
|
||||
if( token.starts_with( "ext:grey" ) )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "3;5;";
|
||||
oss << int( TextColor::greyscale_base ) + boost::lexical_cast< int >( token.substr( 8 ) );
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
if( token.starts_with( "ext:rgb" ) )
|
||||
{
|
||||
const std::string rgb= token.substr( 7 );
|
||||
if( rgb.size() != 3 ) throw std::runtime_error{ "RGB request with more than 3 digits..." };
|
||||
const int r= boost::lexical_cast< int >( rgb.substr( 0, 1 ) );
|
||||
const int g= boost::lexical_cast< int >( rgb.substr( 1, 1 ) );
|
||||
const int b= boost::lexical_cast< int >( rgb.substr( 2, 1 ) );
|
||||
std::ostringstream oss;
|
||||
oss << "3;5;";
|
||||
oss << int( TextColor::rgb_base ) + r * int( TextColor::red_radix ) + g * int( TextColor::green_radix ) + b * int( TextColor::blue_radix );
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
if( token.starts_with( "ext:" ) ) return { "38;5;" + token.substr( 4 ) };
|
||||
if( token.starts_with( "#" ) )
|
||||
{
|
||||
const auto code= token.substr( 1 );
|
||||
const auto [ r_s, g_s, b_s ]= evaluate <=[&]
|
||||
{
|
||||
if( code.size() == 3 ) return std::tuple{ code.substr( 0, 1 ), code.substr( 1, 1 ), code.substr( 2, 1 ) };
|
||||
if( code.size() == 6 ) return std::tuple{ code.substr( 0, 2 ), code.substr( 2, 2 ), code.substr( 4, 2 ) };
|
||||
throw std::runtime_error( "True color code parse error." );
|
||||
};
|
||||
int r, g, b;
|
||||
{
|
||||
std::istringstream iss{ r_s };
|
||||
iss >> std::hex >> r;
|
||||
}
|
||||
|
||||
{
|
||||
std::istringstream iss{ g_s };
|
||||
iss >> std::hex >> g;
|
||||
}
|
||||
|
||||
{
|
||||
std::istringstream iss{ b_s };
|
||||
iss >> std::hex >> b;
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "38;2;" << std::dec << r << ';' << g << ';' << b;
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
throw std::runtime_error{ "Unrecognized SGR Name keyword: `" + token + "`" };
|
||||
}
|
||||
|
||||
SGR_String
|
||||
parseTokens( std::vector< std::string > tokens )
|
||||
{
|
||||
|
||||
SGR_String rv;
|
||||
for( const auto token: tokens ) rv+= parse( token );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
auto init= enroll <=[]
|
||||
{
|
||||
--"screen-width"_option << affectsHelp << cachedScreenWidth << "Sets the screen width for use in automatic word-wrapping. !default!";
|
||||
@ -136,6 +229,7 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
{
|
||||
std::cout << name.name << ": ^[[" << sgr.code << "m" << std::endl;
|
||||
}
|
||||
::exit( EXIT_SUCCESS );
|
||||
}
|
||||
<< "Emit a list with the color variables supported by this application. For use with the `" << colorsEnv()
|
||||
<< "` environment variable.";
|
||||
@ -156,7 +250,27 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
<< "Emit a BASH command which will set the appropriate environment variable to capture the current color settings for this "
|
||||
<< "application.";
|
||||
|
||||
parse_environment_variable_for_color:
|
||||
parse_environment_variables_for_color:
|
||||
// First the SGR Name language
|
||||
if( getenv( sgr_nameEnv().c_str() ) )
|
||||
{
|
||||
const std::string contents= getenv( sgr_nameEnv().c_str() );
|
||||
|
||||
for( const auto var: split( contents, ';' ) )
|
||||
{
|
||||
const auto parsed= split( var, '=' );
|
||||
if( parsed.size() != 2 )
|
||||
{
|
||||
throw std::runtime_error{ "Color environment variable parse error in: `" + var + "`." };
|
||||
}
|
||||
|
||||
const Style name{ parsed.at( 0 ) };
|
||||
const auto value= parsed.at( 1 );
|
||||
|
||||
colorVariables()[ name ]= parseTokens( split( value, ' ' ) );
|
||||
}
|
||||
}
|
||||
// Then the regular terminal codes
|
||||
if( getenv( colorsEnv().c_str() ) )
|
||||
{
|
||||
const std::string contents= getenv( colorsEnv().c_str() );
|
||||
@ -180,7 +294,7 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
std::ostream &
|
||||
csi( std::ostream &os )
|
||||
{
|
||||
return os << "\e";
|
||||
return os << "\e[";
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +327,7 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
std::ostream &
|
||||
exports::operator << ( std::ostream &os, decltype( resetStyle ) )
|
||||
{
|
||||
if( colorEnabled )
|
||||
if( colorEnabled() )
|
||||
{
|
||||
sendSGR( os, resetTextEffects() );
|
||||
}
|
||||
@ -370,9 +484,18 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
|
||||
void Console::clearScreen() { csi() << "2J"; }
|
||||
|
||||
SGR_String exports::resetTextEffects() { return {}; }
|
||||
SGR_String exports::resetTextEffects() { return { "0" }; }
|
||||
|
||||
SGR_String exports::setBold() { return { "1" }; }
|
||||
SGR_String exports::setFaint() { return { "2" }; }
|
||||
SGR_String exports::setItalic() { return { "3" }; }
|
||||
SGR_String exports::setUnderline() { return { "4" }; }
|
||||
SGR_String exports::setBlink() { return { "5" }; }
|
||||
SGR_String exports::setStrike() { return { "9" }; }
|
||||
SGR_String exports::setDoubleUnderline() { return { "21" }; }
|
||||
SGR_String exports::setFramed() { return { "51" }; }
|
||||
SGR_String exports::setEncircled() { return { "52" }; }
|
||||
SGR_String exports::setOverline() { return { "52" }; }
|
||||
|
||||
SGR_String
|
||||
exports::setFgColor( const BasicTextColor c )
|
||||
@ -423,6 +546,53 @@ namespace Alepha::Cavorite ::detail:: console
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
SGR_String
|
||||
exports::setExtUlColor( const TextColor ul )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "58;5;" << int( ul );
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
SGR_String exports::setFgTrueColor( const int rgb ) { return setFgTrueColor( rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); }
|
||||
|
||||
SGR_String
|
||||
exports::setFgTrueColor( const int r, const int g, const int b )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "38;2;" << r << ';' << g << ';' << b;
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
SGR_String exports::setBgTrueColor( const int rgb ) { return setBgTrueColor( rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); }
|
||||
|
||||
SGR_String
|
||||
exports::setBgTrueColor( const int r, const int g, const int b )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "48;2;" << r << ';' << g << ';' << b;
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
SGR_String exports::setUlTrueColor( const int rgb ) { return setUlTrueColor( rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); }
|
||||
|
||||
SGR_String
|
||||
exports::setUlTrueColor( const int r, const int g, const int b )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "58;2;" << r << ';' << g << ';' << b;
|
||||
return { std::move( oss ).str() };
|
||||
}
|
||||
|
||||
SGR_String
|
||||
exports::operator ""_sgr( const char *const p, const std::size_t sz )
|
||||
{
|
||||
const std::string s{ p, p + sz };
|
||||
|
||||
const auto tokens= split( s, ' ' );
|
||||
return parseTokens( tokens );
|
||||
}
|
||||
|
||||
int
|
||||
exports::getConsoleWidth()
|
||||
{
|
||||
|
81
Console.h
81
Console.h
@ -2,6 +2,8 @@ static_assert( __cplusplus > 2020'00 );
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Alepha/Alepha.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
@ -14,7 +16,7 @@ static_assert( __cplusplus > 2020'00 );
|
||||
// As long as this works on most (all?) modern terminal emulators, this should be
|
||||
// fine.
|
||||
|
||||
namespace Alepha::inline Cavorite ::detail:: console
|
||||
namespace Alepha::Hydrogen ::detail:: console
|
||||
{
|
||||
inline namespace exports {}
|
||||
|
||||
@ -30,12 +32,23 @@ namespace Alepha::inline Cavorite ::detail:: console
|
||||
std::string code;
|
||||
};
|
||||
|
||||
inline auto
|
||||
operator ""_sgr( const char *const p, const std::size_t sz )
|
||||
[[nodiscard]] inline SGR_String
|
||||
operator + ( const SGR_String lhs, const SGR_String rhs )
|
||||
{
|
||||
return SGR_String{ { p, p + sz } };
|
||||
if( lhs.code.empty() ) return rhs;
|
||||
if( rhs.code.empty() ) return lhs;
|
||||
return SGR_String{ lhs.code + ';' + rhs.code };
|
||||
}
|
||||
|
||||
inline SGR_String &
|
||||
operator += ( SGR_String &lhs, const SGR_String rhs )
|
||||
{
|
||||
return lhs= lhs + rhs;
|
||||
}
|
||||
|
||||
// Parses sgr token names, like "bold ext:red"
|
||||
[[nodiscard]] SGR_String operator ""_sgr( const char *p, std::size_t sz );
|
||||
|
||||
enum class BasicTextColor : int;
|
||||
enum class TextColor : int;
|
||||
|
||||
@ -143,7 +156,17 @@ namespace Alepha::inline Cavorite ::detail:: console
|
||||
{
|
||||
[[nodiscard]] SGR_String resetTextEffects();
|
||||
|
||||
// Non Colour effects (Mostly sorted by ANSI/ECMA SGR code numeric order)
|
||||
[[nodiscard]] SGR_String setBold();
|
||||
[[nodiscard]] SGR_String setFaint();
|
||||
[[nodiscard]] SGR_String setItalic();
|
||||
[[nodiscard]] SGR_String setUnderline();
|
||||
[[nodiscard]] SGR_String setBlink();
|
||||
[[nodiscard]] SGR_String setStrike();
|
||||
[[nodiscard]] SGR_String setDoubleUnderline();
|
||||
[[nodiscard]] SGR_String setFramed();
|
||||
[[nodiscard]] SGR_String setEncircled();
|
||||
[[nodiscard]] SGR_String setOverline();
|
||||
|
||||
[[nodiscard]] SGR_String setFgColor( BasicTextColor fg );
|
||||
[[nodiscard]] SGR_String setBgColor( BasicTextColor bg );
|
||||
@ -152,6 +175,7 @@ namespace Alepha::inline Cavorite ::detail:: console
|
||||
[[nodiscard]] SGR_String setExtFgColor( TextColor fg );
|
||||
[[nodiscard]] SGR_String setExtBgColor( TextColor fg );
|
||||
[[nodiscard]] SGR_String setExtColor( TextColor fg, TextColor bg );
|
||||
[[nodiscard]] SGR_String setExtUlColor( TextColor ul );
|
||||
|
||||
// Basic color wrapping aliases:
|
||||
[[nodiscard]] inline SGR_String setExtFgColor( const BasicTextColor fg ) { return setExtFgColor( static_cast< TextColor >( fg ) ); }
|
||||
@ -167,13 +191,60 @@ namespace Alepha::inline Cavorite ::detail:: console
|
||||
[[nodiscard]] SGR_String setBgTrueColor( int rgb );
|
||||
[[nodiscard]] SGR_String setBgTrueColor( int r, int g, int b );
|
||||
|
||||
[[nodiscard]] SGR_String setUlTrueColor( int rgb );
|
||||
[[nodiscard]] SGR_String setUlTrueColor( int r, int g, int b );
|
||||
|
||||
void sendSGR( std::ostream &os, SGR_String );
|
||||
|
||||
int getConsoleWidth();
|
||||
}
|
||||
|
||||
enum class exports::BasicTextColor : int
|
||||
{
|
||||
black= 0,
|
||||
red= 1,
|
||||
green= 2,
|
||||
brown= 3,
|
||||
blue= 4,
|
||||
magenta= 5,
|
||||
cyan= 6,
|
||||
grey= 7,
|
||||
};
|
||||
|
||||
enum class exports::TextColor : int
|
||||
{
|
||||
black= 0,
|
||||
dim_red= 1,
|
||||
dim_green= 2,
|
||||
dim_brown= 3,
|
||||
dim_blue= 4,
|
||||
dim_magenta= 5,
|
||||
dim_cyan= 6,
|
||||
bright_grey= 7,
|
||||
|
||||
// Note that bright and dim grey are reverse, since bright grey is dim white and dim grey si bright black.
|
||||
// The names are more understandable this way, I think
|
||||
|
||||
dim_grey= 8,
|
||||
bright_red= 9,
|
||||
bright_green= 10,
|
||||
bright_brown= 11,
|
||||
bright_blue= 12,
|
||||
bright_magenta= 13,
|
||||
bright_cyan= 14,
|
||||
white= 15,
|
||||
|
||||
rgb_base= 16,
|
||||
red_radix= 36,
|
||||
green_radix= 6,
|
||||
blue_radix= 0,
|
||||
|
||||
greyscale_base= 232, // Add N to this to get the greyscale offset.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Alepha::Cavorite::inline exports::inline console
|
||||
namespace Alepha::Hydrogen::inline exports::inline console
|
||||
{
|
||||
using namespace detail::console::exports;
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ static_assert( __cplusplus > 2020'00 );
|
||||
#include <Alepha/Utility/evaluation_helpers.h>
|
||||
|
||||
#include <Alepha/TotalOrder.h>
|
||||
#include <Alepha/console.h>
|
||||
#include <Alepha/Console.h>
|
||||
|
||||
#include "colors.h"
|
||||
|
||||
namespace Alepha::Hydrogen::Testing ::detail:: table_test
|
||||
{
|
||||
@ -41,6 +43,14 @@ namespace Alepha::Hydrogen::Testing ::detail:: table_test
|
||||
enum class OutputMode { All, Relaxed };
|
||||
}
|
||||
|
||||
namespace C
|
||||
{
|
||||
inline namespace Colors
|
||||
{
|
||||
using namespace testing_colors::C::Colors;
|
||||
}
|
||||
}
|
||||
|
||||
template< typename F >
|
||||
concept FunctionVariable=
|
||||
requires( const F &f )
|
||||
@ -60,7 +70,6 @@ namespace Alepha::Hydrogen::Testing ::detail:: table_test
|
||||
{
|
||||
const bool debug= false;
|
||||
const bool debugCaseTypes= false or C::debug;
|
||||
using namespace Alepha::console::C;
|
||||
}
|
||||
|
||||
using std::begin, std::end;
|
||||
@ -260,11 +269,11 @@ namespace Alepha::Hydrogen::Testing ::detail:: table_test
|
||||
const auto result= witness == expected;
|
||||
if( not result )
|
||||
{
|
||||
std::cout << C::red << " FAILURE" << C::normal << ": " << comment << std::endl;
|
||||
std::cout << C::testFail << " FAILURE" << resetStyle << ": " << comment << std::endl;
|
||||
++failureCount;
|
||||
printDebugging< outputMode >( witness, expected );
|
||||
}
|
||||
else std::cout << C::green << " SUCCESS" << C::normal << ": " << comment << std::endl;
|
||||
else std::cout << C::testPass << " SUCCESS" << resetStyle << ": " << comment << std::endl;
|
||||
}
|
||||
|
||||
return failureCount;
|
||||
|
17
Testing/colors.h
Normal file
17
Testing/colors.h
Normal file
@ -0,0 +1,17 @@
|
||||
static_assert( __cplusplus > 2020'00 );
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Alepha/Console.h>
|
||||
|
||||
namespace Alepha::Hydrogen::Testing ::detail:: testing_colors
|
||||
{
|
||||
namespace C
|
||||
{
|
||||
inline namespace Colors
|
||||
{
|
||||
inline const auto testFail= createStyle( "test-failure", setFgColor( BasicTextColor::red ) );
|
||||
inline const auto testPass= createStyle( "test-success", setFgColor( BasicTextColor::green ) );
|
||||
}
|
||||
}
|
||||
}
|
@ -13,12 +13,14 @@ static_assert( __cplusplus > 2020'00 );
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <Alepha/console.h>
|
||||
#include <Alepha/Console.h>
|
||||
#include <Alepha/types.h>
|
||||
|
||||
#include <Alepha/Utility/evaluation_helpers.h>
|
||||
#include <Alepha/Utility/StaticValue.h>
|
||||
|
||||
#include "colors.h"
|
||||
|
||||
namespace Alepha::Hydrogen::Testing
|
||||
{
|
||||
inline namespace exports { inline namespace testing {} }
|
||||
@ -33,7 +35,7 @@ namespace Alepha::Hydrogen::Testing
|
||||
const bool debugTestRegistration= false or C::debug;
|
||||
const bool debugTestRun= false or C::debug;
|
||||
|
||||
using namespace Alepha::Hydrogen::exports::C;
|
||||
using namespace testing_colors::C::Colors;
|
||||
}
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
@ -196,9 +198,9 @@ namespace Alepha::Hydrogen::Testing
|
||||
|
||||
if( explicitlyNamed( name ) or not disabled and selected( name ) )
|
||||
{
|
||||
std::cout << C::green << "BEGIN " << C::normal << ": " << name << std::endl;
|
||||
std::cout << C::testPass << "BEGIN " << resetStyle << ": " << name << std::endl;
|
||||
test();
|
||||
std::cout << C::green << "SUCCESS" << C::normal << ": " << name << std::endl;
|
||||
std::cout << C::testPass << "SUCCESS" << resetStyle << ": " << name << std::endl;
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
@ -206,7 +208,7 @@ namespace Alepha::Hydrogen::Testing
|
||||
try
|
||||
{
|
||||
failed= true;
|
||||
std::cout << C::red << "FAILURE" << C::normal << ": " << name;
|
||||
std::cout << C::testFail << "FAILURE" << resetStyle << ": " << name;
|
||||
throw;
|
||||
}
|
||||
catch( const TestFailureException &fail ) { std::cout << " -- " << fail.failureCount << " failures."; }
|
||||
|
91
console.h
91
console.h
@ -1,91 +0,0 @@
|
||||
static_assert( __cplusplus > 2020'00 );
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Alepha/Alepha.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Alepha::Hydrogen
|
||||
{
|
||||
inline namespace exports { inline namespace console {} }
|
||||
|
||||
namespace detail::console
|
||||
{
|
||||
inline namespace exports {}
|
||||
|
||||
namespace C
|
||||
{
|
||||
const std::string csi= "\e[";
|
||||
const std::string color_code= "m";
|
||||
|
||||
enum Layer
|
||||
{
|
||||
fg_code= '3',
|
||||
bg_code= '4',
|
||||
};
|
||||
|
||||
enum class Color : char
|
||||
{
|
||||
black= '0',
|
||||
red= '1',
|
||||
green= '2',
|
||||
brown= '3',
|
||||
blue= '4',
|
||||
magenta= '5',
|
||||
cyan= '6',
|
||||
white= '7',
|
||||
};
|
||||
}
|
||||
using C::Layer;
|
||||
using C::Color;
|
||||
|
||||
inline std::string
|
||||
make_color( const Layer layer, const Color color )
|
||||
{
|
||||
return C::csi + char(layer) + char(color) + C::color_code;
|
||||
}
|
||||
|
||||
namespace C
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
const std::string normal= C::csi + '0' + color_code;
|
||||
|
||||
inline namespace fg
|
||||
{
|
||||
const std::string black= make_color( C::fg_code, C::Color::black );
|
||||
const std::string red= make_color( C::fg_code, C::Color::red );
|
||||
const std::string green= make_color( C::fg_code, C::Color::green );
|
||||
const std::string brown= make_color( C::fg_code, C::Color::brown );
|
||||
const std::string blue= make_color( C::fg_code, C::Color::blue );
|
||||
const std::string magenta= make_color( C::fg_code, C::Color::magenta );
|
||||
const std::string cyan= make_color( C::fg_code, C::Color::cyan );
|
||||
const std::string white= make_color( C::fg_code, C::Color::white );
|
||||
}
|
||||
|
||||
namespace bg
|
||||
{
|
||||
const std::string black= make_color( C::bg_code, C::Color::black );
|
||||
const std::string red= make_color( C::bg_code, C::Color::red );
|
||||
const std::string green= make_color( C::bg_code, C::Color::green );
|
||||
const std::string brown= make_color( C::bg_code, C::Color::brown );
|
||||
const std::string blue= make_color( C::bg_code, C::Color::blue );
|
||||
const std::string magenta= make_color( C::bg_code, C::Color::magenta );
|
||||
const std::string cyan= make_color( C::bg_code, C::Color::cyan );
|
||||
const std::string white= make_color( C::bg_code, C::Color::white );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace exports
|
||||
{
|
||||
namespace C= detail::console::C;
|
||||
}
|
||||
}
|
||||
|
||||
namespace exports::console
|
||||
{
|
||||
using namespace detail::console::exports;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user