Skip to content

Commit 1212520

Browse files
committed
unified blocking and non-blocking prompt and added the "immediate" toggle to chose between both versions
1 parent 1de25b1 commit 1212520

File tree

5 files changed

+73
-90
lines changed

5 files changed

+73
-90
lines changed

cpp-terminal/prompt.cpp

Lines changed: 59 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
#include "private/conversion.hpp"
66
#include "private/platform.hpp"
77

8-
Term::Result Term::prompt_blocking(const std::string& message,
9-
const std::string& first_option,
10-
const std::string& second_option,
11-
const std::string& prompt_indicator) {
8+
Term::Result Term::prompt(const std::string& message,
9+
const std::string& first_option,
10+
const std::string& second_option,
11+
const std::string& prompt_indicator,
12+
bool immediate) {
1213
Terminal term(false, true, true);
1314
std::cout << message << " [" << first_option << '/' << second_option << ']'
1415
<< prompt_indicator << ' ' << std::flush;
@@ -18,90 +19,76 @@ Term::Result Term::prompt_blocking(const std::string& message,
1819
return Result::ERROR;
1920
}
2021

21-
std::vector<char> input;
22-
unsigned short int length = 0;
2322
int key;
24-
while (true) {
25-
key = Term::read_key();
26-
if (key >= 'a' && key <= 'z') {
27-
std::cout << (char)key << std::flush;
28-
length++;
29-
input.push_back(static_cast<char>(key));
30-
} else if (key >= 'A' && key <= 'Z') {
31-
std::cout << (char)key << std::flush;
32-
length++;
33-
input.push_back(static_cast<char>(
34-
key + 32)); // convert upper case to lowercase
35-
} else if (key == Term::Key::CTRL + 'c') {
36-
std::cout << '\n';
37-
return Result::ABORT;
38-
} else if (key == Term::Key::BACKSPACE) {
39-
if (length != 0) {
40-
std::cout
41-
<< "\033[D \033[D"
42-
<< std::flush; // erase last line and move the cursor back
43-
length--;
44-
input.pop_back();
45-
}
46-
} else if (key == Term::Key::ENTER) {
47-
if (Private::vector_to_string(input) == "y" ||
48-
Private::vector_to_string(input) == "yes") {
23+
24+
if (immediate) {
25+
while (true) {
26+
key = Term::read_key();
27+
if (key == 'y' || key == 'Y') {
4928
Term::write("\n");
5029
return Result::YES;
51-
} else if (Private::vector_to_string(input) == "n" ||
52-
Private::vector_to_string(input) == "no") {
30+
} else if (key == 'n' || key == 'N') {
5331
Term::write("\n");
5432
return Result::NO;
55-
} else if (length == 0) {
33+
} else if (key == Term::Key::CTRL + 'c') {
34+
Term::write("\n");
35+
return Result::ABORT;
36+
} else if (key == Term::Key::ENTER) {
5637
Term::write("\n");
5738
return Result::NONE;
5839
} else {
5940
Term::write("\n");
6041
return Result::INVALID;
6142
}
6243
}
63-
}
64-
// should be unreachable
65-
return Result::ERROR;
66-
}
67-
68-
Term::Result Term::prompt_non_blocking(const std::string& message,
69-
const std::string& first_option,
70-
const std::string& second_option,
71-
const std::string& prompt_indicator) {
72-
Terminal term(false, true, true);
73-
std::cout << message << " [" << first_option << '/' << second_option << ']'
74-
<< prompt_indicator << ' ' << std::flush;
75-
76-
if (!Term::is_stdin_a_tty()) {
77-
Term::write("\n");
78-
return Result::ERROR;
79-
}
80-
81-
int key;
82-
while (true) {
83-
key = Term::read_key();
84-
if (key == 'y' || key == 'Y') {
85-
Term::write("\n");
86-
return Result::YES;
87-
} else if (key == 'n' || key == 'N') {
88-
Term::write("\n");
89-
return Result::NO;
90-
} else if (key == Term::Key::CTRL + 'c') {
91-
Term::write("\n");
92-
return Result::ABORT;
93-
} else if (key == Term::Key::ENTER) {
94-
Term::write("\n");
95-
return Result::NONE;
96-
} else {
97-
Term::write("\n");
98-
return Result::INVALID;
44+
} else {
45+
std::vector<char> input;
46+
unsigned short int length = 0;
47+
while (true) {
48+
key = Term::read_key();
49+
if (key >= 'a' && key <= 'z') {
50+
std::cout << (char)key << std::flush;
51+
length++;
52+
input.push_back(static_cast<char>(key));
53+
} else if (key >= 'A' && key <= 'Z') {
54+
std::cout << (char)key << std::flush;
55+
length++;
56+
input.push_back(static_cast<char>(
57+
key + 32)); // convert upper case to lowercase
58+
} else if (key == Term::Key::CTRL + 'c') {
59+
std::cout << '\n';
60+
return Result::ABORT;
61+
} else if (key == Term::Key::BACKSPACE) {
62+
if (length != 0) {
63+
std::cout << "\033[D \033[D"
64+
<< std::flush; // erase last line and move the
65+
// cursor back
66+
length--;
67+
input.pop_back();
68+
}
69+
} else if (key == Term::Key::ENTER) {
70+
if (Private::vector_to_string(input) == "y" ||
71+
Private::vector_to_string(input) == "yes") {
72+
Term::write("\n");
73+
return Result::YES;
74+
} else if (Private::vector_to_string(input) == "n" ||
75+
Private::vector_to_string(input) == "no") {
76+
Term::write("\n");
77+
return Result::NO;
78+
} else if (length == 0) {
79+
Term::write("\n");
80+
return Result::NONE;
81+
} else {
82+
Term::write("\n");
83+
return Result::INVALID;
84+
}
85+
}
9986
}
10087
}
10188
}
10289

103-
Term::Result_simple Term::prompt_simple(std::string message) {
104-
switch (prompt_blocking(message, "Y", "N", ":")) {
90+
Term::Result_simple Term::prompt_simple(const std::string& message) {
91+
switch (prompt(message, "Y", "N", ":", false)) {
10592
case Result::YES:
10693
return Result_simple::YES;
10794
case Result::ABORT:

cpp-terminal/prompt.hpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,19 @@ enum class Result_simple { YES, NO, ABORT };
2323

2424
// A simple yes/no prompt, requires the user to press the ENTER key to continue
2525
// The arguments are used like this: 1 [2/3]4 <user Input>
26-
Result prompt_blocking(const std::string& message,
27-
const std::string& first_option,
28-
const std::string& second_option,
29-
const std::string& prompt_indicator);
30-
31-
// A simple yes/no prompt, returns immediately after the first key press
32-
// The arguments are used like this: 1 [2/3]4 <user Input>
33-
Result prompt_non_blocking(const std::string& message,
34-
const std::string& first_option,
35-
const std::string& second_option,
36-
const std::string& prompt_indicator);
26+
// the immediate switch indicates toggles wether pressing enter for
27+
// confirming the input is required or not
28+
Result prompt(const std::string& message,
29+
const std::string& first_option,
30+
const std::string& second_option,
31+
const std::string& prompt_indicator,
32+
bool);
3733

3834
// The most simple prompt possible, requires the user to press enter to continue
3935
// The arguments are used like this: 1 [y/N]:
4036
// Invalid input, errors (like no attached terminal) all result in 'no' as
4137
// default
42-
Result_simple prompt_simple(std::string message);
38+
Result_simple prompt_simple(const std::string& message);
4339

4440
/* Multiline prompt */
4541

examples/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
add_executable(prompt_multiline prompt_multiline.cpp)
22
target_link_libraries(prompt_multiline cpp-terminal)
33

4-
add_executable(prompt_blocking prompt_blocking.cpp)
5-
target_link_libraries(prompt_blocking cpp-terminal)
4+
add_executable(prompt_immediate prompt_immediate.cpp)
5+
target_link_libraries(prompt_immediate cpp-terminal)
66

7-
add_executable(prompt_non_blocking prompt_non_blocking.cpp)
8-
target_link_libraries(prompt_non_blocking cpp-terminal)
7+
add_executable(prompt_not_immediate prompt_not_immediate.cpp)
8+
target_link_libraries(prompt_not_immediate cpp-terminal)
99

1010
add_executable(prompt_simple prompt_simple.cpp)
1111
target_link_libraries(prompt_simple cpp-terminal)

examples/prompt_blocking.cpp renamed to examples/prompt_immediate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ int main() {
77
<< CPP_TERMINAL_VERSION_COMPLETE << std::endl;
88
try {
99
std::cout << "CPP-Terminal basic prompt example: \n\n";
10-
switch (Term::prompt_blocking("Proceed?", "Y", "n", ":")) {
10+
switch (Term::prompt("Proceed?", "Y", "n", ":", true)) {
1111
case Term::Result::NONE: // no input was given
1212
std::cout << "No input given, proceeding anyway...\n";
1313
break;

examples/prompt_non_blocking.cpp renamed to examples/prompt_not_immediate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ int main() {
77
<< CPP_TERMINAL_VERSION_COMPLETE << std::endl;
88
try {
99
std::cout << "CPP-Terminal basic prompt example: \n\n";
10-
switch (Term::prompt_non_blocking("Proceed?", "Y", "n", ":")) {
10+
switch (Term::prompt("Proceed?", "Y", "n", ":", false)) {
1111
case Term::Result::NONE: // no input was given
1212
std::cout << "No input given, proceeding anyway...\n";
1313
break;

0 commit comments

Comments
 (0)