#include #include #include namespace groove { Editor::Editor(std::string filename) : x(0), y(0), buffer(std::make_unique()), 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(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(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(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)); } }