Simplify history management

This commit is contained in:
Louis Rubet 2022-03-08 11:15:45 +01:00
parent 29c839c873
commit 39c9a75c7e

View file

@ -12,9 +12,21 @@ using std::cerr;
#include "input.h" #include "input.h"
#include "program.h" #include "program.h"
/// @brief actions to be done at rpn exit /// @brief lines history management: load file
/// ///
static void ExitInteractive() { static void StartHistory() {
struct passwd* pw = getpwuid(getuid());
if (pw != nullptr) {
stringstream history_path;
history_path << pw->pw_dir << "/.rpn_history";
linenoiseHistorySetMaxLen(100);
linenoiseHistoryLoad(history_path.str().c_str());
}
}
/// @brief lines history management: save
///
static void StopHistory() {
struct passwd* pw = getpwuid(getuid()); struct passwd* pw = getpwuid(getuid());
if (pw != nullptr) { if (pw != nullptr) {
stringstream history_path; stringstream history_path;
@ -24,7 +36,6 @@ static void ExitInteractive() {
ofstream history(history_path.str(), ios_base::out | ios_base::trunc); ofstream history(history_path.str(), ios_base::out | ios_base::trunc);
history.close(); history.close();
// save it
if (linenoiseHistorySave(history_path.str().c_str()) != 0) if (linenoiseHistorySave(history_path.str().c_str()) != 0)
cerr << "warning, could not save " << history_path.str() << " [errno=" << errno << ' ' << strerror(errno) cerr << "warning, could not save " << history_path.str() << " [errno=" << errno << ' ' << strerror(errno)
<< "']" << endl; << "']" << endl;
@ -32,38 +43,13 @@ static void ExitInteractive() {
} }
} }
/// @brief actions to be done at rpn exit
///
static void EnterInteractive() {
struct passwd* pw = getpwuid(getuid());
if (pw != nullptr) {
stringstream history_path;
history_path << pw->pw_dir << "/.rpn_history";
// don't care about errors
linenoiseHistorySetMaxLen(100);
linenoiseHistoryLoad(history_path.str().c_str());
}
}
/// @brief handle CtrlC signal (sigaction handler): exit rpn
///
/// @param sig signal, see POSIX sigaction
/// @param siginfo signal info, see POSIX sigaction
/// @param context see POSIX sigaction
///
static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __attribute__((unused)), static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __attribute__((unused)),
void* context __attribute__((unused))) { void* context __attribute__((unused))) {
ExitInteractive(); StopHistory(); // don't put an entry line canceled with CtrlC in history
} }
/// @brief setup signals handlers to stop with honours static void CatchCtrlC() {
///
/// @param prog the prog to catch the signals to, must be checked not nullptr by user
///
static void CatchSignals() {
struct sigaction act = {0}; struct sigaction act = {0};
act.sa_sigaction = &CtrlHandler; act.sa_sigaction = &CtrlHandler;
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, nullptr) < 0) if (sigaction(SIGINT, &act, nullptr) < 0)
@ -87,23 +73,16 @@ int main(int argc, char* argv[]) {
if (argc == 1) { if (argc == 1) {
Program::Welcome(); Program::Welcome();
// init history StartHistory();
EnterInteractive(); CatchCtrlC();
// user could stop prog with CtrlC
CatchSignals();
// entry loop
heap heap; heap heap;
rpnstack stack; rpnstack stack;
while (go_on) { while (go_on) {
//
// make program from interactive entry
Program prog(stack, heap); Program prog(stack, heap);
string entry; string entry;
switch (Input(entry, Program::GetAutocompletionWords()).status) { switch (Input(entry, Program::GetAutocompletionWords()).status) {
case Input::InputStatus::kOk: case Input::InputStatus::kOk:
// run it
if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye) if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye)
go_on = false; go_on = false;
else else
@ -116,10 +95,9 @@ int main(int argc, char* argv[]) {
break; break;
} }
} }
StopHistory();
// manage history and exit } else {
ExitInteractive(); // run with cmd line arguments
} else { // run with cmd line arguments
heap heap; heap heap;
rpnstack stack; rpnstack stack;
Program prog(stack, heap); Program prog(stack, heap);
@ -132,10 +110,6 @@ int main(int argc, char* argv[]) {
// make program // make program
ret = prog.Parse(entry); ret = prog.Parse(entry);
if (ret == kOk) { if (ret == kOk) {
// user could stop prog with CtrlC
CatchSignals();
// run it
ret = prog.Run(); ret = prog.Run();
prog.ShowStack(false); prog.ShowStack(false);
} }