This repository has been archived on 2022-05-26. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
calculator/src/main.cpp

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;
}