Initial commit
This commit is contained in:
commit
dabf8a22f6
14 changed files with 1072 additions and 0 deletions
185
src/main.cpp
Normal file
185
src/main.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "calculator.cpp"
|
||||
#include "commands.cpp"
|
||||
#include "cursor.cpp"
|
||||
#include "getch.h"
|
||||
#include "terminal.cpp"
|
||||
|
||||
/**
|
||||
* @brief Prints value of pressed key in top left corner.
|
||||
* Additionally it can get offet to see more presses.
|
||||
*
|
||||
* @param _flags keypress flags.
|
||||
* @param _key char that we got.
|
||||
* @param offset how much column do you want to spare?
|
||||
*/
|
||||
void debugKey(cursor::key _key, short& offset) {
|
||||
cursor::savePosition();
|
||||
cursor::setPosition(1, 1);
|
||||
// std::cout << " "; // clear debug corner :^)
|
||||
cursor::setPosition(offset++ * 4 + 1, 1);
|
||||
std::cout << "\033[31;1m";
|
||||
// if control flag set
|
||||
if (_key.special != 0)
|
||||
std::cout << "^";
|
||||
std::cout << int(_key.code);
|
||||
std::cout << "\033[0m";
|
||||
cursor::restorePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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";
|
||||
|
||||
short debugOffset = 0; //debug
|
||||
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:
|
||||
debugKey(input, debugOffset);
|
||||
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:
|
||||
debugKey(input, debugOffset);
|
||||
break;
|
||||
};
|
||||
}
|
||||
std::cout << "\033[0m";
|
||||
return 0;
|
||||
}
|
Reference in a new issue