nds-console/source/console.cpp

219 lines
5.8 KiB
C++

#include "console.h"
void NDSConsole::processVirtualKey(int key)
{
// remapping some special virtual keyboard keys
switch (key)
{
case DVK_LEFT:
moveCursorIndex(MovingDirection2D::LeftOrUp);
break;
case DVK_RIGHT:
moveCursorIndex(MovingDirection2D::RightOrDown);
break;
case DVK_UP:
moveRecentBuffer(MovingDirection2D::LeftOrUp);
break;
case DVK_DOWN:
moveRecentBuffer(MovingDirection2D::RightOrDown);
break;
case DVK_BACKSPACE:
removeChar();
break;
case DVK_ENTER:
returnPrompt();
break;
case DVK_ALT:
case DVK_CTRL:
case DVK_SHIFT:
case DVK_CAPS:
case DVK_FOLD:
case DVK_MENU:
break;
default:
insertChar(char(key));
break;
}
}
void NDSConsole::insertChar(char c)
{
// the letter has to be added at the top of the string
if (promptCursorIndex == promptBuffer->length())
{
promptBuffer->push_back(c);
promptCursorIndex++;
}
// the letter has to be inserted inside the string
else
promptBuffer->insert(promptBuffer->begin() + promptCursorIndex++, c);
// setting the max reached prompt length whether the current prompt length is greater
if (promptBuffer->length() > maxReachedPromptLength)
maxReachedPromptLength = promptBuffer->length();
}
void NDSConsole::removeChar()
{
// when the prompt buffer is empty there's no need to remove any char
if (promptCursorIndex == 0)
return;
// the letter to remove is on the top of the string
if (promptCursorIndex == promptBuffer->length())
{
promptBuffer->pop_back();
promptCursorIndex--;
return;
}
// the letter to remove is inside the string
promptBuffer->erase(promptBuffer->begin() + --promptCursorIndex);
}
void NDSConsole::flushPromptBuffer(uint64_t frame, bool printCursor)
{
// going back at the end of the prompt prefix
printableConsole->cursorX = getPromptPrefix().length();
// printing the buffer and the cursor
for (uint64_t i = 0; i < promptBuffer->length(); i++)
{
// printing the cursor when it's inside the string
if (i == promptCursorIndex)
printBlinkingCursor(frame, printCursor);
iprintf("%c", promptBuffer->at(i));
}
// printing the cursor when is on the top of the string
if (promptCursorIndex == promptBuffer->length())
printBlinkingCursor(frame, printCursor);
// replacing the overflowed letters with spaces
for (uint64_t i = 0; i < maxReachedPromptLength + 1 - promptBuffer->length(); i++)
iprintf(" ");
}
void NDSConsole::moveCursorIndex(MovingDirection2D direction)
{
// the cursor index is at the left edge (cannot be moved again)
if (direction == MovingDirection2D::LeftOrUp && promptCursorIndex == 0)
return;
// the cursor index is at the right edge (cannot be moved again)
if (direction == MovingDirection2D::RightOrDown && promptCursorIndex == promptBuffer->length())
return;
promptCursorIndex += uint64_t(direction);
}
void NDSConsole::moveRecentBuffer(MovingDirection2D direction)
{
// the reecent buffer index is at the upper edge (cannot be moved again)
if (direction == MovingDirection2D::LeftOrUp && recentPromptsIndex == 0)
return;
// the recenet buffer index is at the down edge (cannot be moved again)
if (direction == MovingDirection2D::RightOrDown && recentPromptsIndex == recentPrompts.size() - 1)
return;
// updating the recent prompts index and setting up the new prompt buffer
recentPromptsIndex += uint64_t(direction);
this->promptBuffer = recentPrompts[recentPromptsIndex];
this->promptCursorIndex = promptBuffer->length();
}
void NDSConsole::scrollScreen(MovingDirection2D direction)
{
// unimplemented yet
}
void NDSConsole::returnPrompt()
{
// when the prompt buffer is empty there's no need to process the prompted command
if (promptBuffer->empty())
return;
// removing the old prompt buffer whether it's empty (returnPrompt worked because promptBuffer was set to another recent prompt)
if (recentPrompts[recentPrompts.size() - 1]->empty())
{
delete recentPrompts[recentPrompts.size() - 1];
recentPrompts.pop_back();
}
// reprinting the current prompt buffer without the cursor
flushPromptBuffer(1, false);
// going to the next line for the prompted command output
iprintf("\n");
try
{
// processing the prompted command
auto result = processCommand(*promptBuffer);
// when the expression returns `none` it's not shown up
if (result.kind != NScript::NodeKind::None)
iprintf("\n%s\n", result.toString().c_str());
}
catch (const NScript::Error& e)
{
printPromptParsingError(e);
}
// setting up the new prompt buffer
// the old one is already saved on the top of recentPrompts
this->promptBuffer = new std::string();
this->promptCursorIndex = 0;
// saving the new prompt buffer on the top of recentPrompts
recentPromptsIndex = recentPrompts.size();
recentPrompts.push_back(promptBuffer);
// initializing the new prompt line
printPromptPrefix();
}
void NDSConsole::printPromptParsingError(NScript::Error e)
{
auto promptLength = getPromptPrefix().length();
// padding the error underlining
for (uint64_t i = 0; i < promptLength + e.position.startPos; i++)
iprintf(" ");
// underlining the wrong part
for (uint64_t i = 0; i < e.position.length(); i++)
iprintf("-");
// printing the error message
iprintf("\n\nerror: ");
for (const auto& m : e.message)
iprintf("%s", m.c_str());
iprintf("\n");
}
NScript::Node NDSConsole::processCommand(std::string command)
{
NScript::Parser parser(command);
return evaluator.evaluateNode(parser.parse());
}
void NDSConsole::printBlinkingCursor(uint64_t frame, bool printCursor)
{
if (!printCursor)
return;
iprintf(frame % 32 <= 16 ? " " : "|");
}