Skip to content
7 changes: 4 additions & 3 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2

- name: Build and test
- name: Build
run: |
ci\compile_test.bat
examples\Release\colors.exe
ci\compile_test.ps1
- name: Test
run: ci\test.ps1
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ cmake-build-release-cygwin/
cmake-build-debug/
cmake-build-debug-visual-studio/
cmake-build-debug-cygwin/
cmake-build-minsizerel/
cmake-build-relwithdebinfo/
.idea/

# cmake
Expand Down
8 changes: 0 additions & 8 deletions ci/compile_test.bat

This file was deleted.

11 changes: 11 additions & 0 deletions ci/compile_test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#cmake -DCMAKE_INSTALL_PREFIX=.\inst .
cmake .
cmake --build . --config Release
cmake --install . --config Release
ctest --output-on-failure

# Install on windows is complicated and not like on linux
#cd tests\test-standalone
#cmake -DCMAKE_PREFIX_PATH=%cd%\..\inst .
#cmake --build . --config Release
#cd
10 changes: 10 additions & 0 deletions ci/test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
echo "running example programs"
.\examples\Release\colors.exe
.\tests\Release\test_terminal.exe
.\examples\Release\read_stdin.exe

echo "testing read_stind"
if ((echo test | .\examples\Release\read_stdin.exe) -ne "Input from stdin: test") {
echo "read_stdin gave wrong output"
exit 1
}
7 changes: 7 additions & 0 deletions ci/tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ set -ex

./tests/test_terminal
./examples/colors
./examples/read_stdin

echo "testing stdin example"
if [[ $(echo test | ./examples/read_stdin) != "Input from stdin: test" ]]; then
echo "stdin example returned wrong input"
exit 1
fi

echo "Expected to succeed:"
./examples/colors < README.md
Expand Down
20 changes: 20 additions & 0 deletions cpp-terminal/input.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <chrono>
#include <cpp-terminal/base.hpp>
#include <cpp-terminal/input.hpp>
#include <thread>
#include "private/platform.hpp"
Expand Down Expand Up @@ -183,3 +184,22 @@ int Term::read_key0() {
return c;
}
}

// returns the whole input from STDIN as string
std::string Term::read_stdin() {
std::string file;
char c;
while (true) {
c = Private::read_raw_stdin();
if (c == 0x04) { // check for end of transmission signal
return file;
} else {
file += c;
}
}
}
std::string Term::read_stdin_alone() {
// temporarily enable raw mode
Term::Terminal term(false, true, false, false);
return Term::read_stdin();
}
16 changes: 15 additions & 1 deletion cpp-terminal/input.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <string>

namespace Term {
enum Key {
Expand Down Expand Up @@ -40,11 +41,24 @@ enum Key {
};

// Waits for a key press, translates escape codes
// if Term:Terminal is not enabling the keyboard it'll loop for infinity
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
// otherwise returns 0. If the escape code is not supported it returns a
// negative number.
// if Term::Terminal is not enabling the keyboard it'll always return 0
int read_key0();

// returns the stdin as a string
// waits until the EOT signal is send
// if Term::Terminal is not enabling the keyboard this function will wait until
// the user presses CTRL+D (which sends the EOT signal)
std::string read_stdin();

// returns stdin as a string, Term::Terminal is used to enable input to make the
// function non-blocking, use Term::read_stdin() when Term::Terminal is already
// created
std::string read_stdin_alone();

} // namespace Term
40 changes: 22 additions & 18 deletions cpp-terminal/private/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,24 @@ bool Term::Private::get_term_size(int& rows, int& cols) {
}
#endif
}
char Term::Private::read_raw_stdin() {
int c = getchar();
if (c >= 0) {
return c;
} else if (c == EOF) {
// In non-raw (blocking) mode this happens when the input file
// ends. In such a case, return the End of Transmission (EOT)
// character (Ctrl-D)
return 0x04;
} else {
throw std::runtime_error("getchar() failed");
}
}

bool Term::Private::read_raw(char* s) {
// TODO: What if the keyboard is not initialized?
if (false) {
int c = getchar();
if (c >= 0) {
*s = c;
} else if (c == EOF) {
// In non-raw (blocking) mode this happens when the input file
// ends. In such a case, return the End of Transmission (EOT)
// character (Ctrl-D)
*s = 0x04;
} else {
throw std::runtime_error("getchar() failed");
}
return true;
// do nothing when TTY is not connected
if (!is_stdin_a_tty()) {
return false;
}
#ifdef _WIN32
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
Expand Down Expand Up @@ -144,8 +146,9 @@ Term::Private::BaseTerminal::~BaseTerminal() noexcept(false) {
Term::Private::BaseTerminal::BaseTerminal(bool enable_keyboard,
bool /*disable_ctrl_c*/)
: keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
// silently disable raw mode for non-tty
if (keyboard_enabled)
keyboard_enabled = is_stdin_a_tty();
out_console = is_stdout_a_tty();
if (out_console) {
hout = GetStdHandle(STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -187,8 +190,9 @@ Term::Private::BaseTerminal::BaseTerminal(bool enable_keyboard,
bool disable_ctrl_c)
: orig_termios{std::make_unique<termios>()},
keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
// silently disable raw mode for non-tty
if (keyboard_enabled)
keyboard_enabled = is_stdin_a_tty();
if (keyboard_enabled) {
if (tcgetattr(STDIN_FILENO, orig_termios.get()) == -1) {
throw std::runtime_error("tcgetattr() failed");
Expand Down
2 changes: 2 additions & 0 deletions cpp-terminal/private/platform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,6 @@ class BaseTerminal {
virtual ~BaseTerminal() noexcept(false);
};

char read_raw_stdin();

} // namespace Term::Private
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ target_link_libraries(keys cpp-terminal)
add_executable(colors colors.cpp)
target_link_libraries(colors cpp-terminal)

add_executable(read_stdin read_stdin.cpp)
target_link_libraries(read_stdin cpp-terminal)

# enable warnings and set compile features
foreach(target kilo menu menu_window keys colors)
# Force Microsoft Visual Studio to decode sources files in UTF-8
Expand Down
6 changes: 6 additions & 0 deletions examples/keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ using Term::Terminal;

int main() {
try {
// check if the terminal is capable of handling input
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(true, true, true, false);
int rows{}, cols{};
Term::get_term_size(rows, cols);
Expand Down
6 changes: 6 additions & 0 deletions examples/kilo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,12 @@ int main(int argc, char* argv[]) {
// being called when exception happens and the terminal is not put into
// correct state.
try {
// check if the terminal is capable of handling input
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(true, true, false, false);
initEditor();
if (argc >= 2) {
Expand Down
6 changes: 6 additions & 0 deletions examples/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ void render(int rows, int cols, int menuheight, int menuwidth, int menupos) {

int main() {
try {
// check if the terminal is capable of handling input
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(true, true, true, true);
int rows{}, cols{};
Term::get_term_size(rows, cols);
Expand Down
6 changes: 6 additions & 0 deletions examples/menu_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ std::string render(Term::Window& scr,

int main() {
try {
// check if the terminal is capable of handling input
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(true, true, true, true);
int rows{}, cols{};
Term::get_term_size(rows, cols);
Expand Down
6 changes: 6 additions & 0 deletions examples/menu_window_24bit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ std::string render(Term::Window_24bit& scr,

int main() {
try {
// check if the terminal is capable of handling input
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(true, true, false, false);
int rows{}, cols{};
Term::get_term_size(rows, cols);
Expand Down
5 changes: 5 additions & 0 deletions examples/prompt_multiline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ bool determine_completeness([[maybe_unused]] std::string command) {

int main() {
try {
if (!Term::is_stdin_a_tty()) {
std::cout << "The terminal is not attached to a TTY and therefore "
"can't catch user input. Exiting...\n";
return 1;
}
Terminal term(false, true, false, false);
std::cout << "Interactive prompt." << std::endl;
std::cout << " * Use Ctrl-D to exit." << std::endl;
Expand Down
6 changes: 6 additions & 0 deletions examples/read_stdin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <cpp-terminal/input.hpp>
#include <iostream>

int main() {
std::cout << "Input from stdin: " << Term::read_stdin_alone() << std::endl;
}