Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Splitting the rest #132

Merged
merged 16 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cpp-terminal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
configure_file(version.h.in version.h)

# create and confirgure library target
add_library(cpp-terminal terminal_base.cpp terminal.cpp base.cpp prompt.cpp window.cpp)
add_library(cpp-terminal base.cpp prompt.cpp window.cpp input.cpp private/platform.cpp)

target_include_directories(cpp-terminal BEFORE PUBLIC
${cpp-terminal_SOURCE_DIR}
Expand All @@ -11,5 +11,5 @@ target_include_directories(cpp-terminal BEFORE PUBLIC
target_include_directories(cpp-terminal INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})

set_target_properties(cpp-terminal PROPERTIES
PUBLIC_HEADER "cpp-terminal/terminal.h;cpp-terminal/terminal_base.h;cpp-terminal/version.h;cpp-terminal/base.hpp;cpp-terminal/prompt.hpp;cpp-terminal/window.hpp"
PUBLIC_HEADER "cpp-terminal/version.h;cpp-terminal/base.hpp;cpp-terminal/prompt.hpp;cpp-terminal/window.hpp;cpp-terminal/input.hpp"
)
92 changes: 91 additions & 1 deletion cpp-terminal/base.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <cpp-terminal/base.hpp>
#include <iostream>
#include <string>
#include "private/platform.hpp"
#include "private/conversion.hpp"


std::string Term::color(style value) {
Expand Down Expand Up @@ -65,4 +67,92 @@ std::string Term::cursor_position_report() {

std::string Term::erase_to_eol() {
return "\x1b[K";
}
}
bool Term::is_stdin_a_tty() {
return Private::is_stdin_a_tty();
}
bool Term::is_stdout_a_tty() {
return Private::is_stdout_a_tty();
}
bool Term::get_term_size(int &rows, int &cols) {
return Private::get_term_size(rows, cols);
}

void Term::restore_screen() {
write("\033[?1049l"); // restore screen
write(
"\033"
"8"); // restore current cursor position
// restore_screen_ = false;
}

void Term::save_screen() {
write(
"\033"
"7"); // save current cursor position
write("\033[?1049h"); // save screen
}



void Term::get_cursor_position(int& rows, int& cols){
char buf[32];
write(cursor_position_report());
for (unsigned int i = 0; i < sizeof(buf) - 1; i++) {
while (!Private::read_raw(&buf[i]))
;
if (buf[i] == 'R') {
if (i < 5) {
throw std::runtime_error(
"get_cursor_position(): too short response");
} else {
buf[i] = '\0';
}
break;
}
}
// Find the result in the response, drop the rest:
for (unsigned int i = 0; i < sizeof(buf) - 6; i++) {
if (buf[i] == '\x1b' && buf[i + 1] == '[') {
if (Private::convert_string_to_int(&buf[i + 2], "%d;%d", &rows, &cols) !=
2) {
throw std::runtime_error(
"get_cursor_position(): result could not be parsed");
}
return;
}
if (buf[i] == '\0')
break;
}
throw std::runtime_error(
"get_cursor_position(): result not found in the response");
}
// TODO: repair or remove
// void Term::get_term_size_slow(int& rows, int& cols) {
// struct CursorOff {
// const Terminal& term;
// explicit CursorOff(const Terminal& term) : term{term} {
// write(cursor_off());
// }
// ~CursorOff() { write(cursor_on()); }
// };
// CursorOff cursor_off(*this);
// int old_row{}, old_col{};
// get_cursor_position(old_row, old_col);
// write(move_cursor_right(999) + move_cursor_down(999));
// get_cursor_position(rows, cols);
// write(move_cursor(old_row, old_col));
// }

Term::Terminal::Terminal(bool _clear_screen, bool enable_keyboard, bool disable_ctrl_c) : BaseTerminal(enable_keyboard, disable_ctrl_c), clear_screen{_clear_screen} {
if (clear_screen)
save_screen();
}
Term::Terminal::Terminal(bool _clear_screen) : BaseTerminal(false, true), clear_screen{_clear_screen} {
if (clear_screen)
save_screen();
}
Term::Terminal::~Terminal() {
if (clear_screen)
restore_screen();
}
30 changes: 29 additions & 1 deletion cpp-terminal/base.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <string>
// TODO: remove include
#include "private/platform.hpp"

namespace Term {

Expand Down Expand Up @@ -93,4 +95,30 @@ std::string cursor_position_report();

std::string erase_to_eol();

}
bool is_stdin_a_tty();
bool is_stdout_a_tty();
bool get_term_size(int&, int&);

void restore_screen();

void save_screen();

void get_cursor_position(int&, int&);

// This function takes about 23ms, so it should only be used as a fallback
void get_term_size_slow(int&, int&);


// initializes the terminal
class Terminal : public Private::BaseTerminal {
private:
bool clear_screen{};
public:
Terminal(bool _clear_screen, bool enable_keyboard, bool disable_ctrl_c);
// providing no parameters will disable the keyboard and ctrl+c
Terminal(bool _clear_screen);

virtual ~Terminal() override;
};

}
103 changes: 15 additions & 88 deletions cpp-terminal/terminal.cpp → cpp-terminal/input.cpp
Original file line number Diff line number Diff line change
@@ -1,53 +1,28 @@
#include <cpp-terminal/terminal.h>
#include <cpp-terminal/terminal_base.h>
#include <functional>
#include <iostream>
#include <string>
#include <cpp-terminal/input.hpp>
#include <chrono>
#include <thread>
#include <vector>
#include <cpp-terminal/base.hpp>
#include "private/platform.hpp"

Term::Terminal::~Terminal() {
restore_screen();
}

void Term::Terminal::restore_screen() {
if (restore_screen_) {
write("\033[?1049l"); // restore screen
write(
"\033"
"8"); // restore current cursor position
restore_screen_ = false;
}
}

void Term::Terminal::save_screen() {
restore_screen_ = true;
write(
"\033"
"7"); // save current cursor position
write("\033[?1049h"); // save screen
}

int Term::Terminal::read_key() const {
int Term::read_key() {
int key{};
while ((key = read_key0()) == 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return key;
}

int Term::Terminal::read_key0() const {
int Term::read_key0() {
char c{};
if (!read_raw(&c))
if (!Private::read_raw(&c))
return 0;

if (c == '\x1b') {
char seq[4];

if (!read_raw(&seq[0]))
if (!Private::read_raw(&seq[0]))
return Key::ESC;
if (!read_raw(&seq[1])) {
if (!Private::read_raw(&seq[1])) {
if (seq[0] >= 'a' && seq[0] <= 'z') {
// gnome-term, Windows Console
return Key::ALT + seq[0];
Expand All @@ -61,7 +36,7 @@ int Term::Terminal::read_key0() const {

if (seq[0] == '[') {
if (seq[1] >= '0' && seq[1] <= '9') {
if (!read_raw(&seq[2])) {
if (!Private::read_raw(&seq[2])) {
return -2;
}
if (seq[2] == '~') {
Expand All @@ -85,10 +60,10 @@ int Term::Terminal::read_key0() const {
}
} else if (seq[2] == ';') {
if (seq[1] == '1') {
if (!read_raw(&seq[2])) {
if (!Private::read_raw(&seq[2])) {
return -10;
}
if (!read_raw(&seq[3])) {
if (!Private::read_raw(&seq[3])) {
return -11;
}
if (seq[2] == '5') {
Expand All @@ -107,7 +82,7 @@ int Term::Terminal::read_key0() const {
}
} else {
if (seq[2] >= '0' && seq[2] <= '9') {
if (!read_raw(&seq[3])) {
if (!Private::read_raw(&seq[3])) {
return -3;
}
if (seq[3] == '~') {
Expand Down Expand Up @@ -186,7 +161,7 @@ int Term::Terminal::read_key0() const {
return Key::BACKSPACE;
}
if (c == '\xc3') {
if (!read_raw(&c)) {
if (!Private::read_raw(&c)) {
return -8;
} else {
if (c >= '\xa1' && c <= '\xba') {
Expand All @@ -196,7 +171,7 @@ int Term::Terminal::read_key0() const {
return -9;
}
} else if (c == '\xc2') {
if (!read_raw(&c)) {
if (!Private::read_raw(&c)) {
return -10;
} else {
if (c == '\x8d') {
Expand All @@ -208,52 +183,4 @@ int Term::Terminal::read_key0() const {
}
return c;
}
}

void Term::Terminal::get_cursor_position(int& rows, int& cols) const {
char buf[32];
write(cursor_position_report());
for (unsigned int i = 0; i < sizeof(buf) - 1; i++) {
while (!read_raw(&buf[i]))
;
if (buf[i] == 'R') {
if (i < 5) {
throw std::runtime_error(
"get_cursor_position(): too short response");
} else {
buf[i] = '\0';
}
break;
}
}
// Find the result in the response, drop the rest:
for (unsigned int i = 0; i < sizeof(buf) - 6; i++) {
if (buf[i] == '\x1b' && buf[i + 1] == '[') {
if (convert_string_to_int(&buf[i + 2], "%d;%d", &rows, &cols) !=
2) {
throw std::runtime_error(
"get_cursor_position(): result could not be parsed");
}
return;
}
if (buf[i] == '\0')
break;
}
throw std::runtime_error(
"get_cursor_position(): result not found in the response");
}
void Term::Terminal::get_term_size_slow(int& rows, int& cols) {
struct CursorOff {
const Terminal& term;
explicit CursorOff(const Terminal& term) : term{term} {
write(cursor_off());
}
~CursorOff() { write(cursor_on()); }
};
CursorOff cursor_off(*this);
int old_row{}, old_col{};
get_cursor_position(old_row, old_col);
write(move_cursor_right(999) + move_cursor_down(999));
get_cursor_position(rows, cols);
write(move_cursor(old_row, old_col));
}
}
50 changes: 50 additions & 0 deletions cpp-terminal/input.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

namespace Term {
enum Key {
BACKSPACE = 1000,
ENTER,
ALT_ENTER,
TAB,
ARROW_LEFT,
ARROW_RIGHT,
ARROW_UP,
ARROW_DOWN,
CTRL_UP,
CTRL_DOWN,
CTRL_RIGHT,
CTRL_LEFT,
NUMERIC_5,
DEL,
HOME,
INSERT,
END,
PAGE_UP,
PAGE_DOWN,
ESC,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
// special keys
CTRL = -96,
ALT = -128
};

// Waits for a key press, translates escape codes
int read_key();

// If there was a key press, returns the translated key from escape codes,
// otherwise returns 0. If the escape code is not supported, returns a
// negative number.
int read_key0();

}
Loading