added history (undo/redo)

development
Michael Ochmann 8 years ago
parent f5a4a896a6
commit c2e922344d
  1. 8
      CHANGELOG.md
  2. 25
      main.cpp
  3. 3
      src/Editor.cpp
  4. 14
      src/Editor.hpp
  5. 6
      src/Highlighter.cpp
  6. 42
      src/History.hpp
  7. 48
      src/modes/Edit.cpp

@ -1,4 +1,10 @@
# 0.0.1
# v0.0.4
Major improvements:
* Undo/redo capability in `edit` mode
* Linemodes: `numbers`, `relativenumbers`, `nonumbers`
# v0.0.1
Simple editor working. The editor is capable of
* Loading files

@ -1,3 +1,28 @@
/**
* Groove Editor
*
* Version 0.0.4
*
* Copyright (c) 2017 Michael Ochmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <iostream>
#include <ncurses/ncurses.hpp>
#include <Editor.hpp>

@ -8,7 +8,8 @@ namespace groove {
Editor::Editor(std::string filename) : x(0), y(0),
buffer(std::make_unique<Buffer>()), mode_(Mode::EDIT),
filename(filename), offset(0), lineMode(LineMode::NONE) {
filename(filename), offset(0), voffset(0), lineMode(LineMode::RELATIVE),
history(History()) {
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));

@ -1,13 +1,14 @@
#pragma once
#include <memory>
#include <unordered_map>
#include <Buffer.hpp>
#include <ncurses/ncurses.hpp>
#include <modes/Insert.hpp>
#include <modes/Edit.hpp>
#include <modes/Quit.hpp>
#include <modes/Save.hpp>
#include <unordered_map>
#include <History.hpp>
namespace groove {
@ -31,11 +32,14 @@ namespace groove {
friend class modes::Edit;
friend class modes::Quit;
friend class modes::Save;
friend class History;
private:
long x, y;
int offset;
int voffset;
long vspace;
char lastChar = 0;
History history;
LineMode lineMode;
std::unique_ptr<Buffer> buffer;
Mode mode_;
@ -65,10 +69,14 @@ namespace groove {
}
}
void right() {
if (this->x + 1 <= COLS && this->x + 1 <= this->buffer->linebuffer().at(this->y).length())
if (this->x + 1 <= this->buffer->linebuffer().at(this->y).length()) {
if (this->x + 1 <= COLS)
this->x++;
else
this->voffset++;
}
else {
if (this->y + 1 <= this->buffer->size()) {
if (this->y + 1 < this->buffer->size()) {
this->y++;
this->x = this->buffer->at(this->y).size();
}

@ -5,16 +5,16 @@
namespace groove {
std::vector<std::pair<std::regex, ncurses::Colors>> Highlighter::list = {
make_pair("(#[a-z]+ ?)(.*)", ncurses::Colors::ORANGE),
make_pair("([+-.<>,;=!:])", ncurses::Colors::CYAN),
make_pair("([\\{\\}\\[\\]\\(\\)])", ncurses::Colors::GREEN),
make_pair("(while|if|try|catch|void|this|namespace|private|public|protected|class|char|bool|unsigned|long|short|int|return)\\*?", ncurses::Colors::MAGENTA),
make_pair("(while|if|try|catch|void|this|else|namespace|private|public|protected|class|char|bool|unsigned|long|short|int|return)\\*?", ncurses::Colors::MAGENTA),
make_pair("([a-zA-Z_][a-zA-Z_0-9]+)::", ncurses::Colors::GREEN),
make_pair("::([a-zA-Z_][a-zA-Z_0-9]+)", ncurses::Colors::CYAN),
make_pair("\\.([a-zA-Z_][a-zA-Z_0-9]+)", ncurses::Colors::CYAN),
make_pair("\\\".*\\\"", ncurses::Colors::ORANGE),
make_pair("/\\*.*\\*//*", ncurses::Colors::ORANGE),
make_pair("(//.*)", ncurses::Colors::ORANGE),
make_pair("(#.*<.*>$)", ncurses::Colors::ORANGE)
make_pair("(//.*)", ncurses::Colors::ORANGE)
};
std::unordered_map<long, std::pair<long, ncurses::Colors>> groove::Highlighter::get() {

@ -2,40 +2,48 @@
#include <functional>
#include <memory>
#include <vector>
namespace groove {
struct HistoryNode {
std::shared_ptr<HistoryNode> last;
std::shared_ptr<HistoryNode> next;
std::function<void()> undo, redo;
HistoryNode(std::function<void()> undo, std::function<void()> redo,
std::shared_ptr<HistoryNode> last = nullptr,
std::shared_ptr<HistoryNode> next = nullptr) :
undo(undo), redo(redo), last(last), next(next) {}
HistoryNode(std::function<void()> undo, std::function<void()> redo) :
undo(std::move(undo)), redo(std::move(redo)) {}
};
class History {
private:
std::shared_ptr<HistoryNode> begin;
std::shared_ptr<HistoryNode> end;
std::unique_ptr<std::vector<HistoryNode>> history;
unsigned long pointer;
void cutTail() {
if (this->history->begin() == this->history->end() || this->pointer >= this->history->size())
return;
this->history->erase(this->history->begin() + this->pointer + 1, this->history->end());
}
public:
History() : begin(nullptr), end(nullptr) {}
void push(std::function<void()> undo, std::function<void()> redo) {
this->end->next = std::make_shared<HistoryNode>(undo, redo, this->end);
History() : history(std::make_unique<std::vector<HistoryNode>>()), pointer(0) {
this->push(HistoryNode([](){}, [](){}));
}
void pop() {
this->end = this->end->last;
void push(HistoryNode node) {
this->cutTail();
this->history->emplace_back(std::move(node));
this->pointer = this->history->size() - 1;
}
void undo() {
this->end->undo();
this->end = this->end->last;
if (this->pointer <= 0)
return;
this->history->at(this->pointer).undo();
this->pointer--;
}
void redo() {
this->end->redo();
if (this->pointer + 1 >= this->history->size())
return;
this->history->at(this->pointer + 1).redo();
this->pointer++;
}
};

@ -25,16 +25,51 @@ namespace groove {
this->editor.clipboard = this->editor.buffer->at(this->editor.y);
break;
case 'x':
this->editor.clipboard = this->editor.buffer->at(this->editor.y);
this->editor.buffer->remove(this->editor.y);
{
long y = this->editor.y;
std::string line = this->editor.buffer->at(y);
this->editor.history.push(
HistoryNode([this, y, line](){
this->editor.buffer->insert(line, y);
}, [this, y](){
this->editor.buffer->remove(y);
})
);
this->editor.clipboard = this->editor.buffer->at(y);
this->editor.buffer->remove(y);
}
break;
case 'v':
this->editor.buffer->insert(this->editor.clipboard, this->editor.y);
{
std::string clipboard = this->editor.clipboard;
long y = this->editor.y;
this->editor.history.push(
HistoryNode([this, y](){
this->editor.buffer->remove(y);
},[this, y, clipboard](){
this->editor.buffer->insert(clipboard, y);
this->editor.y = y;
this->editor.x = this->editor.buffer->at(y).size();
})
);
this->editor.buffer->insert(clipboard, y);
this->editor.y++;
this->editor.x = this->editor.buffer->at(this->editor.y).size();
this->editor.x = this->editor.buffer->at(y).size();
}
break;
case 'd':
{
long y = this->editor.y;
std::string line = this->editor.buffer->at(y);
this->editor.history.push(
HistoryNode([this, y, line](){
this->editor.buffer->insert(line, y);
}, [this, y, line](){
this->editor.buffer->remove(y);
})
);
this->editor.buffer->remove(this->editor.y);
}
break;
case 'l':
switch (this->editor.lineMode) {
@ -49,6 +84,11 @@ namespace groove {
break;
}
break;
case 'u':
this->editor.history.undo();
break;
case 'r':
this->editor.history.redo();
}
}
}

Loading…
Cancel
Save