From d6d3f3132614b513339aa44b6fc46e38710ad3b5 Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Tue, 8 Sep 2026 11:50:17 +0100 Subject: [PATCH] Add cancel buffer (to store cancelled operations.) --- include/internal/buffer/types/generic.h | 4 ++-- .../buffer/types/{history.h => readonly.h} | 20 ++++++++++--------- src/bed/run.cc | 13 ++++++++++-- src/internal/buffer/generic.cc | 8 ++++---- src/internal/parser/address.cc | 1 + src/internal/ui/text_mode/text_mode.cc | 4 ++-- 6 files changed, 31 insertions(+), 19 deletions(-) rename include/internal/buffer/types/{history.h => readonly.h} (67%) diff --git a/include/internal/buffer/types/generic.h b/include/internal/buffer/types/generic.h index a0aa133..f8c2c38 100644 --- a/include/internal/buffer/types/generic.h +++ b/include/internal/buffer/types/generic.h @@ -1,7 +1,7 @@ #pragma once #include "../decl.h" -#include "history.h" +#include "readonly.h" #include "shard.h" namespace bed::internal::buffer { @@ -25,7 +25,7 @@ struct GenericBuffer : ShardBuffer { ~GenericBuffer(); void list_history(BEd &ctx); - HistoryBuffer *get_history(uint64_t version); + ReadonlyBuffer *get_history(uint64_t version); void snapshot(std::string action); bool undo(BEd &ctx); bool redo(BEd &ctx); diff --git a/include/internal/buffer/types/history.h b/include/internal/buffer/types/readonly.h similarity index 67% rename from include/internal/buffer/types/history.h rename to include/internal/buffer/types/readonly.h index dc0f103..26eb198 100644 --- a/include/internal/buffer/types/history.h +++ b/include/internal/buffer/types/readonly.h @@ -4,36 +4,38 @@ #include "shard.h" namespace bed::internal::buffer { -struct HistoryBuffer : ShardBuffer { - HistoryBuffer( +struct ReadonlyBuffer : ShardBuffer { + bool useless = true; + + ReadonlyBuffer( std::string name, vase::Shard *root, const syntax::ParserSnapshot &snapshot ) : ShardBuffer(std::move(name), root, snapshot, Kind::History) {} bool waste() override { - return true; + return useless; } 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 {} std::filesystem::path filename() override { return {}; } 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 { - throw ed_error("History buffers are read-only."); + throw ed_error("This buffer is read-only."); } 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 { - 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 { - throw ed_error("History buffers are read-only."); + throw ed_error("This buffer is read-only."); } }; } // namespace bed::internal::buffer diff --git a/src/bed/run.cc b/src/bed/run.cc index 74d2085..b5caf0a 100644 --- a/src/bed/run.cc +++ b/src/bed/run.cc @@ -171,7 +171,14 @@ void BEd::handle(std::string_view cmd, bool eof) { if (!b) { text = a; } else { - internal::vase::Shard::release(a); + 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); + } 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) { 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); if (it != buffers.end()) return *it->second; } constexpr std::string_view prefix = "history/"; + if (name == "cancel") + throw ed_error("Cancel buffer empty."); if (name.starts_with(prefix)) { std::string_view path{name}; path.remove_prefix(prefix.size()); diff --git a/src/internal/buffer/generic.cc b/src/internal/buffer/generic.cc index 8815078..5d37fc3 100644 --- a/src/internal/buffer/generic.cc +++ b/src/internal/buffer/generic.cc @@ -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(); if (version < base_version) throw ed_error("History version has been pruned."); if (version < current) { 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) - return new HistoryBuffer(name, root, parse); + return new ReadonlyBuffer(name, root, parse); uint64_t redo_offset = version - current - 1; if (redo_offset >= redo_stack.size()) throw ed_error("No such history version."); 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_) { diff --git a/src/internal/parser/address.cc b/src/internal/parser/address.cc index 92a9eb1..61f2af5 100644 --- a/src/internal/parser/address.cc +++ b/src/internal/parser/address.cc @@ -188,6 +188,7 @@ void Parser::locator(AddressPromise &addr) { token(io::Token::AddressSymbol); advance(); end_token(); + token(io::Token::Number); addr.base = AddressPromise::Current{}; uint16_t j = 0; uint64_t num = 0; diff --git a/src/internal/ui/text_mode/text_mode.cc b/src/internal/ui/text_mode/text_mode.cc index 7ceb99a..84c4b98 100644 --- a/src/internal/ui/text_mode/text_mode.cc +++ b/src/internal/ui/text_mode/text_mode.cc @@ -272,7 +272,7 @@ std::pair TextMode::run_terminal() { cursor.col = byte_column(previous.line, wanted); } break; case io::KeyEvent::SpecialKey::DOWN: { - if (cursor.row + 1 >= vase->lines) + if (cursor.row >= vase->lines) break; vase::Iterator current(vase, cursor.row, Direction::Forward); if (!current.next()) @@ -294,7 +294,7 @@ std::pair TextMode::run_terminal() { if (!it.next()) throw ed_error("Invalid cursor position."); next.col = next_cluster(it.line, cursor.col); - } else if (cursor.row + 1 < vase->lines) { + } else if (cursor.row < vase->lines) { ++next.row; next.col = 0; } else {