diff --git a/src/input.cc b/src/input.cc index c9c50bf..ed8d0a0 100644 --- a/src/input.cc +++ b/src/input.cc @@ -7,43 +7,44 @@ vector* Input::ac_list_ = nullptr; Input::Input(string& entry, vector& autocompletion_list, string prompt, string multiline_prompt) - : status(InputStatus::kContinue) { + : status(InputStatus::kOk) { char* c_entry = nullptr; bool multiline = false; int entry_len; + bool goodbye; ac_list_ = &autocompletion_list; // linenoise for entry linenoiseSetCompletionCallback(EntryCompletionGenerator); - while (status == InputStatus::kContinue) { - // get user entry + do { + // prompt + goodbye = true; if (multiline) c_entry = linenoise(multiline_prompt.c_str(), &entry_len); else c_entry = linenoise(prompt.c_str(), &entry_len); - // Ctrl-C - if (linenoiseKeyType() == 1) { - if (entry_len > 0 || multiline) + if (linenoiseKeyType() == 1 || linenoiseKeyType() == 2) { + if (entry_len > 0 || multiline) // Ctrl-C or Ctrl-D status = InputStatus::kAbort; else status = InputStatus::kCtrlc; } else if (linenoiseKeyType() == 3) { - multiline = true; + multiline = true; // Alt-Enter (multiline) if (c_entry != nullptr) entry += c_entry; entry += " "; + goodbye = false; } else { + status = InputStatus::kError; if (c_entry != nullptr) { - entry += c_entry; - // keep history - if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str()); + entry += c_entry; // string entry + if (entry_len > 0 && c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str()); // keep history status = InputStatus::kOk; - } else { - status = InputStatus::kError; } } - } + } while (!goodbye); + free(c_entry); } diff --git a/src/input.h b/src/input.h index 171775b..4b53717 100644 --- a/src/input.h +++ b/src/input.h @@ -1,7 +1,7 @@ // Copyright (c) 2014-2022 Louis Rubet -#ifndef SRC_INPUT_HPP_ -#define SRC_INPUT_HPP_ +#ifndef SRC_INPUT_H_ +#define SRC_INPUT_H_ #include #include @@ -13,7 +13,12 @@ using std::string, std::vector; class Input { public: Input(string& entry, vector& autocompletion_list, string prompt = "rpn> ", string multiline_prompt = ">"); - enum class InputStatus { kOk, kContinue, kAbort, kCtrlc, kError } status; + enum class InputStatus { + kOk, // user entered a good string + kCtrlc, // user pressed CtrlC + kAbort, // user aborted current line + kError // entry internal error + } status; static void Preload(const char* preloadText); @@ -22,4 +27,4 @@ class Input { static vector* ac_list_; }; -#endif // SRC_INPUT_HPP_ +#endif // SRC_INPUT_H_ diff --git a/src/main.cc b/src/main.cc index 187c4dd..c1497d4 100644 --- a/src/main.cc +++ b/src/main.cc @@ -65,7 +65,7 @@ static void CatchCtrlC() { /// int main(int argc, char* argv[]) { int ret = 0; - bool go_on = true; + bool goodbye = false; // apply default configuration Program::ApplyDefault(); @@ -79,19 +79,22 @@ int main(int argc, char* argv[]) { heap heap; rpnstack stack; - while (go_on) { + while (!goodbye) { Program prog(stack, heap); string entry; switch (Input(entry, Program::GetAutocompletionWords()).status) { case Input::InputStatus::kOk: - if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye) - go_on = false; - else - prog.ShowStack(); + if (prog.Parse(entry) == kOk) { + if (prog.Run() != kGoodbye) + prog.ShowStack(); + else + goodbye = true; + continue; + } break; case Input::InputStatus::kCtrlc: - go_on = false; - break; + goodbye = true; + continue; default: break; } diff --git a/src/program.cc b/src/program.cc index a60ca3f..2f98463 100644 --- a/src/program.cc +++ b/src/program.cc @@ -249,7 +249,7 @@ RetValue Program::Run() { // test error: make rpn return EXIT_FAILURE if (err_ == kTestFailed) ret = kTestFailed; - // error: show it + // other deadly error if (ShowError(err_, err_context_) == kDeadlyError) // pb showing error -> go out software ret = kGoodbye;