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.
154 lines
4.4 KiB
154 lines
4.4 KiB
#include <Editor.hpp>
|
|
#include <Highlighter.hpp>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <math.h>
|
|
|
|
namespace groove {
|
|
|
|
Editor::Editor(std::string filename) : x(0), y(0),
|
|
buffer(std::make_unique<Buffer>()), mode_(Mode::EDIT),
|
|
filename(filename), offset(0), voffset(0), lineMode(LineMode::RELATIVE),
|
|
history(History()), inComment(false) {
|
|
this->modes.emplace(Mode::INSERT, std::make_unique<modes::Insert>(*this));
|
|
this->modes.emplace(Mode::EDIT, std::make_unique<modes::Edit>(*this));
|
|
this->modes.emplace(Mode::QUIT, std::make_unique<modes::Quit>(*this));
|
|
this->modes.emplace(Mode::SAVE, std::make_unique<modes::Save>(*this));
|
|
|
|
this->overlay = newwin(LINES * 0.9, COLS * 0.9, (LINES * 0.1f) / 2.0f, (COLS * 0.1f) / 2.0f);
|
|
box(this->overlay, 0, 0);
|
|
|
|
if (!this->load()) {
|
|
std::cerr << "Could not open file: '" << this->filename << "', creating it on save.\n";
|
|
this->buffer->insert("");
|
|
}
|
|
}
|
|
|
|
bool Editor::load() {
|
|
if (this->filename == "") {
|
|
this->filename = "unbenannt";
|
|
|
|
return false;
|
|
}
|
|
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 c) {
|
|
this->modes.at(this->mode_)->input(c);
|
|
}
|
|
|
|
void Editor::render() {
|
|
long linenumber = this->offset;
|
|
this->vspace = this->lineMode == LineMode::RELATIVE || this->lineMode == LineMode::NUMBERS ?
|
|
Editor::Digits(this->buffer->linebuffer().size()) + 2 : 0;
|
|
clear();
|
|
for (int i = this->offset; i < LINES - 1 + this->offset; i++) {
|
|
long ln;
|
|
switch (this->lineMode) {
|
|
case LineMode::RELATIVE:
|
|
ln = static_cast<long>(std::sqrt(std::pow(static_cast<double>(this->y - linenumber), 2)));
|
|
ln = ln == 0 ? linenumber : ln;
|
|
break;
|
|
case LineMode::NUMBERS:
|
|
ln = linenumber;
|
|
break;
|
|
}
|
|
|
|
if(i >= this->buffer->linebuffer().size()) {
|
|
move(i - this->offset, 0);
|
|
clrtoeol();
|
|
}
|
|
else {
|
|
std::string line = this->buffer->at(i);
|
|
Highlighter highlighter(line);
|
|
std::unordered_map<long, std::pair<long, ncurses::Colors>> hilist = highlighter.get();
|
|
long x = this->vspace;
|
|
long found = -1;
|
|
long len = -1;
|
|
|
|
if (this->lineMode != LineMode::NONE) {
|
|
std::string label = std::string(x - Editor::Digits(ln) - 1, ' ');
|
|
label += std::to_string(ln) + ' ';
|
|
if (linenumber != this->y)
|
|
attron(COLOR_PAIR(ncurses::Colors::LINENUMBERS));
|
|
mvprintw(i - offset, 0, label.c_str());
|
|
if (linenumber != this->y)
|
|
attroff(COLOR_PAIR(ncurses::Colors::LINENUMBERS));
|
|
}
|
|
|
|
for (auto& car : line) {
|
|
if (car == '*' && this->lastChar == '/')
|
|
this->inComment = true;
|
|
if (car == '/' && this->lastChar == '*')
|
|
this->inComment = false;
|
|
if (hilist.find(x - this->vspace) != hilist.end()) {
|
|
found = x - this->vspace;
|
|
len = hilist.at(x - this->vspace).first;
|
|
}
|
|
if (found >= 0 && len >= 0) {
|
|
if (x - this->vspace >= found && x - this->vspace <= found + len - 1)
|
|
attron(COLOR_PAIR(hilist.at(found).second));
|
|
else if (x - this->vspace > found && x - this->vspace >= found + len) {
|
|
attron(COLOR_PAIR(ncurses::Colors::MAIN));
|
|
found = -1;
|
|
len = -1;
|
|
}
|
|
}
|
|
if (inComment)
|
|
attron(COLOR_PAIR(ncurses::Colors::COMMENTS));
|
|
mvaddch(i - this->offset, x , car);
|
|
attron(COLOR_PAIR(ncurses::Colors::MAIN));
|
|
this->lastChar = car;
|
|
x++;
|
|
}
|
|
//mvprintw(i - this->offset, 0, line.c_str());
|
|
}
|
|
clrtoeol();
|
|
linenumber++;
|
|
}
|
|
this->status();
|
|
move(static_cast<int>(this->y - this->offset), static_cast<int>(this->x + this->vspace));
|
|
this->renderOverlay();
|
|
|
|
}
|
|
|
|
void Editor::status() {
|
|
std::string status;
|
|
|
|
std::string position = std::to_string(this->y) + ", " + std::to_string(this->x) + " ";
|
|
status = this->modes.at(this->mode_)->status();
|
|
status += std::string(COLS - status.length() - position.length(), ' ');
|
|
status += position;
|
|
|
|
attron(COLOR_PAIR(ncurses::Colors::STATUSBAR));
|
|
mvprintw(LINES-1, 0, status.c_str());
|
|
attroff(COLOR_PAIR(ncurses::Colors::STATUSBAR));
|
|
}
|
|
|
|
long Editor::Digits(long number) {
|
|
return number > 0 ? static_cast<long>(log10 ((double) number) + 1) : 1;
|
|
}
|
|
|
|
} |