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  Column
 
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  Position
 
class  Row
 
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 40 of file cursor.cpp.

40{ 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 144 of file prompt.cpp.

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

◆ cursor_down()

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

Definition at line 32 of file cursor.cpp.

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

◆ cursor_left()

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

Definition at line 36 of file cursor.cpp.

36{ 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 28 of file cursor.cpp.

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

◆ cursor_off()

std::string Term::cursor_off ( )

Definition at line 24 of file cursor.cpp.

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

◆ cursor_on()

std::string Term::cursor_on ( )

Definition at line 26 of file cursor.cpp.

26{ 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({Row(inf.dwCursorPosition.Y + 1), Column(inf.dwCursorPosition.X + 1)});
33 else
34 return {};
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({Row(std::stoi(ret.substr(2, found - 2))), Column(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:38
@ Cursor
Show the cursor.

◆ cursor_position_report()

std::string Term::cursor_position_report ( )

Definition at line 38 of file cursor.cpp.

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

◆ cursor_right()

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

Definition at line 34 of file cursor.cpp.

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

◆ cursor_up()

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

Definition at line 30 of file cursor.cpp.

30{ 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 176 of file prompt.cpp.

177{
178 std::size_t h{y2 - y1 + 1};
179 if(h == 1) { scr.set_char(x, y1, UU("]")); }
180 else
181 {
182 scr.set_char(x, y1, UU("┐"));
183 for(std::size_t j = y1 + 1; j <= y2 - 1; j++) { scr.set_char(x, j, UU("│")); }
184 scr.set_char(x, y2, UU("┘"));
185 }
186}
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:169

◆ 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 27 of file prompt.cpp.

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

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

◆ 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 130 of file prompt.cpp.

131{
132 switch(prompt(message, "y", "N", ":", false))
133 {
134 case Result::Yes: return Result_simple::Yes;
135 case Result::Abort: return Result_simple::Abort;
136 case Result::No: // falls through
137 case Result::Error: // falls through
138 case Result::None: // falls through
139 case Result::Invalid:
140 default: return Result_simple::No;
141 }
142}
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:27

◆ 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 188 of file prompt.cpp.

189{
190 scr.clear();
191 print_left_curly_bracket(scr, cols, 1, model.lines.size());
192 scr.print_str(cols - 6, model.lines.size(), std::to_string(model.cursor_row) + "," + std::to_string(model.cursor_col));
193 for(std::size_t j = 0; j < model.lines.size(); j++)
194 {
195 if(j == 0)
196 {
197 scr.fill_fg(1, j + 1, model.prompt_string.size(), model.lines.size(), Term::Color::Name::Green);
198 scr.fill_style(1, j + 1, model.prompt_string.size(), model.lines.size(), Term::Style::Bold);
199 scr.print_str(1, j + 1, model.prompt_string);
200 }
201 else
202 {
203 for(std::size_t i = 0; i < model.prompt_string.size() - 1; i++) { scr.set_char(i + 1, j + 1, '.'); }
204 }
205 scr.print_str(model.prompt_string.size() + 1, j + 1, model.lines[j]);
206 }
207 scr.set_cursor_pos(model.prompt_string.size() + model.cursor_col, model.cursor_row);
208}
@ 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:176

◆ 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 151 of file prompt.cpp.

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

◆ 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.