You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
5.5 KiB
234 lines
5.5 KiB
#include <Editor.hpp>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
namespace groove {
|
|
|
|
Editor::Editor(std::string filename) : x(0), y(0), buffer(std::make_unique<Buffer>()),
|
|
mode_(Mode::EDIT), filename(filename), offset(0) {
|
|
|
|
if (!this->load()) {
|
|
std::cerr << "Could not open file: '" << this->filename << "', creating it on save.\n";
|
|
this->buffer->insert("");
|
|
}
|
|
}
|
|
|
|
bool Editor::load() {
|
|
std::ifstream file(this->filename.c_str());
|
|
if(file.is_open()) {
|
|
while(!file.eof()) {
|
|
std::string line;
|
|
std::getline(file, line);
|
|
this->buffer->insert(line);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Editor::save() {
|
|
std::ofstream file(this->filename.c_str());
|
|
if(file.is_open()) {
|
|
for (auto& line : this->buffer->linebuffer()) {
|
|
file << line << std::endl;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void groove::Editor::input(int car) {
|
|
if (this->mode_ != Mode::SAVE) {
|
|
switch (car) {
|
|
case KEY_LEFT:
|
|
this->left();
|
|
return;
|
|
case KEY_RIGHT:
|
|
this->right();
|
|
return;
|
|
case KEY_UP:
|
|
this->up();
|
|
return;
|
|
case KEY_DOWN:
|
|
this->down();
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (this->mode_) {
|
|
case Mode::EDIT:
|
|
switch (car) {
|
|
case 'q':
|
|
this->mode_ = Mode::QUIT;
|
|
break;
|
|
case 'i':
|
|
this->mode_ = Mode::INSERT;
|
|
break;
|
|
case 'a':
|
|
this->x = static_cast<int>(this->buffer->at(this->y).length());
|
|
this->mode_ = Mode::INSERT;
|
|
break;
|
|
case 's':
|
|
this->mode_ = Mode::SAVE;
|
|
break;
|
|
case 'c':
|
|
this->clipboard = this->buffer->at(this->y);
|
|
break;
|
|
case 'x':
|
|
this->clipboard = this->buffer->at(this->y);
|
|
this->buffer->remove(this->y);
|
|
break;
|
|
case 'p':
|
|
this->buffer->insert(this->clipboard, this->y);
|
|
this->y++;
|
|
this->x = this->buffer->at(this->y).size();
|
|
break;
|
|
case 'd':
|
|
this->buffer->remove(this->y);
|
|
break;
|
|
}
|
|
break;
|
|
case Mode::INSERT:
|
|
switch (car) {
|
|
case 27:
|
|
this->mode_ = Mode::EDIT;
|
|
break;
|
|
case KEY_ENTER:
|
|
case 10:
|
|
{
|
|
std::string appendix;
|
|
appendix = "";
|
|
if (this->buffer->at(this->y).size() > this->x) {
|
|
appendix = this->buffer->at(this->y).substr(this->x, this->buffer->at(this->y).size());
|
|
this->buffer->at(this->y) = this->buffer->at(this->y).substr(0, this->x);
|
|
}
|
|
this->buffer->insert(this->y);
|
|
this->y++;
|
|
this->buffer->linebuffer().at(this->y) += appendix;
|
|
this->x = 0;
|
|
}
|
|
break;
|
|
case KEY_BACKSPACE:
|
|
if (this->x - 1 >= 0) {
|
|
this->x--;
|
|
this->buffer->remove(this->y, this->x);
|
|
}
|
|
else {
|
|
if (this->buffer->at(this->y).size() > 0 && this->y > 0) {
|
|
int oldLength = static_cast<int>(this->buffer->at(this->y - 1).size());
|
|
this->buffer->at(this->y - 1) += this->buffer->at(this->y);
|
|
this->buffer->remove(this->y);
|
|
this->y--;
|
|
this->x = oldLength;
|
|
}
|
|
else {
|
|
if (this->y - 1 >= 0) {
|
|
this->buffer->remove(this->y);
|
|
this->y--;
|
|
this->x = static_cast<int>(this->buffer->at(this->y).length());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case KEY_DC:
|
|
if (this->buffer->at(this->y).length() > this->x)
|
|
this->buffer->deleteChar(this->y, this->x);
|
|
else {
|
|
if (this->buffer->at(this->y).empty() && this->buffer->linebuffer().size() - 1 > this->y)
|
|
this->buffer->remove(this->y);
|
|
else if (this->buffer->linebuffer().size() - 1 > this->y) {
|
|
this->buffer->at(this->y) += this->buffer->at(this->y + 1);
|
|
this->buffer->remove(this->y + 1);
|
|
}
|
|
}
|
|
break;
|
|
case KEY_BTAB:
|
|
case KEY_CTAB:
|
|
case KEY_STAB:
|
|
case KEY_CATAB:
|
|
case 9:
|
|
this->buffer->at(this->y).insert(this->x, 4, ' ');
|
|
this->x += 4;
|
|
break;
|
|
default:
|
|
{
|
|
std::ofstream log("log");
|
|
log << car << std::endl;
|
|
this->buffer->at(this->y).insert(this->x, 1, char(car));
|
|
if (this->lastChar != 195 && this->lastChar != 182)
|
|
this->x++;
|
|
this->lastChar = char(car);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case Mode::QUIT:
|
|
break;
|
|
case Mode::SAVE:
|
|
switch (car) {
|
|
case 'n':
|
|
case 27:
|
|
this->mode_ = Mode::EDIT;
|
|
break;
|
|
case 'y':
|
|
if (!this->save())
|
|
std::cerr << "Could not write to file: '" << this->filename << "'\n";
|
|
this->mode_ = Mode::EDIT;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Editor::render() {
|
|
clear();
|
|
for (int i = 0; i < LINES - 1 + this->offset; i++) {
|
|
if(i >= this->buffer->linebuffer().size()) {
|
|
move(i - this->offset, 0);
|
|
clrtoeol();
|
|
}
|
|
else {
|
|
std::string line = /*std::to_string(i) + " | " +*/ this->buffer->at(i);
|
|
mvprintw(i - this->offset, 0, line.c_str());
|
|
}
|
|
clrtoeol();
|
|
}
|
|
this->status();
|
|
move(this->y - this->offset, this->x);
|
|
}
|
|
|
|
void Editor::status() {
|
|
std::string status;
|
|
switch(this->mode_)
|
|
{
|
|
case Mode::EDIT:
|
|
status = "[E]";
|
|
break;
|
|
case Mode::INSERT:
|
|
status = "[I]";
|
|
break;
|
|
case Mode::QUIT:
|
|
status = "[QUIT]";
|
|
break;
|
|
}
|
|
status += "\t\t" +
|
|
std::to_string(this->y) + ", " +
|
|
std::to_string(this->x) +
|
|
"\t\t\tbuffer: " + std::to_string(this->buffer->linebuffer().size()) +
|
|
"\toffset: " + std::to_string(this->offset);
|
|
|
|
if (this->mode_ == Mode::SAVE)
|
|
status = "Save File '" + this->filename + "'? [Y/N]: ";
|
|
|
|
status += std::string(COLS - status.length(), ' ');
|
|
|
|
attron(COLOR_PAIR(2));
|
|
mvprintw(LINES-1, 0, status.c_str());
|
|
|
|
//clrtoeol();
|
|
attroff(COLOR_PAIR(2));
|
|
}
|
|
|
|
} |