cpp-terminal 1.0.0
Small C++ library for writing multiplatform terminal applications
Loading...
Searching...
No Matches
Term Namespace Reference

Namespaces

namespace  Private
 
namespace  Version
 

Classes

class  Argc
 
class  Arguments
 
class  Buffer
 
class  Button
 
class  Color
 
class  Columns
 
class  Cursor
 
class  Event
 
class  Exception
 
class  Focus
 Class to return the focus of the terminal. More...
 
class  IOStreamInitializer
 
class  Key
 
class  MetaKey
 
class  Model
 
class  Mouse
 
class  Options
 
class  Rows
 
class  Screen
 
class  Size
 
class  Terminal
 
class  TerminalInitializer
 
class  Terminfo
 
class  TIstream
 
class  TOstream
 
class  Window
 Represents a rectangular window, as a 2D array of characters and their attributes. More...
 

Enumerations

enum class  Option : std::int16_t {
  Raw = 1 , Cooked = -1 , ClearScreen = 2 , NoClearScreen = -2 ,
  SignalKeys = 3 , NoSignalKeys = -3 , Cursor = 4 , NoCursor = -4
}
 Option to set-up the terminal. More...
 
enum class  Result {
  Yes , No , Error , None ,
  Abort , Invalid
}
 
enum class  Result_simple { Yes , No , Abort }
 
enum class  Style : std::uint8_t {
  Reset = 0 , Bold = 1 , Dim = 2 , Italic = 3 ,
  Underline = 4 , Blink = 5 , BlinkRapid = 6 , Reversed = 7 ,
  Conceal = 8 , Crossed = 9 , Font0 = 10 , ResetFont = 10 ,
  Font1 = 11 , Font2 = 12 , Font3 = 13 , Font4 = 14 ,
  Font5 = 15 , Font6 = 16 , Font7 = 17 , Font8 = 18 ,
  Font9 = 19 , Font10 = 20 , DoublyUnderlinedOrNotBold = 21 , ResetBold = 22 ,
  ResetDim = 22 , ResetItalic = 23 , ResetUnderline = 24 , ResetBlink = 25 ,
  ResetBlinkRapid = 25 , ResetReversed = 27 , ResetConceal = 28 , ResetCrossed = 29 ,
  DefaultForegroundColor = 39 , DefaultBackgroundColor = 49 , Frame = 51 , Encircle = 52 ,
  Overline = 53 , ResetFrame = 54 , ResetEncircle = 54 , ResetOverline = 55 ,
  DefaultUnderlineColor = 59 , BarRight = 60 , DoubleBarRight = 61 , BarLeft = 62 ,
  DoubleBarLeft = 63 , StressMarking = 64 , ResetBar = 65 , Superscript = 73 ,
  Subscript = 74 , ResetSuperscript = 75 , ResetSubscript = 75
}
 

Functions

std::string color_bg (const Term::Color::Name &name)
 
std::string color_bg (const std::uint8_t &value)
 
std::string color_bg (const std::uint8_t &red, const std::uint8_t &green, const std::uint8_t &blue)
 
std::string color_bg (const Color &color)
 
std::string color_fg (const Term::Color::Name &name)
 
std::string color_fg (const std::uint8_t &value)
 
std::string color_fg (const std::uint8_t &red, const std::uint8_t &green, const std::uint8_t &blue)
 
std::string color_fg (const Color &color)
 
Term::Cursor cursor_position ()
 
std::string cursor_move (const std::size_t &row, const std::size_t &column)
 
std::string cursor_up (const std::size_t &rows)
 
std::string cursor_down (const std::size_t &rows)
 
std::string cursor_left (const std::size_t &columns)
 
std::string cursor_right (const std::size_t &columns)
 
std::string cursor_position_report ()
 
std::string cursor_off ()
 
std::string cursor_on ()
 
std::string clear_eol ()
 
Term::Event read_event ()
 
constexpr bool operator== (Key l, MetaKey r)
 
constexpr bool operator== (MetaKey l, Key r)
 
constexpr bool operator< (MetaKey l, Key r)
 
constexpr bool operator< (Key l, MetaKey r)
 
constexpr bool operator!= (Key l, MetaKey r)
 
constexpr bool operator!= (MetaKey l, Key r)
 
constexpr bool operator>= (MetaKey l, Key r)
 
constexpr bool operator>= (Key l, MetaKey r)
 
constexpr bool operator> (MetaKey l, Key r)
 
constexpr bool operator> (Key l, MetaKey r)
 
constexpr bool operator<= (MetaKey l, Key r)
 
constexpr bool operator<= (Key l, MetaKey r)
 
constexpr Key operator+ (MetaKey metakey, Key key)
 
constexpr Key operator+ (Key key, MetaKey meta)
 
constexpr Key operator+ (MetaKey::Value l, Key r)
 
constexpr Key operator+ (Key l, MetaKey::Value r)
 
constexpr Key operator+ (MetaKey::Value l, Key::value_type r)
 
constexpr Key operator+ (Key::value_type l, MetaKey::Value r)
 
std::uint16_t returnCode () noexcept
 
Result prompt (const std::string &message, const std::string &first_option, const std::string &second_option, const std::string &prompt_indicator, bool)
 A simple yes/no prompt, requires the user to press the ENTER key to continue.
 
Result_simple prompt_simple (const std::string &message)
 The most simple prompt possible, requires the user to press enter to continue.
 
std::string concat (const std::vector< std::string > &)
 
std::vector< std::string > split (const std::string &)
 
void print_left_curly_bracket (Term::Window &, const std::size_t &, const std::size_t &, const std::size_t &)
 
void render (Term::Window &, const Model &, const std::size_t &)
 
std::string prompt_multiline (const std::string &, std::vector< std::string > &, std::function< bool(std::string)> &)
 
std::string clear_screen ()
 
std::string screen_save ()
 
std::string screen_load ()
 
Screen screen_size ()
 
std::string style (const Term::Style &style)
 
template<class Stream >
Stream & operator<< (Stream &stream, const Term::Style &style_type)
 
Term::TOstreamoperator<< (Term::TOstream &term, const Term::Style &style_type)
 
std::string terminal_title (const std::string &title)
 
std::string clear_buffer ()
 
bool is_stdin_a_tty ()
 Check if stdin is a tty.
 
bool is_stdout_a_tty ()
 Check if stdout is a tty.
 
bool is_stderr_a_tty ()
 Check if stderr is a tty.
 
std::string homepage () noexcept
 Homepage of cpp-terminal.
 

Variables

TIstreamcin = reinterpret_cast<Term::TIstream&>(cin_buffer)
 
TOstreamcout = reinterpret_cast<Term::TOstream&>(cout_buffer)
 
TOstreamcerr = reinterpret_cast<Term::TOstream&>(cerr_buffer)
 
TOstreamclog = reinterpret_cast<Term::TOstream&>(clog_buffer)
 
Term::Terminalterminal = reinterpret_cast<Term::Terminal&>(::terminal_buffer)
 

Enumeration Type Documentation

◆ Option

enum class Term::Option : std::int16_t
strong

Option to set-up the terminal.

Enumerator
Raw 

Set terminal in raw mode.

Cooked 

Set terminal in cooked mode.

ClearScreen 

Clear the screen (and restore its states when the program stops).

NoClearScreen 

Doesn't clear the screen.

SignalKeys 

Enable the signal keys (Ctrl+C, etc...), if activated these keys will have their default OS behaviour.

NoSignalKeys 

Disable the signal keys (Ctrl+C, etc...) will not be processed by the OS and will appears has standard combination keys.

Cursor 

Show the cursor.

NoCursor 

Hide the cursor (and restore its states when the program stops).

Definition at line 22 of file options.hpp.

23{
24 Raw = 1,
25 Cooked = -1,
26 ClearScreen = 2,
27 NoClearScreen = -2,
28 SignalKeys = 3,
29 NoSignalKeys = -3,
30 Cursor = 4,
31 NoCursor = -4
32};
@ NoClearScreen
Doesn't clear the screen.
@ ClearScreen
Clear the screen (and restore its states when the program stops).
@ Cooked
Set terminal in cooked mode.
@ Raw
Set terminal in raw mode.
@ NoSignalKeys
Disable the signal keys (Ctrl+C, etc...) will not be processed by the OS and will appears has standar...
@ NoCursor
Hide the cursor (and restore its states when the program stops).
@ SignalKeys
Enable the signal keys (Ctrl+C, etc...), if activated these keys will have their default OS behaviour...

◆ Result

enum class Term::Result
strong
Enumerator
Yes 

Returned if the user chose yes.

No 

Returned if the user chose no.

Error 

Returned if no terminal is attached to the program.

None 

Returned if the enter key was pressed without additional input.

Abort 

Returned if CTRL+C was pressed.

Invalid 

Returned if the given input did not match the case yes of no.

Definition at line 21 of file prompt.hpp.

22{
23 Yes,
24 No,
25 Error,
26 None,
27 Abort,
28 Invalid
29};
@ Invalid
Returned if the given input did not match the case yes of no.
@ None
Returned if the enter key was pressed without additional input.
@ Abort
Returned if CTRL+C was pressed.
@ Error
Returned if no terminal is attached to the program.
@ Yes
Returned if the user chose yes.
@ No
Returned if the user chose no.

◆ Result_simple

enum class Term::Result_simple
strong
Enumerator
Yes 

Returned if the user chose yes.

No 

Returned if the user chose no or invalid / no input or if no terminal is attached.

Abort 

Returned if CTRL+C was pressed.

Definition at line 44 of file prompt.hpp.

45{
46
47 Yes,
48 No,
49 Abort
50};

◆ Style

enum class Term::Style : std::uint8_t
strong
Enumerator
Reset 

resets all attributes (styles and colors)

Bold 

Thick text font.

Dim 

lighter, slimmer text font

Italic 

slightly bend text font

Underline 

draws a line below the text

Blink 

Sets blinking to less than 150 times per minute.

BlinkRapid 

MS-DOS ANSI.SYS, 150+ per minute; not widely supported.

Reversed 

swap foreground and background colors

Conceal 

Note: not widely supported.

Crossed 

strikes through the text, mostly supported

Font0 

Primary or default font.

ResetFont 
Font1 
Font2 
Font3 
Font4 
Font5 
Font6 
Font7 
Font8 
Font9 
Font10 

Fraktur / Gothic font.

DoublyUnderlinedOrNotBold 
ResetBold 
ResetDim 
ResetItalic 
ResetUnderline 
ResetBlink 
ResetBlinkRapid 
ResetReversed 
ResetConceal 
ResetCrossed 
DefaultForegroundColor 
DefaultBackgroundColor 
Frame 
Encircle 
Overline 
ResetFrame 
ResetEncircle 
ResetOverline 
DefaultUnderlineColor 

non standard, implemented in Kitty, VTE, mintty, and iTerm2

BarRight 

draw a vertical bar on the right side of the character

DoubleBarRight 

draw a double vertical bar to the right

BarLeft 

draw a vertical bar on the left side of the character

DoubleBarLeft 

draw a double vertical bar to the left

StressMarking 

reset all bars left and right double and simple

ResetBar 
Superscript 
Subscript 
ResetSuperscript 
ResetSubscript 

Definition at line 23 of file style.hpp.

24{
25
26 Reset = 0,
27 Bold = 1,
28 Dim = 2,
29 Italic = 3,
30 Underline = 4,
31 Blink = 5,
32 BlinkRapid = 6,
33 Reversed = 7,
34 Conceal = 8,
35 Crossed = 9,
36
37 // different fonts
38 Font0 = 10,
39 ResetFont = 10,
40 Font1 = 11,
41 Font2 = 12,
42 Font3 = 13,
43 Font4 = 14,
44 Font5 = 15,
45 Font6 = 16,
46 Font7 = 17,
47 Font8 = 18,
48 Font9 = 19,
49 Font10 = 20,
50
51 // Double-underline per ECMA-48,[5] 8.3.117 but instead disables bold intensity on several terminals,
52 // including in the Linux kernel's console before version 4.17
54
55 // resets corresponding styles
56 ResetBold = 22,
57 ResetDim = 22,
58 ResetItalic = 23,
59 ResetUnderline = 24,
60 ResetBlink = 25,
61 ResetBlinkRapid = 25,
62 ResetReversed = 27,
63 ResetConceal = 28,
64 ResetCrossed = 29,
65
66 // sets the foreground and background color to the implementation defined colors
69
70 Frame = 51,
71 Encircle = 52,
72 Overline = 53, // draw a line over the text, barely supported
73 ResetFrame = 54,
74 ResetEncircle = 54,
75 ResetOverline = 55,
76
77 // sets the underline color to the implementation defined colors
79
80 BarRight = 60,
81 DoubleBarRight = 61,
82 BarLeft = 62,
83 DoubleBarLeft = 63,
84 StressMarking = 64,
85
86 ResetBar = 65, // resets 60 - 64 inclusive
87
88 Superscript = 73, // only implemented in mintty
89 Subscript = 74, // only implemented in mintty
90 ResetSuperscript = 75, // only implemented in mintty
92};
@ Reversed
swap foreground and background colors
@ Bold
Thick text font.
@ Italic
slightly bend text font
@ Crossed
strikes through the text, mostly supported
@ BarLeft
draw a vertical bar on the left side of the character
@ DefaultBackgroundColor
@ DefaultForegroundColor
@ BlinkRapid
MS-DOS ANSI.SYS, 150+ per minute; not widely supported.
@ Reset
resets all attributes (styles and colors)
@ DoubleBarRight
draw a double vertical bar to the right
@ Font10
Fraktur / Gothic font.
@ Underline
draws a line below the text
@ Dim
lighter, slimmer text font
@ Conceal
Note: not widely supported.
@ Font0
Primary or default font.
@ BarRight
draw a vertical bar on the right side of the character
@ DoubleBarLeft
draw a double vertical bar to the left
@ StressMarking
reset all bars left and right double and simple
@ Blink
Sets blinking to less than 150 times per minute.
@ DefaultUnderlineColor
non standard, implemented in Kitty, VTE, mintty, and iTerm2
@ DoublyUnderlinedOrNotBold

Function Documentation

◆ clear_buffer()

std::string Term::clear_buffer ( )

Definition at line 23 of file terminal.cpp.

23{ return "\u001b[3J"; }

◆ clear_eol()

std::string Term::clear_eol ( )

Definition at line 44 of file cursor.cpp.

44{ return "\u001b[K"; }

◆ clear_screen()

std::string Term::clear_screen ( )

Definition at line 20 of file screen.cpp.

20{ return "\u001b[2J"; }

◆ color_bg() [1/4]

std::string Term::color_bg ( const Color & color)

Definition at line 87 of file color.cpp.

88{
89 if(color.getType() == Term::Color::Type::Unset || color.getType() == Term::Color::Type::NoColor) return "";
91 {
94 case Term::Terminfo::ColorMode::Bit3: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to3bits()) + 40) + "m\u001b[K";
95 case Term::Terminfo::ColorMode::Bit4: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
97 if(color.getType() == Term::Color::Type::Bit4 || color.getType() == Term::Color::Type::Bit3) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
98 else
99 return "\u001b[48;5;" + std::to_string(color.to8bits()) + "m\u001b[K";
101 if(color.getType() == Term::Color::Type::Bit3 || color.getType() == Term::Color::Type::Bit4) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 40) + "m\u001b[K";
102 else if(color.getType() == Term::Color::Type::Bit8)
103 return "\u001b[48;5;" + std::to_string(color.to8bits()) + "m\u001b[K";
104 else
105 return "\u001b[48;2;" + std::to_string(color.to24bits()[0]) + ';' + std::to_string(color.to24bits()[1]) + ';' + std::to_string(color.to24bits()[2]) + "m\u001b[K";
106 default: return {};
107 }
108}
Name to4bits() const
Definition color.cpp:48
std::uint8_t to8bits() const
Definition color.cpp:64
std::array< std::uint8_t, 3 > to24bits() const
Definition color.cpp:77
Type getType() const
Definition color.cpp:37
Name to3bits() const
Definition color.cpp:39
static ColorMode getColorMode()
Definition terminfo.cpp:136

◆ color_bg() [2/4]

std::string Term::color_bg ( const std::uint8_t & red,
const std::uint8_t & green,
const std::uint8_t & blue )

Definition at line 83 of file color.cpp.

83{ return color_bg(Color(r, g, b)); }
std::string color_bg(const Term::Color::Name &name)
Definition color.cpp:79

◆ color_bg() [3/4]

std::string Term::color_bg ( const std::uint8_t & value)

Definition at line 81 of file color.cpp.

81{ return color_bg(Color(color)); }

◆ color_bg() [4/4]

std::string Term::color_bg ( const Term::Color::Name & name)

Definition at line 79 of file color.cpp.

79{ return color_bg(Color(color)); }

◆ color_fg() [1/4]

std::string Term::color_fg ( const Color & color)

Definition at line 116 of file color.cpp.

117{
118 if(color.getType() == Term::Color::Type::Unset || color.getType() == Term::Color::Type::NoColor) { return {}; }
120 {
123 case Term::Terminfo::ColorMode::Bit3: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to3bits()) + 30) + "m";
124 case Term::Terminfo::ColorMode::Bit4: return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
126 if(color.getType() == Term::Color::Type::Bit4 || color.getType() == Term::Color::Type::Bit3) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
127 else
128 return "\u001b[38;5;" + std::to_string(color.to8bits()) + "m";
130 if(color.getType() == Term::Color::Type::Bit3 || color.getType() == Term::Color::Type::Bit4) return "\u001b[" + std::to_string(static_cast<uint8_t>(color.to4bits()) + 30) + "m";
131 else if(color.getType() == Term::Color::Type::Bit8)
132 return "\u001b[38;5;" + std::to_string(color.to8bits()) + "m";
133 else
134 return "\u001b[38;2;" + std::to_string(color.to24bits()[0]) + ';' + std::to_string(color.to24bits()[1]) + ';' + std::to_string(color.to24bits()[2]) + "m";
135 default: return {};
136 }
137}

◆ color_fg() [2/4]

std::string Term::color_fg ( const std::uint8_t & red,
const std::uint8_t & green,
const std::uint8_t & blue )

Definition at line 114 of file color.cpp.

114{ return color_fg(Color(red, green, blue)); }
std::string color_fg(const Term::Color::Name &name)
Definition color.cpp:110

◆ color_fg() [3/4]

std::string Term::color_fg ( const std::uint8_t & value)

Definition at line 112 of file color.cpp.

112{ return color_fg(Color(value)); }

◆ color_fg() [4/4]

std::string Term::color_fg ( const Term::Color::Name & name)

Definition at line 110 of file color.cpp.

110{ return color_fg(Color(name)); }

◆ concat()

std::string Term::concat ( const std::vector< std::string > & lines)

Definition at line 143 of file prompt.cpp.

144{
145 std::string s;
146 for(auto& line: lines) { s.append(line + "\n"); }
147 return s;
148}

◆ cursor_down()

std::string Term::cursor_down ( const std::size_t & rows)

Definition at line 36 of file cursor.cpp.

36{ return "\u001b[" + std::to_string(rows) + 'B'; }

◆ cursor_left()

std::string Term::cursor_left ( const std::size_t & columns)

Definition at line 40 of file cursor.cpp.

40{ return "\u001b[" + std::to_string(columns) + 'D'; }

◆ cursor_move()

std::string Term::cursor_move ( const std::size_t & row,
const std::size_t & column )

Definition at line 32 of file cursor.cpp.

32{ return "\u001b[" + std::to_string(row) + ';' + std::to_string(column) + 'H'; }

◆ cursor_off()

std::string Term::cursor_off ( )

Definition at line 28 of file cursor.cpp.

28{ return "\u001b[?25l"; }

◆ cursor_on()

std::string Term::cursor_on ( )

Definition at line 30 of file cursor.cpp.

30{ return "\u001b[?25h"; }

◆ cursor_position()

Term::Cursor Term::cursor_position ( )

Definition at line 26 of file cursor.cpp.

27{
28 static const Term::Private::FileInitializer files_init;
29 if(Term::Private::in.null()) { return {}; }
30#if defined(_WIN32)
31 CONSOLE_SCREEN_BUFFER_INFO inf;
32 if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Cursor(static_cast<std::size_t>(inf.dwCursorPosition.Y + 1), static_cast<std::size_t>(inf.dwCursorPosition.X + 1));
33 else
34 return Term::Cursor(0, 0);
35#else
36 std::string ret;
37 std::size_t nread{0};
39 // Hack to be sure we can do this all the time "Cooked" or "Raw" mode
40 ::termios actual;
41 if(!Private::out.null())
42 {
43 if(tcgetattr(Private::out.fd(), &actual) == -1) { return {}; }
44 }
45 ::termios raw = actual;
46 // Put terminal in raw mode
47 raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
48 // This disables output post-processing, requiring explicit \r\n. We
49 // keep it enabled, so that in C++, one can still just use std::endl
50 // for EOL instead of "\r\n".
51 // raw.c_oflag &= ~(OPOST);
52 raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
53 raw.c_lflag &= ~ISIG;
54 raw.c_cc[VMIN] = 1;
55 raw.c_cc[VTIME] = 0;
56 if(!Private::out.null()) tcsetattr(Private::out.fd(), TCSAFLUSH, &raw);
58 while(nread == 0) { ::ioctl(Private::in.fd(), FIONREAD, &nread); }
59 ret = Term::Private::in.read();
60 tcsetattr(Private::out.fd(), TCSAFLUSH, &actual);
62 try
63 {
64 if(ret[0] == '\033' && ret[1] == '[' && ret[ret.size() - 1] == 'R')
65 {
66 std::size_t found = ret.find(';', 2);
67 if(found != std::string::npos) { return Cursor(std::stoi(ret.substr(2, found - 2)), std::stoi(ret.substr(found + 1, ret.size() - (found + 2)))); }
68 return {};
69 }
70 return {};
71 }
72 catch(...)
73 {
74 return {};
75 }
76#endif
77}
std::string read() const
Definition file.cpp:127
std::size_t write(const std::string &str) const
Definition file.cpp:101
InputFileHandler & in
Definition file.cpp:43
OutputFileHandler & out
Definition file.cpp:44
std::string cursor_position_report()
Definition cursor.cpp:42
@ Cursor
Show the cursor.

◆ cursor_position_report()

std::string Term::cursor_position_report ( )

Definition at line 42 of file cursor.cpp.

42{ return "\u001b[6n"; }

◆ cursor_right()

std::string Term::cursor_right ( const std::size_t & columns)

Definition at line 38 of file cursor.cpp.

38{ return "\u001b[" + std::to_string(columns) + 'C'; }

◆ cursor_up()

std::string Term::cursor_up ( const std::size_t & rows)

Definition at line 34 of file cursor.cpp.

34{ return "\u001b[" + std::to_string(rows) + 'A'; }

◆ homepage()

std::string Term::homepage ( )
noexcept

Homepage of cpp-terminal.

Returns
std::string return the URL of the cpp-terminal project.

◆ is_stderr_a_tty()

bool Term::is_stderr_a_tty ( )

Check if stderr is a tty.

Returns
true : stderr is a tty.
false : stderr is not a tty.

Definition at line 36 of file tty.cpp.

36{ return ::is_a_tty(stderr); }

◆ is_stdin_a_tty()

bool Term::is_stdin_a_tty ( )

Check if stdin is a tty.

Returns
true : stdin is a tty.
false : stdin is not a tty.

Definition at line 32 of file tty.cpp.

32{ return ::is_a_tty(stdin); }

◆ is_stdout_a_tty()

bool Term::is_stdout_a_tty ( )

Check if stdout is a tty.

Returns
true : stdout is a tty.
false : stdout is not a tty.

Definition at line 34 of file tty.cpp.

34{ return ::is_a_tty(stdout); }

◆ operator!=() [1/2]

bool Term::operator!= ( Key l,
MetaKey r )
constexpr

Definition at line 430 of file key.hpp.

430{ return static_cast<std::int32_t>(l) != static_cast<std::int32_t>(r); }

◆ operator!=() [2/2]

bool Term::operator!= ( MetaKey l,
Key r )
constexpr

Definition at line 431 of file key.hpp.

431{ return static_cast<std::int32_t>(l) != static_cast<std::int32_t>(r); }

◆ operator+() [1/6]

Key Term::operator+ ( Key key,
MetaKey meta )
constexpr

Definition at line 443 of file key.hpp.

443{ return meta + key; }

◆ operator+() [2/6]

Key Term::operator+ ( Key l,
MetaKey::Value r )
constexpr

Definition at line 446 of file key.hpp.

446{ return l + MetaKey(r); }

◆ operator+() [3/6]

Key Term::operator+ ( Key::value_type l,
MetaKey::Value r )
constexpr

Definition at line 448 of file key.hpp.

448{ return Key(l) + MetaKey(r); }

◆ operator+() [4/6]

Key Term::operator+ ( MetaKey metakey,
Key key )
constexpr

Definition at line 442 of file key.hpp.

442{ return Key(key.value + ((metakey == MetaKey::Value::Ctrl && !key.hasCtrlAll() && !key.empty()) ? static_cast<std::int32_t>(MetaKey::Value::Ctrl) : 0) + ((metakey == MetaKey::Value::Alt && !key.hasAlt() && !key.empty()) ? static_cast<std::int32_t>(MetaKey::Value::Alt) : 0)); }
constexpr bool empty() const
Definition key.hpp:412
constexpr bool hasCtrlAll() const
Definition key.hpp:400
std::int32_t value
Definition key.hpp:421

◆ operator+() [5/6]

Key Term::operator+ ( MetaKey::Value l,
Key r )
constexpr

Definition at line 445 of file key.hpp.

445{ return MetaKey(l) + r; }

◆ operator+() [6/6]

Key Term::operator+ ( MetaKey::Value l,
Key::value_type r )
constexpr

Definition at line 447 of file key.hpp.

447{ return MetaKey(l) + Key(r); }

◆ operator<() [1/2]

bool Term::operator< ( Key l,
MetaKey r )
constexpr

Definition at line 428 of file key.hpp.

428{ return static_cast<std::int32_t>(l) < static_cast<std::int32_t>(r); }

◆ operator<() [2/2]

bool Term::operator< ( MetaKey l,
Key r )
constexpr

Definition at line 427 of file key.hpp.

427{ return static_cast<std::int32_t>(l) < static_cast<std::int32_t>(r); }

◆ operator<<() [1/2]

template<class Stream >
Stream & Term::operator<< ( Stream & stream,
const Term::Style & style_type )

Definition at line 96 of file style.hpp.

96{ return stream << style(style_type); }
std::string style(const Term::Style &style)
Definition style.cpp:12

◆ operator<<() [2/2]

Term::TOstream & Term::operator<< ( Term::TOstream & term,
const Term::Style & style_type )
inline

Definition at line 98 of file style.hpp.

98{ return term << style(style_type); }

◆ operator<=() [1/2]

bool Term::operator<= ( Key l,
MetaKey r )
constexpr

Definition at line 440 of file key.hpp.

440{ return static_cast<std::int32_t>(l) <= static_cast<std::int32_t>(r); }

◆ operator<=() [2/2]

bool Term::operator<= ( MetaKey l,
Key r )
constexpr

Definition at line 439 of file key.hpp.

439{ return static_cast<std::int32_t>(l) <= static_cast<std::int32_t>(r); }

◆ operator==() [1/2]

bool Term::operator== ( Key l,
MetaKey r )
constexpr

Definition at line 424 of file key.hpp.

424{ return static_cast<std::int32_t>(l) == static_cast<std::int32_t>(r); }

◆ operator==() [2/2]

bool Term::operator== ( MetaKey l,
Key r )
constexpr

Definition at line 425 of file key.hpp.

425{ return static_cast<std::int32_t>(l) == static_cast<std::int32_t>(r); }

◆ operator>() [1/2]

bool Term::operator> ( Key l,
MetaKey r )
constexpr

Definition at line 437 of file key.hpp.

437{ return static_cast<std::int32_t>(l) > static_cast<std::int32_t>(r); }

◆ operator>() [2/2]

bool Term::operator> ( MetaKey l,
Key r )
constexpr

Definition at line 436 of file key.hpp.

436{ return static_cast<std::int32_t>(l) > static_cast<std::int32_t>(r); }

◆ operator>=() [1/2]

bool Term::operator>= ( Key l,
MetaKey r )
constexpr

Definition at line 434 of file key.hpp.

434{ return static_cast<std::int32_t>(l) >= static_cast<std::int32_t>(r); }

◆ operator>=() [2/2]

bool Term::operator>= ( MetaKey l,
Key r )
constexpr

Definition at line 433 of file key.hpp.

433{ return static_cast<std::int32_t>(l) >= static_cast<std::int32_t>(r); }

◆ print_left_curly_bracket()

void Term::print_left_curly_bracket ( Term::Window & scr,
const std::size_t & x,
const std::size_t & y1,
const std::size_t & y2 )

Definition at line 175 of file prompt.cpp.

176{
177 std::size_t h{y2 - y1 + 1};
178 if(h == 1) { scr.set_char(x, y1, UU("]")); }
179 else
180 {
181 scr.set_char(x, y1, UU("┐"));
182 for(std::size_t j = y1 + 1; j <= y2 - 1; j++) { scr.set_char(x, j, UU("│")); }
183 scr.set_char(x, y2, UU("┘"));
184 }
185}
void set_char(const std::size_t &column, const std::size_t &row, const char32_t &character)
Definition window.cpp:46
char32_t UU(const std::string &s)
Definition prompt.cpp:168

◆ prompt()

Term::Result Term::prompt ( const std::string & message,
const std::string & first_option,
const std::string & second_option,
const std::string & prompt_indicator,
bool immediate )

A simple yes/no prompt, requires the user to press the ENTER key to continue.

The arguments are used like this: 1 [2/3]4 <user Input>. The immediate switch indicates toggles whether pressing enter for confirming the input is required or not.

Parameters
message
first_option
second_option
prompt_indicator
Returns
Result

Definition at line 26 of file prompt.cpp.

27{
28 Term::terminal.setOptions(Option::NoClearScreen, Option::NoSignalKeys, Option::Cursor, Term::Option::Raw);
29 std::cout << message << " [" << first_option << '/' << second_option << ']' << prompt_indicator << ' ' << std::flush;
30
32 {
33 std::cout << '\n' << std::flush;
34 return Result::Error;
35 }
36
37 Term::Key key;
38
39 if(immediate)
40 {
41 while(true)
42 {
43 key = Term::read_event();
44 if(key == Term::Key::NoKey) continue;
45 if(key == Term::Key::y || key == Term::Key::Y)
46 {
47 std::cout << '\n' << std::flush;
48 return Result::Yes;
49 }
50 else if(key == Term::Key::n || key == Term::Key::N)
51 {
52 std::cout << '\n' << std::flush;
53 return Result::No;
54 }
55 else if(key == Term::Key::Ctrl_C || key == Term::Key::Ctrl_D)
56 {
57 std::cout << '\n' << std::flush;
58 return Result::Abort;
59 }
60 else if(key == Term::Key::Enter)
61 {
62 std::cout << '\n' << std::flush;
63 return Result::None;
64 }
65 else
66 {
67 std::cout << '\n' << std::flush;
68 return Result::Invalid;
69 }
70 }
71 }
72 else
73 {
74 std::string input;
75 while(true)
76 {
77 key = Term::read_event();
78 if(key == Term::Key::NoKey) continue;
79 if(key >= 'a' && key <= 'z')
80 {
81 std::cout << (char)key << std::flush;
82 input.push_back(static_cast<char>(key));
83 }
84 else if(key >= 'A' && key <= 'Z')
85 {
86 std::cout << (char)key << std::flush;
87 input.push_back(static_cast<char>(key.tolower())); // convert upper case to lowercase
88 }
89 else if(key == Term::Key::Ctrl_C || key == Term::Key::Ctrl_D)
90 {
91 std::cout << '\n';
92 return Result::Abort;
93 }
94 else if(key == Term::Key::Backspace)
95 {
96 if(input.empty() != 0)
97 {
98 std::cout << "\u001b[D \u001b[D" << std::flush; // erase last line and move the cursor back
99 input.pop_back();
100 }
101 }
102 else if(key == Term::Key::Enter)
103 {
104 if(input == "y" || input == "yes")
105 {
106 std::cout << '\n' << std::flush;
107 return Result::Yes;
108 }
109 else if(input == "n" || input == "no")
110 {
111 std::cout << '\n' << std::flush;
112 return Result::No;
113 }
114 else if(input.empty())
115 {
116 std::cout << '\n' << std::flush;
117 return Result::None;
118 }
119 else
120 {
121 std::cout << '\n' << std::flush;
122 return Result::Invalid;
123 }
124 }
125 }
126 }
127}
@ Ctrl_D
Definition key.hpp:100
@ Enter
Definition key.hpp:231
@ Backspace
Definition key.hpp:229
@ NoKey
Definition key.hpp:92
@ Ctrl_C
Definition key.hpp:99
constexpr Key tolower() const
Definition key.hpp:390
void setOptions(const Args &&... args)
Term::Event read_event()
Definition input.cpp:338
Term::Terminal & terminal
Definition terminal.cpp:19
bool is_stdin_a_tty()
Check if stdin is a tty.
Definition tty.cpp:32

◆ prompt_multiline()

std::string Term::prompt_multiline ( const std::string & prompt_string,
std::vector< std::string > & m_history,
std::function< bool(std::string)> & iscomplete )

Definition at line 209 of file prompt.cpp.

210{
211 Term::Cursor cursor;
212 Term::Screen screen({Term::Rows(25), Term::Columns(80)});
213 bool term_attached = Term::is_stdin_a_tty();
214 if(is_stdin_a_tty())
215 {
216 cursor = cursor_position();
217 screen = screen_size();
218 }
219
220 Model model;
221 model.prompt_string = prompt_string;
222
223 // Make a local copy of history that can be modified by the user. All
224 // changes will be forgotten once a command is submitted.
225 std::vector<std::string> history = m_history;
226 std::size_t history_pos = history.size();
227 history.push_back(concat(model.lines)); // Push back empty input
228
229 Term::Window scr({Term::Columns(screen.columns()), Term::Rows(1)});
230 Term::Key key;
231 render(scr, model, screen.columns());
232 std::cout << scr.render(1, cursor.row(), term_attached) << std::flush;
233 bool not_complete = true;
234 while(not_complete)
235 {
236 key = Term::read_event();
237 if(key == Term::Key::NoKey) continue;
238 if(key.isprint())
239 {
240 std::string before = model.lines[model.cursor_row - 1].substr(0, model.cursor_col - 1);
241 std::string newchar;
242 newchar.push_back(static_cast<char>(key));
243 std::string after = model.lines[model.cursor_row - 1].substr(model.cursor_col - 1);
244 model.lines[model.cursor_row - 1] = before += newchar += after;
245 model.cursor_col++;
246 }
247 else if(key == Key::Ctrl_D)
248 {
249 if(model.lines.size() == 1 && model.lines[model.cursor_row - 1].empty())
250 {
251 model.lines[model.cursor_row - 1].push_back(static_cast<char>(Key::Ctrl_D));
252 std::cout << "\n" << std::flush;
253 m_history.push_back(model.lines[0]);
254 return model.lines[0];
255 }
256 }
257 else
258 {
259 switch(key)
260 {
261 case Key::Enter:
262 not_complete = !iscomplete(concat(model.lines));
263 if(not_complete) key = Key(static_cast<Term::Key>(Term::MetaKey::Value::Alt + Term::Key::Enter));
264 else
265 break;
267 case Key::Backspace:
268 if(model.cursor_col > 1)
269 {
270 std::string before = model.lines[model.cursor_row - 1].substr(0, model.cursor_col - 2);
271 std::string after = model.lines[model.cursor_row - 1].substr(model.cursor_col - 1);
272 model.lines[model.cursor_row - 1] = before + after;
273 model.cursor_col--;
274 }
275 else if(model.cursor_col == 1 && model.cursor_row > 1)
276 {
277 model.cursor_col = model.lines[model.cursor_row - 2].size() + 1;
278 model.lines[model.cursor_row - 2] += model.lines[model.cursor_row - 1];
279 model.lines.erase(model.lines.begin() + static_cast<long>(model.cursor_row) - 1);
280 model.cursor_row--;
281 }
282 break;
283 case Key::Del:
284 if(model.cursor_col <= model.lines[model.cursor_row - 1].size())
285 {
286 std::string before = model.lines[model.cursor_row - 1].substr(0, model.cursor_col - 1);
287 std::string after = model.lines[model.cursor_row - 1].substr(model.cursor_col);
288 model.lines[model.cursor_row - 1] = before + after;
289 }
290 break;
291 case Key::ArrowLeft:
292 if(model.cursor_col > 1) { model.cursor_col--; }
293 break;
294 case Key::ArrowRight:
295 if(model.cursor_col <= model.lines[model.cursor_row - 1].size()) { model.cursor_col++; }
296 break;
297 case Key::Home: model.cursor_col = 1; break;
298 case Key::End: model.cursor_col = model.lines[model.cursor_row - 1].size() + 1; break;
299 case Key::ArrowUp:
300 if(model.cursor_row == 1)
301 {
302 if(history_pos > 0)
303 {
304 history[history_pos] = concat(model.lines);
305 history_pos--;
306 model.lines = split(history[history_pos]);
307 model.cursor_row = model.lines.size();
308 if(model.cursor_col > model.lines[model.cursor_row - 1].size() + 1) { model.cursor_col = model.lines[model.cursor_row - 1].size() + 1; }
309 if(model.lines.size() > scr.columns()) { scr.set_h(model.lines.size()); }
310 }
311 }
312 else
313 {
314 model.cursor_row--;
315 if(model.cursor_col > model.lines[model.cursor_row - 1].size() + 1) { model.cursor_col = model.lines[model.cursor_row - 1].size() + 1; }
316 }
317 break;
318 case Key::ArrowDown:
319 if(model.cursor_row == model.lines.size())
320 {
321 if(history_pos < history.size() - 1)
322 {
323 history[history_pos] = concat(model.lines);
324 history_pos++;
325 model.lines = split(history[history_pos]);
326 model.cursor_row = 1;
327 if(model.cursor_col > model.lines[model.cursor_row - 1].size() + 1) { model.cursor_col = model.lines[model.cursor_row - 1].size() + 1; }
328 if(model.lines.size() > scr.columns()) { scr.set_h(model.lines.size()); }
329 }
330 }
331 else
332 {
333 model.cursor_row++;
334 if(model.cursor_col > model.lines[model.cursor_row - 1].size() + 1) { model.cursor_col = model.lines[model.cursor_row - 1].size() + 1; }
335 }
336 break;
337 case Key::Ctrl_N:
338 {
339 std::string before = model.lines[model.cursor_row - 1].substr(0, model.cursor_col - 1);
340 std::string after = model.lines[model.cursor_row - 1].substr(model.cursor_col - 1);
341 model.lines[model.cursor_row - 1] = before;
342 if(model.cursor_row < model.lines.size())
343 {
344 // Not at the bottom row, can't push back
345 model.lines.insert(model.lines.begin() + static_cast<long>(model.cursor_row), after);
346 }
347 else { model.lines.push_back(after); }
348 model.cursor_col = 1;
349 model.cursor_row++;
350 if(model.lines.size() > scr.columns()) { scr.set_h(model.lines.size()); }
351 break;
352 }
353 default: break;
354 }
355 }
356 render(scr, model, screen.columns());
357 std::cout << scr.render(1, cursor.row(), term_attached) << std::flush;
358 if(cursor.row() + scr.columns() - 1 > screen.rows())
359 {
360 cursor.setRow(static_cast<std::uint16_t>(screen.rows() - (scr.columns() - 1)));
361 std::cout << scr.render(1, cursor.row(), term_attached) << std::flush;
362 }
363 }
364 std::string line_skips;
365 for(std::size_t i = 0; i <= model.lines.size() - model.cursor_row; i++) { line_skips += "\n"; }
366 std::cout << line_skips << std::flush;
367 m_history.push_back(concat(model.lines));
368 return concat(model.lines);
369}
void setRow(const std::size_t &)
Definition cursor.cpp:20
std::size_t row() const
Definition cursor.cpp:14
Represents a rectangular window, as a 2D array of characters and their attributes.
Definition window.hpp:34
#define CPP_TERMINAL_FALLTHROUGH
Definition macros.hpp:40
std::vector< std::string > split(const std::string &)
Definition prompt.cpp:150
std::string concat(const std::vector< std::string > &)
Definition prompt.cpp:143
void render(Term::Window &, const Model &, const std::size_t &)
Definition prompt.cpp:187

◆ prompt_simple()

Term::Result_simple Term::prompt_simple ( const std::string & message)

The most simple prompt possible, requires the user to press enter to continue.

The arguments are used like this: 1 [y/N]: Invalid input, errors (like no attached terminal) all result in no as default.

Parameters
message
Returns
Result_simple

Definition at line 129 of file prompt.cpp.

130{
131 switch(prompt(message, "y", "N", ":", false))
132 {
133 case Result::Yes: return Result_simple::Yes;
134 case Result::Abort: return Result_simple::Abort;
135 case Result::No: // falls through
136 case Result::Error: // falls through
137 case Result::None: // falls through
138 case Result::Invalid:
139 default: return Result_simple::No;
140 }
141}
Result prompt(const std::string &message, const std::string &first_option, const std::string &second_option, const std::string &prompt_indicator, bool)
A simple yes/no prompt, requires the user to press the ENTER key to continue.
Definition prompt.cpp:26

◆ read_event()

Term::Event Term::read_event ( )

Definition at line 338 of file input.cpp.

339{
340 m_input.startReading();
341 return m_input.getEventBlocking();
342}
static Term::Event getEventBlocking()
Definition input.cpp:328
static void startReading()
Definition input.cpp:315

◆ render()

void Term::render ( Term::Window & scr,
const Model & model,
const std::size_t & cols )

Definition at line 187 of file prompt.cpp.

188{
189 scr.clear();
190 print_left_curly_bracket(scr, cols, 1, model.lines.size());
191 scr.print_str(cols - 6, model.lines.size(), std::to_string(model.cursor_row) + "," + std::to_string(model.cursor_col));
192 for(std::size_t j = 0; j < model.lines.size(); j++)
193 {
194 if(j == 0)
195 {
196 scr.fill_fg(1, j + 1, model.prompt_string.size(), model.lines.size(), Term::Color::Name::Green);
197 scr.fill_style(1, j + 1, model.prompt_string.size(), model.lines.size(), Term::Style::Bold);
198 scr.print_str(1, j + 1, model.prompt_string);
199 }
200 else
201 {
202 for(std::size_t i = 0; i < model.prompt_string.size() - 1; i++) { scr.set_char(i + 1, j + 1, '.'); }
203 }
204 scr.print_str(model.prompt_string.size() + 1, j + 1, model.lines[j]);
205 }
206 scr.set_cursor_pos(model.prompt_string.size() + model.cursor_col, model.cursor_row);
207}
@ Green
Green FG: 32, BG: 42.
std::vector< std::string > lines
Definition prompt.hpp:69
std::size_t cursor_row
Definition prompt.hpp:72
std::size_t cursor_col
Definition prompt.hpp:71
std::string prompt_string
Definition prompt.hpp:68
void print_str(const std::size_t &column, const std::size_t &, const std::string &, const std::size_t &=0, bool=false)
Definition window.cpp:97
void fill_style(const std::size_t &column, const std::size_t &, const std::size_t &, const std::size_t &, const Style &)
Definition window.cpp:140
void set_cursor_pos(const std::size_t &column, const std::size_t &row)
Definition window.cpp:78
void fill_fg(const std::size_t &column, const std::size_t &, const std::size_t &, const std::size_t &, const Color &)
Definition window.cpp:124
void clear()
Definition window.cpp:189
void print_left_curly_bracket(Term::Window &, const std::size_t &, const std::size_t &, const std::size_t &)
Definition prompt.cpp:175

◆ returnCode()

std::uint16_t Term::returnCode ( )
noexcept

Definition at line 18 of file return_code.cpp.

19{
20 static std::uint16_t code{EXIT_FAILURE};
21 const std::pair<bool, std::string> returnCode{Private::getenv("CPP_TERMINAL_BADSTATE")};
22 try
23 {
24 if(returnCode.first && (std::stoi(returnCode.second) != EXIT_SUCCESS)) { code = static_cast<std::uint16_t>(std::stoi(returnCode.second)); }
25 }
26 catch(...)
27 {
28 code = EXIT_FAILURE;
29 }
30 return code;
31}
std::uint16_t returnCode() noexcept

◆ screen_load()

std::string Term::screen_load ( )

Definition at line 27 of file screen.cpp.

28{
29 return "\u001b[?1049l\u001b8"; // restores screen, restore current cursor position FIXME
30}

◆ screen_save()

std::string Term::screen_save ( )

Definition at line 22 of file screen.cpp.

23{
24 return "\u001b7\u001b[?1049h"; // save current cursor position, save screen FIXME
25}

◆ screen_size()

Term::Screen Term::screen_size ( )

Definition at line 24 of file screen.cpp.

25{
26#ifdef _WIN32
27 CONSOLE_SCREEN_BUFFER_INFO inf;
28 if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Screen({Term::Rows(inf.srWindow.Bottom - inf.srWindow.Top + 1), Term::Columns(inf.srWindow.Right - inf.srWindow.Left + 1)});
29 return {};
30#else
31 struct winsize window{0, 0, 0, 0};
32 if(ioctl(Private::out.fd(), TIOCGWINSZ, &window) != -1) return Term::Screen({Term::Rows(window.ws_row), Term::Columns(window.ws_col)});
33 return {};
34#endif
35}

◆ split()

std::vector< std::string > Term::split ( const std::string & s)

Definition at line 150 of file prompt.cpp.

151{
152 std::size_t j = 0;
153 std::vector<std::string> lines;
154 lines.emplace_back("");
155 if(s[s.size() - 1] != '\n') throw Term::Exception("\\n is required");
156 for(std::size_t i = 0; i < s.size() - 1; i++)
157 {
158 if(s[i] == '\n')
159 {
160 j++;
161 lines.emplace_back("");
162 }
163 else { lines[j].push_back(s[i]); }
164 }
165 return lines;
166}

◆ style()

std::string Term::style ( const Term::Style & style)

Definition at line 12 of file style.cpp.

13{
14 //https://unix.stackexchange.com/questions/212933/background-color-whitespace-when-end-of-the-terminal-reached
15 std::string ret{"\u001b[" + std::to_string(static_cast<std::uint8_t>(style)) + 'm'};
16 if(style == Term::Style::DefaultBackgroundColor) { ret += "\u001b[K"; }
17 return ret;
18}

◆ terminal_title()

std::string Term::terminal_title ( const std::string & title)

Definition at line 21 of file terminal.cpp.

21{ return "\u001b]0;" + title + '\a'; }

Variable Documentation

◆ cerr

Term::TOstream & Term::cerr = reinterpret_cast<Term::TOstream&>(cerr_buffer)
extern

Definition at line 24 of file iostream.cpp.

◆ cin

Term::TIstream & Term::cin = reinterpret_cast<Term::TIstream&>(cin_buffer)
extern

Definition at line 25 of file iostream.cpp.

◆ clog

Term::TOstream & Term::clog = reinterpret_cast<Term::TOstream&>(clog_buffer)
extern

Definition at line 23 of file iostream.cpp.

◆ cout

Term::TOstream & Term::cout = reinterpret_cast<Term::TOstream&>(cout_buffer)
extern

Definition at line 22 of file iostream.cpp.

◆ terminal

Term::Terminal & Term::terminal = reinterpret_cast<Term::Terminal&>(::terminal_buffer)
extern

Definition at line 19 of file terminal.cpp.