167 lines
4.6 KiB
C++
167 lines
4.6 KiB
C++
#include <iostream>
|
|
#include <sstream>
|
|
#include "calculator.cpp"
|
|
#include "commands.cpp"
|
|
#include "cursor.cpp"
|
|
#include "debug.cpp"
|
|
#include "getch.h"
|
|
#include "terminal.cpp"
|
|
|
|
/**
|
|
* @brief Prints entered keys to the console.
|
|
*
|
|
* @param keys currently typed keys.
|
|
*/
|
|
void writeInput(terminal::state keys) {
|
|
// FIXME: Do not duplicate lines when line overflows
|
|
// possible mitigation: only write one line
|
|
|
|
// FIXME: flickering
|
|
cursor::setX(1);
|
|
std::cout << "\033[0K" << "> ";
|
|
for(auto it = keys.keys.begin(); it != keys.keys.end(); it++) {
|
|
std::cout << *it;
|
|
}
|
|
|
|
cursor::setX(3+keys.cursorPos);
|
|
}
|
|
|
|
/**
|
|
* @brief Writes result line with the result while in typing mode
|
|
*
|
|
* @param string the result
|
|
* @param paranthesis missing paranthesis count, negative if misses left paranthesis
|
|
* @param calcuationValid is calculation valid
|
|
* @param inputSize the current input size (used to where display missing paranthesis)
|
|
*/
|
|
void writeResultLine(
|
|
const std::string string,
|
|
const int paranthesis = 0,
|
|
const bool calcuationValid = true,
|
|
const unsigned int inputSize = 20
|
|
) {
|
|
auto savedCursorPosition = cursor::getPosition().x;
|
|
|
|
if (paranthesis != 0) {
|
|
cursor::setX(inputSize+5);
|
|
std::cout << "\033[31m";
|
|
if (paranthesis > 4) {
|
|
std::cout << ") * " << paranthesis;
|
|
}
|
|
else if (paranthesis > 0) {
|
|
for(unsigned short i = 0; i < paranthesis; i++) std::cout << ")";
|
|
}
|
|
else if (paranthesis < 4) {
|
|
std::cout << "( * " << -paranthesis;
|
|
}
|
|
else { //paranthesis is one of -1,-2,-3,-4
|
|
for(unsigned short i = 0; i < -paranthesis; i++) std::cout << ")";
|
|
}
|
|
std::cout << "\033[0m";
|
|
}
|
|
|
|
std::cout << "\n\033[0K\033[90m";
|
|
// FIXME: line overflow handling
|
|
if (calcuationValid) std::cout << string;
|
|
else std::cout << "-";
|
|
cursor::up();
|
|
cursor::setX(savedCursorPosition);
|
|
std::cout << "\033[0m";
|
|
}
|
|
|
|
/**
|
|
* @brief Writes result line with the result while in typing mode
|
|
*
|
|
* @param result the calculation result
|
|
* @param inputSize the current input size (used to where display missing paranthesis)
|
|
*/
|
|
void writeResultLine(Calculator::parseAndCalculateResult result, const unsigned int inputSize) {
|
|
std::stringstream result_string;
|
|
result_string << result.value;
|
|
writeResultLine(result_string.str(), result.unmatchedParanthesis, result.valid, inputSize);
|
|
}
|
|
|
|
int main() {
|
|
#ifdef _WIN32
|
|
// https://stackoverflow.com/a/47158348
|
|
{ // enable virtual terminal for legacy Windows terminals
|
|
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
DWORD consoleMode;
|
|
GetConsoleMode(console, &consoleMode);
|
|
consoleMode |= 0x0004;
|
|
SetConsoleMode(console, consoleMode);
|
|
}
|
|
#endif
|
|
std::setlocale(LC_ALL, "");
|
|
std::cout << "type :q to exit, type :h for help\n";
|
|
|
|
bool exit = false; //should we exit?
|
|
terminal::state keys;
|
|
while (!exit) {
|
|
writeInput(keys);
|
|
// writeResultLine("");
|
|
// background calculation
|
|
// new std::thread([keys]{
|
|
writeResultLine(Calculator::parseAndCaluclate(keys.keys), keys.keys.size());
|
|
// });
|
|
auto input = cursor::getchar();
|
|
|
|
// if speciality char
|
|
if (input.special != 0) {
|
|
switch (input.code)
|
|
{
|
|
case 75: // ARROW_LEFT
|
|
terminal::key_left(keys);
|
|
break;
|
|
case 77: // ARROW_RIGHT
|
|
terminal::key_right(keys);
|
|
break;
|
|
default:
|
|
#ifdef DEBUG
|
|
debugKey(input);
|
|
#endif
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
else switch (input.code) {
|
|
case 8: // BACKSPACE
|
|
terminal::key_backspace(keys);
|
|
break;
|
|
case 13: // ENTER
|
|
std::cout << "\n\033[2K" << Calculator::parseAndCaluclate(keys.keys, true).value << "\n";
|
|
keys.cursorPos = 0;
|
|
keys.keys.clear();
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case '.':
|
|
case '+':
|
|
case '-':
|
|
case '*':
|
|
case '/':
|
|
case '(':
|
|
case ')':
|
|
terminal::key_insert(keys, input.code);
|
|
break;
|
|
case ':':
|
|
exit |= commands::loop();
|
|
break;
|
|
default:
|
|
#ifdef DEBUG
|
|
debugKey(input);
|
|
#endif
|
|
break;
|
|
};
|
|
}
|
|
std::cout << "\033[0m";
|
|
return 0;
|
|
}
|