Add cancel buffer (to store cancelled operations.)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../decl.h"
|
#include "../decl.h"
|
||||||
#include "history.h"
|
#include "readonly.h"
|
||||||
#include "shard.h"
|
#include "shard.h"
|
||||||
|
|
||||||
namespace bed::internal::buffer {
|
namespace bed::internal::buffer {
|
||||||
@@ -25,7 +25,7 @@ struct GenericBuffer : ShardBuffer {
|
|||||||
~GenericBuffer();
|
~GenericBuffer();
|
||||||
|
|
||||||
void list_history(BEd &ctx);
|
void list_history(BEd &ctx);
|
||||||
HistoryBuffer *get_history(uint64_t version);
|
ReadonlyBuffer *get_history(uint64_t version);
|
||||||
void snapshot(std::string action);
|
void snapshot(std::string action);
|
||||||
bool undo(BEd &ctx);
|
bool undo(BEd &ctx);
|
||||||
bool redo(BEd &ctx);
|
bool redo(BEd &ctx);
|
||||||
|
|||||||
@@ -4,36 +4,38 @@
|
|||||||
#include "shard.h"
|
#include "shard.h"
|
||||||
|
|
||||||
namespace bed::internal::buffer {
|
namespace bed::internal::buffer {
|
||||||
struct HistoryBuffer : ShardBuffer {
|
struct ReadonlyBuffer : ShardBuffer {
|
||||||
HistoryBuffer(
|
bool useless = true;
|
||||||
|
|
||||||
|
ReadonlyBuffer(
|
||||||
std::string name, vase::Shard *root,
|
std::string name, vase::Shard *root,
|
||||||
const syntax::ParserSnapshot &snapshot
|
const syntax::ParserSnapshot &snapshot
|
||||||
) : ShardBuffer(std::move(name), root, snapshot, Kind::History) {}
|
) : ShardBuffer(std::move(name), root, snapshot, Kind::History) {}
|
||||||
|
|
||||||
bool waste() override {
|
bool waste() override {
|
||||||
return true;
|
return useless;
|
||||||
}
|
}
|
||||||
void load(BEd &, vase::Shard *) override {
|
void load(BEd &, vase::Shard *) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void set_filename(std::filesystem::path) override {}
|
void set_filename(std::filesystem::path) override {}
|
||||||
std::filesystem::path filename() override {
|
std::filesystem::path filename() override {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
void substitute(BEd &, uint64_t, uint64_t, std::string &, std::string &, std::string &) override {
|
void substitute(BEd &, uint64_t, uint64_t, std::string &, std::string &, std::string &) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void join(BEd &, uint64_t, uint64_t) override {
|
void join(BEd &, uint64_t, uint64_t) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void remove(BEd &, uint64_t, uint64_t) override {
|
void remove(BEd &, uint64_t, uint64_t) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void append(BEd &, vase::Shard *, uint64_t) override {
|
void append(BEd &, vase::Shard *, uint64_t) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void replace(BEd &, vase::Shard *, uint64_t, uint64_t) override {
|
void replace(BEd &, vase::Shard *, uint64_t, uint64_t) override {
|
||||||
throw ed_error("History buffers are read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace bed::internal::buffer
|
} // namespace bed::internal::buffer
|
||||||
+10
-1
@@ -171,7 +171,14 @@ void BEd::handle(std::string_view cmd, bool eof) {
|
|||||||
if (!b) {
|
if (!b) {
|
||||||
text = a;
|
text = a;
|
||||||
} else {
|
} else {
|
||||||
|
if (a) {
|
||||||
|
auto p = internal::syntax::make_parser(a, a->lines + 1, lang);
|
||||||
|
auto cancel_buf = new internal::buffer::ReadonlyBuffer("cancel", a, p);
|
||||||
|
internal::syntax::release(p);
|
||||||
|
buffers["cancel"] = cancel_buf;
|
||||||
|
cancel_buf->useless = false;
|
||||||
internal::vase::Shard::release(a);
|
internal::vase::Shard::release(a);
|
||||||
|
}
|
||||||
throw ed_error("Operation cancelled.");
|
throw ed_error("Operation cancelled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,13 +201,15 @@ void BEd::handle(std::string_view cmd, bool eof) {
|
|||||||
|
|
||||||
internal::buffer::Buffer &BEd::buffer(const std::string &name) {
|
internal::buffer::Buffer &BEd::buffer(const std::string &name) {
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
throw ed_error("can't have empty buffer name");
|
throw ed_error("Can't have empty buffer name");
|
||||||
{
|
{
|
||||||
auto it = buffers.find(name);
|
auto it = buffers.find(name);
|
||||||
if (it != buffers.end())
|
if (it != buffers.end())
|
||||||
return *it->second;
|
return *it->second;
|
||||||
}
|
}
|
||||||
constexpr std::string_view prefix = "history/";
|
constexpr std::string_view prefix = "history/";
|
||||||
|
if (name == "cancel")
|
||||||
|
throw ed_error("Cancel buffer empty.");
|
||||||
if (name.starts_with(prefix)) {
|
if (name.starts_with(prefix)) {
|
||||||
std::string_view path{name};
|
std::string_view path{name};
|
||||||
path.remove_prefix(prefix.size());
|
path.remove_prefix(prefix.size());
|
||||||
|
|||||||
@@ -72,21 +72,21 @@ void GenericBuffer::list_history(BEd &ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryBuffer *GenericBuffer::get_history(uint64_t version) {
|
ReadonlyBuffer *GenericBuffer::get_history(uint64_t version) {
|
||||||
uint64_t current = base_version + undo_stack.size();
|
uint64_t current = base_version + undo_stack.size();
|
||||||
if (version < base_version)
|
if (version < base_version)
|
||||||
throw ed_error("History version has been pruned.");
|
throw ed_error("History version has been pruned.");
|
||||||
if (version < current) {
|
if (version < current) {
|
||||||
auto &item = undo_stack[version - base_version];
|
auto &item = undo_stack[version - base_version];
|
||||||
return new HistoryBuffer(name, item.text, item.parse_state);
|
return new ReadonlyBuffer(name, item.text, item.parse_state);
|
||||||
}
|
}
|
||||||
if (version == current)
|
if (version == current)
|
||||||
return new HistoryBuffer(name, root, parse);
|
return new ReadonlyBuffer(name, root, parse);
|
||||||
uint64_t redo_offset = version - current - 1;
|
uint64_t redo_offset = version - current - 1;
|
||||||
if (redo_offset >= redo_stack.size())
|
if (redo_offset >= redo_stack.size())
|
||||||
throw ed_error("No such history version.");
|
throw ed_error("No such history version.");
|
||||||
auto &item = redo_stack[redo_stack.size() - 1 - redo_offset];
|
auto &item = redo_stack[redo_stack.size() - 1 - redo_offset];
|
||||||
return new HistoryBuffer(name, item.text, item.parse_state);
|
return new ReadonlyBuffer(name, item.text, item.parse_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericBuffer::snapshot(std::string action_) {
|
void GenericBuffer::snapshot(std::string action_) {
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ void Parser::locator(AddressPromise &addr) {
|
|||||||
token(io::Token::AddressSymbol);
|
token(io::Token::AddressSymbol);
|
||||||
advance();
|
advance();
|
||||||
end_token();
|
end_token();
|
||||||
|
token(io::Token::Number);
|
||||||
addr.base = AddressPromise::Current{};
|
addr.base = AddressPromise::Current{};
|
||||||
uint16_t j = 0;
|
uint16_t j = 0;
|
||||||
uint64_t num = 0;
|
uint64_t num = 0;
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ std::pair<vase::Shard *, bool> TextMode::run_terminal() {
|
|||||||
cursor.col = byte_column(previous.line, wanted);
|
cursor.col = byte_column(previous.line, wanted);
|
||||||
} break;
|
} break;
|
||||||
case io::KeyEvent::SpecialKey::DOWN: {
|
case io::KeyEvent::SpecialKey::DOWN: {
|
||||||
if (cursor.row + 1 >= vase->lines)
|
if (cursor.row >= vase->lines)
|
||||||
break;
|
break;
|
||||||
vase::Iterator current(vase, cursor.row, Direction::Forward);
|
vase::Iterator current(vase, cursor.row, Direction::Forward);
|
||||||
if (!current.next())
|
if (!current.next())
|
||||||
@@ -294,7 +294,7 @@ std::pair<vase::Shard *, bool> TextMode::run_terminal() {
|
|||||||
if (!it.next())
|
if (!it.next())
|
||||||
throw ed_error("Invalid cursor position.");
|
throw ed_error("Invalid cursor position.");
|
||||||
next.col = next_cluster(it.line, cursor.col);
|
next.col = next_cluster(it.line, cursor.col);
|
||||||
} else if (cursor.row + 1 < vase->lines) {
|
} else if (cursor.row < vase->lines) {
|
||||||
++next.row;
|
++next.row;
|
||||||
next.col = 0;
|
next.col = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user