1
0
forked from Alepha/Alepha

A console driver from my ISO scratch work.

This commit is contained in:
2023-10-09 20:36:44 -04:00
parent 3610746a63
commit ed3d64e1df
2 changed files with 568 additions and 0 deletions

169
Console.h Normal file
View File

@ -0,0 +1,169 @@
static_assert( __cplusplus > 2020'00 );
#pragma once
// These are some terminal/console control primitives.
// There are several "modern" terminal assumptions built
// into this library.
//
// As long as this works on most (all?) modern terminal emulators, this should be
// fine.
namespace Alepha::inline Cavorite ::detail:: console
{
inline namespace exports {}
namespace exports
{
struct ScreenSize;
struct CursorPosition;
class Console;
Console &console() noexcept;
struct SGR_String
{
std::string code;
};
inline auto
operator ""_sgr( const char *const p, const std::size_t sz )
{
return SGR_String{ { p, p + sz } };
}
enum class BasicTextColor : int;
enum class TextColor : int;
struct Style
{
std::string name;
TotalOrder operator <=> ( const Style & ) const= default;
};
std::ostream &operator << ( std::ostream &, const Style & );
Style createStyle( const std::string &name, const SGR_String &style );
bool styleVarSet( const std::string &name );
enum ResetStyle { resetStyle };
std::ostream &operator << ( std::ostream &, ResetStyle );
// TODO: Move this to its own library.
const std::string &applicationName();
void setApplication( std::string name );
}
struct exports::ScreenSize
{
int rows;
int columns;
};
struct exports::CursorPosition
{
int x;
int y;
};
class exports::Console
{
private:
class Impl;
std::unique_ptr< Impl > impl;
Impl &pimpl() noexcept { return *impl; }
const Impl &pimpl() const noexcept { return *impl; }
std::ostream &csi();
public:
// A console object can only be constructed on a raw UNIX file descriptor.
explicit Console( int fd );
enum Mode;
Mode getMode() const;
int getScreenWidth();
int getScreenHeight();
// Althought this could be implemented by combining the above observers,
// there are more efficient ways to implement this, thus we actually
// keep them separate.
ScreenSize getScreenSize();
void hideCursor();
void showCursor();
// Pushes the current mode (raw or normal) onto the stack.
void setRaw();
// A nonblock mode is used to prevent terminal IO from blocking. This helps with keypress driven
// programs. This is its own raw mode.
void setNoblock();
// The Console object maintains an internal stack of the last terminal modes it set and how to
// revert tothe previous. There is no arbitrary limit on this stack size. Calling this with
// no previous modes is a no-op.
void popTermMode();
// Line kill functions keep the cursor where it is, but erase the specified text on the line.
void killLine();
void killLineHead();
void killLineTail();
// One should avoid calling these, as some internals may also use these hardware functions.
// It is better to use `gotoXY` and `getXY` to save/restore cursor positions. One should
// maintain a software stack (as a caller) of cursor positions, if necessary.
void saveHardwareCursor();
void restoreHardwareCursor();
void gotoX( int x );
void gotoY( int y );
void gotoXY( int x, int y );
int getX();
int getY();
CursorPosition getXY();
void cursorUp( unsigned amt= 0 );
void cursorDown( unsigned amt= 0 );
void cursorLeft( unsigned amt= 0 );
void cursorRight( unsigned amt= 0 );
void clearScreen(); // `console` library does direct cursor control, so this won't return the cursor to 1,1.
};
namespace exports
{
[[nodiscard]] SGR_String resetTextEffects();
[[nodiscard]] SGR_String setBlink();
[[nodiscard]] SGR_String setFGColor( BasicTextColor fg );
[[nodiscard]] SGR_String setBGColor( BasicTextColor bg );
[[nodiscard]] SGR_String setColor( BasicTextColor fg, BasicTextColor bg );
[[nodiscard]] SGR_String setExtFGColor( TextColor fg );
[[nodiscard]] SGR_String setExtBGColor( TextColor fg );
[[nodiscard]] SGR_String setExtColor( TextColor fg, TextColor bg );
// Basic color wrapping aliases:
[[nodiscard]] inline SGR_String setExtFgColor( const BasicTextColor fg ) { return setExtFgColor( static_cast< TextColor >( fg ) ); }
[[nodiscard]] inline SGR_String setExtBgColor( const BasicTextColor bg ) { return setExtBgColor( static_cast< TextColor >( bg ) ); }
[[nodiscard]] inline SGR_String setExtColor( const TextColor fg, const BasicTextColor bg ) { return setExtColor( ( fg ), static_cast< TextColor >( bg ) ); }
[[nodiscard]] inline SGR_String setExtColor( const BasicTextColor fg, const TextColor bg ) { return setExtColor( static_cast< TextColor >( fg ), ( bg ) ); }
[[nodiscard]] inline SGR_String setExtColor( const BasicTextColor fg, const BasicTextColor bg ) { return setExtColor( static_cast< TextColor >( fg ), static_cast< TextColor >( bg ) ); }
[[nodiscard]] SGR_String setFgTrueColor( int rgb );
[[nodiscard]] SGR_String setFgTrueColor( int r, int g, int b )
[[nodiscard]] SGR_String setBgTrueColor( int rgb );
[[nodiscard]] SGR_String setBgTrueColor( int r, int g, int b )
void sendSGR( std::ostream &os, SGR_String );
}
}