Add x function and other bug fixes.
This commit is contained in:
@@ -24,6 +24,7 @@ struct ClipBuffer : Buffer {
|
|||||||
void join(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void join(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void append(BEd &ctx, vase::Shard *text, uint64_t line) override;
|
void append(BEd &ctx, vase::Shard *text, uint64_t line) override;
|
||||||
|
void replace(BEd &ctx, vase::Shard *text, uint64_t start_line, uint64_t end_line) override;
|
||||||
void print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ struct Buffer {
|
|||||||
virtual void join(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
virtual void join(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
virtual void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
virtual void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
virtual void append(BEd &ctx, vase::Shard *text, uint64_t line) = 0;
|
virtual void append(BEd &ctx, vase::Shard *text, uint64_t line) = 0;
|
||||||
|
virtual void replace(BEd &ctx, vase::Shard *text, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
virtual void print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
virtual void print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
virtual void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
virtual void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
virtual void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
virtual void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) = 0;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct GenericBuffer : Buffer {
|
|||||||
void join(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void join(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void remove(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void append(BEd &ctx, vase::Shard *text, uint64_t line) override;
|
void append(BEd &ctx, vase::Shard *text, uint64_t line) override;
|
||||||
|
void replace(BEd &ctx, vase::Shard *text, uint64_t start_line, uint64_t end_line) override;
|
||||||
void print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
void list_print(BEd &ctx, uint64_t start_line, uint64_t end_line) override;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ struct MarksEngine {
|
|||||||
continue;
|
continue;
|
||||||
if (marks[i].number == UINT64_MAX)
|
if (marks[i].number == UINT64_MAX)
|
||||||
continue;
|
continue;
|
||||||
if (marks[i].number >= start)
|
if (marks[i].number > start)
|
||||||
marks[i].number += count;
|
marks[i].number += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ std::string to_string(Shard *root, Range range);
|
|||||||
|
|
||||||
Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line);
|
Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line);
|
||||||
Shard *erase(Shard *root, uint64_t start, uint64_t end);
|
Shard *erase(Shard *root, uint64_t start, uint64_t end);
|
||||||
|
Shard *replace(Shard *root, Shard *text, uint64_t start, uint64_t end);
|
||||||
Shard *join(Shard *root, uint64_t start, uint64_t end);
|
Shard *join(Shard *root, uint64_t start, uint64_t end);
|
||||||
Shard *copy(Shard *root, uint64_t start, uint64_t end);
|
Shard *copy(Shard *root, uint64_t start, uint64_t end);
|
||||||
void write_file(std::filesystem::path path, Shard *text);
|
void write_file(std::filesystem::path path, Shard *text);
|
||||||
|
|||||||
@@ -51,13 +51,15 @@ std::filesystem::path GenericBuffer::filename() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void GenericBuffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
void GenericBuffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
||||||
|
if (!text)
|
||||||
|
return;
|
||||||
ctx.prev().buffername = name;
|
ctx.prev().buffername = name;
|
||||||
ctx.prev().start = line + 1;
|
ctx.prev().start = line + 1;
|
||||||
ctx.prev().end = line + text->lines + 1;
|
ctx.prev().end = line + text->lines + 1;
|
||||||
root = vase::insert(&ctx.append, root, text, line);
|
root = vase::insert(&ctx.append, root, text, line);
|
||||||
ctx.marks.insert(name, ctx.prev().start, ctx.prev().end);
|
ctx.marks.insert(name, line, text->lines + 1);
|
||||||
if (parser)
|
if (parser)
|
||||||
parser->insert(root, ctx.prev().start, ctx.prev().end);
|
parser->insert(root, line, text->lines + 1);
|
||||||
state = Modified;
|
state = Modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +74,33 @@ void GenericBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
|||||||
state = Modified;
|
state = Modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericBuffer::replace(BEd &ctx, vase::Shard *text, uint64_t start_line, uint64_t end_line) {
|
||||||
|
if (!text) {
|
||||||
|
remove(ctx, start_line, end_line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.prev().buffername = name;
|
||||||
|
ctx.prev().start = start_line;
|
||||||
|
ctx.prev().end = start_line + text->lines;
|
||||||
|
uint64_t new_count = text->lines + 1;
|
||||||
|
uint64_t old_count = end_line - start_line + 1;
|
||||||
|
root = vase::replace(root, text, start_line, end_line);
|
||||||
|
if (parser) {
|
||||||
|
parser->begin_edit();
|
||||||
|
parser->erase(start_line, old_count);
|
||||||
|
parser->insert(start_line, new_count);
|
||||||
|
parser->end_edit(root);
|
||||||
|
}
|
||||||
|
if (new_count > old_count) {
|
||||||
|
uint64_t diff = new_count - old_count;
|
||||||
|
ctx.marks.insert(name, end_line, diff);
|
||||||
|
} else if (new_count < old_count) {
|
||||||
|
uint64_t diff = old_count - new_count;
|
||||||
|
ctx.marks.collapse(name, start_line + new_count - 1, diff);
|
||||||
|
}
|
||||||
|
state = Modified;
|
||||||
|
}
|
||||||
|
|
||||||
void GenericBuffer::join(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
void GenericBuffer::join(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||||
root = vase::join(root, start_line, end_line);
|
root = vase::join(root, start_line, end_line);
|
||||||
ctx.prev().buffername = name;
|
ctx.prev().buffername = name;
|
||||||
@@ -107,9 +136,9 @@ void GenericBuffer::substitute(
|
|||||||
parser->erase(line, old_lines);
|
parser->erase(line, old_lines);
|
||||||
}
|
}
|
||||||
if (new_lines) {
|
if (new_lines) {
|
||||||
ctx.marks.insert(name, line, line + new_lines - 1);
|
ctx.marks.insert(name, line, line + new_lines);
|
||||||
if (parser)
|
if (parser)
|
||||||
parser->insert(line, line + new_lines - 1);
|
parser->insert(line, new_lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ std::filesystem::path ClipBuffer::filename() {
|
|||||||
void ClipBuffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
void ClipBuffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
||||||
ctx.prev().buffername = name;
|
ctx.prev().buffername = name;
|
||||||
ctx.prev().start = line + 1;
|
ctx.prev().start = line + 1;
|
||||||
ctx.prev().end = line + text->lines + 1;
|
ctx.prev().end = line + (text ? text->lines + 1 : 0);
|
||||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||||
s = vase::insert(&ctx.append, s, text, line);
|
s = vase::insert(&ctx.append, s, text, line);
|
||||||
clip_write(s);
|
clip_write(s);
|
||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
ctx.marks.insert(name, ctx.prev().start, ctx.prev().end);
|
ctx.marks.insert(name, line, text->lines + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
void ClipBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||||
@@ -73,6 +73,30 @@ void ClipBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
|||||||
ctx.marks.erase(name, start_line, end_line - start_line + 1);
|
ctx.marks.erase(name, start_line, end_line - start_line + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClipBuffer::replace(BEd &ctx, vase::Shard *text, uint64_t start_line, uint64_t end_line) {
|
||||||
|
if (!text) {
|
||||||
|
remove(ctx, start_line, end_line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.prev().buffername = name;
|
||||||
|
ctx.prev().start = start_line;
|
||||||
|
ctx.prev().end = start_line + text->lines;
|
||||||
|
uint64_t new_count = text->lines + 1;
|
||||||
|
uint64_t old_count = end_line - start_line + 1;
|
||||||
|
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||||
|
s = vase::replace(s, text, start_line, end_line);
|
||||||
|
clip_write(s);
|
||||||
|
vase::Shard::release(s);
|
||||||
|
if (new_count > old_count) {
|
||||||
|
uint64_t diff = new_count - old_count;
|
||||||
|
ctx.marks.insert(name, end_line, diff);
|
||||||
|
} else if (new_count < old_count) {
|
||||||
|
uint64_t diff = old_count - new_count;
|
||||||
|
ctx.marks.collapse(name, start_line + new_count - 1, diff);
|
||||||
|
}
|
||||||
|
state = Modified;
|
||||||
|
}
|
||||||
|
|
||||||
void ClipBuffer::join(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
void ClipBuffer::join(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||||
s = vase::join(s, start_line, end_line);
|
s = vase::join(s, start_line, end_line);
|
||||||
|
|||||||
@@ -14,7 +14,13 @@ void Function::register_extented(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &, const buffer::Address &, vase::Shard *, const Argument &arg_, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto path = std::get<std::string>(arg_);
|
auto path = std::get<std::string>(arg_);
|
||||||
const auto first = path.find_first_not_of(" \t");
|
const auto first = path.find_first_not_of(" \t");
|
||||||
const auto last = path.find_last_not_of(" \t");
|
const auto last = path.find_last_not_of(" \t");
|
||||||
@@ -46,7 +52,13 @@ void Function::register_extented(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
if (!getcwd(cwd, sizeof(cwd)))
|
if (!getcwd(cwd, sizeof(cwd)))
|
||||||
throw ed_error("Can't determine current directory.");
|
throw ed_error("Can't determine current directory.");
|
||||||
@@ -54,5 +66,36 @@ void Function::register_extented(BEd &ctx) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
ctx.functions.insert(
|
||||||
|
"x",
|
||||||
|
Function{
|
||||||
|
.address_kind = Function::AddressKind::Range,
|
||||||
|
.argument_kind = Function::ArgumentKind::Range,
|
||||||
|
.input_mode = Function::InputMode::None,
|
||||||
|
.desc = "Exchange a range of lines for another.",
|
||||||
|
.default_address = ".,.",
|
||||||
|
.accept_zero = false,
|
||||||
|
.pre_text_mode = nullptr,
|
||||||
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
|
auto arg = std::get<buffer::Range>(arg_);
|
||||||
|
auto text = ctx.buffer(addr.buffername).copy(addr.start, addr.end);
|
||||||
|
try {
|
||||||
|
ctx.buffer(arg.buffername).replace(ctx, text, arg.start, arg.end);
|
||||||
|
vase::Shard::release(text);
|
||||||
|
} catch (...) {
|
||||||
|
vase::Shard::release(text);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
ctx.current() = {arg.buffername, arg.start + addr.end - addr.start + 1};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} // namespace bed::internal::functions
|
} // namespace bed::internal::functions
|
||||||
|
|||||||
+183
-33
@@ -38,7 +38,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".",
|
.default_address = ".",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *text, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *text,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Line>(addr_);
|
auto addr = std::get<buffer::Line>(addr_);
|
||||||
ctx.buffer(addr.buffername).append(ctx, text, addr.number);
|
ctx.buffer(addr.buffername).append(ctx, text, addr.number);
|
||||||
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
||||||
@@ -56,10 +62,15 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *text, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *text,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).remove(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).replace(ctx, text, addr.start, addr.end);
|
||||||
ctx.buffer(addr.buffername).append(ctx, text, addr.start - 1);
|
|
||||||
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
||||||
vase::Shard::release(text);
|
vase::Shard::release(text);
|
||||||
}
|
}
|
||||||
@@ -75,7 +86,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).remove(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).remove(ctx, addr.start, addr.end);
|
||||||
ctx.current() = {addr.buffername, addr.start};
|
ctx.current() = {addr.buffername, addr.start};
|
||||||
@@ -92,7 +109,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<std::string>(addr_);
|
auto &addr = std::get<std::string>(addr_);
|
||||||
auto &buf = ctx.buffer(addr);
|
auto &buf = ctx.buffer(addr);
|
||||||
if (buf.state == buffer::Buffer::Modified) {
|
if (buf.state == buffer::Buffer::Modified) {
|
||||||
@@ -136,7 +159,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<std::string>(addr_);
|
auto &addr = std::get<std::string>(addr_);
|
||||||
auto &buf = ctx.buffer(addr);
|
auto &buf = ctx.buffer(addr);
|
||||||
vase::Shard *s = nullptr;
|
vase::Shard *s = nullptr;
|
||||||
@@ -176,7 +205,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<std::string>(addr_);
|
auto &addr = std::get<std::string>(addr_);
|
||||||
auto &buf_ = ctx.buffer(addr);
|
auto &buf_ = ctx.buffer(addr);
|
||||||
if (buf_.kind != buffer::Buffer::Kind::Generic)
|
if (buf_.kind != buffer::Buffer::Kind::Generic)
|
||||||
@@ -202,7 +237,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
ctx.io.write_line(ctx.last_help);
|
ctx.io.write_line(ctx.last_help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +258,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
ctx.help_mode = !ctx.help_mode;
|
ctx.help_mode = !ctx.help_mode;
|
||||||
if (ctx.help_mode)
|
if (ctx.help_mode)
|
||||||
ctx.io.write_line(ctx.last_help);
|
ctx.io.write_line(ctx.last_help);
|
||||||
@@ -234,7 +281,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".",
|
.default_address = ".",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *text, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *text,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Line>(addr_);
|
auto addr = std::get<buffer::Line>(addr_);
|
||||||
if (addr.number)
|
if (addr.number)
|
||||||
addr.number--;
|
addr.number--;
|
||||||
@@ -254,7 +307,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.+1",
|
.default_address = ".,.+1",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).join(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).join(ctx, addr.start, addr.end);
|
||||||
ctx.current() = {addr.buffername, addr.start};
|
ctx.current() = {addr.buffername, addr.start};
|
||||||
@@ -271,7 +330,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".",
|
.default_address = ".",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<buffer::Line>(addr_);
|
auto &addr = std::get<buffer::Line>(addr_);
|
||||||
ctx.mark(std::get<char>(arg), addr);
|
ctx.mark(std::get<char>(arg), addr);
|
||||||
}
|
}
|
||||||
@@ -287,7 +352,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).list_print(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).list_print(ctx, addr.start, addr.end);
|
||||||
ctx.current() = {addr.buffername, addr.end};
|
ctx.current() = {addr.buffername, addr.end};
|
||||||
@@ -304,7 +375,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg_, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
auto arg = std::get<buffer::Line>(arg_);
|
auto arg = std::get<buffer::Line>(arg_);
|
||||||
if (arg.buffername == addr.buffername
|
if (arg.buffername == addr.buffername
|
||||||
@@ -343,7 +420,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).number_print(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).number_print(ctx, addr.start, addr.end);
|
||||||
ctx.current() = {addr.buffername, addr.end};
|
ctx.current() = {addr.buffername, addr.end};
|
||||||
@@ -360,7 +443,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
ctx.buffer(addr.buffername).print(ctx, addr.start, addr.end);
|
ctx.buffer(addr.buffername).print(ctx, addr.start, addr.end);
|
||||||
ctx.current() = {addr.buffername, addr.end};
|
ctx.current() = {addr.buffername, addr.end};
|
||||||
@@ -377,7 +466,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
ctx.prompt_mode = !ctx.prompt_mode;
|
ctx.prompt_mode = !ctx.prompt_mode;
|
||||||
if (ctx.prompt_mode && !ctx.prompt) {
|
if (ctx.prompt_mode && !ctx.prompt) {
|
||||||
ctx.prompt = [](BEd &) { return "*"; };
|
ctx.prompt = [](BEd &) { return "*"; };
|
||||||
@@ -395,7 +490,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
std::string modified_buffers;
|
std::string modified_buffers;
|
||||||
for (auto &[name, buffer] : ctx.buffers) {
|
for (auto &[name, buffer] : ctx.buffers) {
|
||||||
if (buffer->state == buffer::Buffer::Modified) {
|
if (buffer->state == buffer::Buffer::Modified) {
|
||||||
@@ -420,7 +521,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
throw fatal_error("Force Quitting", 0);
|
throw fatal_error("Force Quitting", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,7 +542,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "$",
|
.default_address = "$",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<buffer::Line>(addr_);
|
auto &addr = std::get<buffer::Line>(addr_);
|
||||||
auto &buf = ctx.buffer(addr.buffername);
|
auto &buf = ctx.buffer(addr.buffername);
|
||||||
vase::Shard *s = nullptr;
|
vase::Shard *s = nullptr;
|
||||||
@@ -476,7 +589,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg_, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<buffer::Range>(addr_);
|
auto &addr = std::get<buffer::Range>(addr_);
|
||||||
auto arg = std::get<RegexArg>(arg_);
|
auto arg = std::get<RegexArg>(arg_);
|
||||||
if (arg.expression == "")
|
if (arg.expression == "")
|
||||||
@@ -509,7 +628,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".,.",
|
.default_address = ".,.",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg_, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
auto arg = std::get<buffer::Line>(arg_);
|
auto arg = std::get<buffer::Line>(arg_);
|
||||||
auto text = ctx.buffer(addr.buffername).copy(addr.start, addr.end);
|
auto text = ctx.buffer(addr.buffername).copy(addr.start, addr.end);
|
||||||
@@ -517,11 +642,6 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
ctx.buffer(arg.buffername).append(ctx, text, arg.number);
|
ctx.buffer(arg.buffername).append(ctx, text, arg.number);
|
||||||
vase::Shard::release(text);
|
vase::Shard::release(text);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (!addr.start) {
|
|
||||||
vase::Shard::release(text);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
ctx.buffer(addr.buffername).append(ctx, text, --addr.start);
|
|
||||||
vase::Shard::release(text);
|
vase::Shard::release(text);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@@ -539,7 +659,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "0,$",
|
.default_address = "0,$",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Range>(addr_);
|
auto addr = std::get<buffer::Range>(addr_);
|
||||||
auto &buf = ctx.buffer(addr.buffername);
|
auto &buf = ctx.buffer(addr.buffername);
|
||||||
vase::Shard *text;
|
vase::Shard *text;
|
||||||
@@ -584,7 +710,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "$",
|
.default_address = "$",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<buffer::Range>(addr_);
|
auto &addr = std::get<buffer::Range>(addr_);
|
||||||
if (addr.start == addr.end)
|
if (addr.start == addr.end)
|
||||||
ctx.io.write_line(std::format(":{}:{}", addr.buffername, addr.start));
|
ctx.io.write_line(std::format(":{}:{}", addr.buffername, addr.start));
|
||||||
@@ -604,7 +736,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &arg_, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &arg_,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto &addr = std::get<std::string>(addr_);
|
auto &addr = std::get<std::string>(addr_);
|
||||||
auto filename = ctx.buffer(addr).filename();
|
auto filename = ctx.buffer(addr).filename();
|
||||||
auto &arg = std::get<ShellArg>(arg_);
|
auto &arg = std::get<ShellArg>(arg_);
|
||||||
@@ -624,7 +762,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = ".+1",
|
.default_address = ".+1",
|
||||||
.accept_zero = true,
|
.accept_zero = true,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &addr_, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &addr_,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
auto addr = std::get<buffer::Line>(addr_);
|
auto addr = std::get<buffer::Line>(addr_);
|
||||||
if (addr.number != 0)
|
if (addr.number != 0)
|
||||||
ctx.buffer(addr.buffername).print(ctx, addr.number, addr.number);
|
ctx.buffer(addr.buffername).print(ctx, addr.number, addr.number);
|
||||||
@@ -639,7 +783,13 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.default_address = "",
|
.default_address = "",
|
||||||
.accept_zero = false,
|
.accept_zero = false,
|
||||||
.pre_text_mode = nullptr,
|
.pre_text_mode = nullptr,
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
.handle = [](
|
||||||
|
BEd &ctx,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
std::string modified_buffers;
|
std::string modified_buffers;
|
||||||
for (auto &[name, buffer] : ctx.buffers) {
|
for (auto &[name, buffer] : ctx.buffers) {
|
||||||
if (buffer->state == buffer::Buffer::Modified) {
|
if (buffer->state == buffer::Buffer::Modified) {
|
||||||
|
|||||||
@@ -123,9 +123,14 @@ std::pair<vase::Shard *, bool> TextMode::run() {
|
|||||||
cursor = cmd.size();
|
cursor = cmd.size();
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
if (cmd.size() == 2 && cmd.compare(0, 2, ".\n") == 0) {
|
||||||
|
cmd.clear();
|
||||||
|
cursor = 0;
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t total_lines = 1 + std::count(cmd.begin(), cmd.end(), '\n');
|
size_t total_lines = cmd.size() ? 1 + std::count(cmd.begin(), cmd.end(), '\n') : 0;
|
||||||
uint16_t last_row = start + total_lines;
|
uint16_t last_row = start + total_lines;
|
||||||
bed.io.move_cursor(last_row, 1);
|
bed.io.move_cursor(last_row, 1);
|
||||||
bed.io.write("\n", 1);
|
bed.io.write("\n", 1);
|
||||||
|
|||||||
@@ -173,6 +173,8 @@ Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line) {
|
|||||||
Shard::retain(text);
|
Shard::retain(text);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
if (!text)
|
||||||
|
return root;
|
||||||
if (line > root->lines + 1)
|
if (line > root->lines + 1)
|
||||||
throw ed_error("line out of range");
|
throw ed_error("line out of range");
|
||||||
Shard::retain(text);
|
Shard::retain(text);
|
||||||
@@ -201,6 +203,34 @@ Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shard *replace(Shard *root, Shard *text, uint64_t start, uint64_t end) {
|
||||||
|
if (!start || !end)
|
||||||
|
throw ed_error("Invalid range.");
|
||||||
|
start--;
|
||||||
|
end--;
|
||||||
|
if (!root)
|
||||||
|
throw ed_error("line range out of bounds");
|
||||||
|
uint64_t line_count = root->lines + 1;
|
||||||
|
if (start > end || end >= line_count)
|
||||||
|
throw ed_error("line range out of bounds");
|
||||||
|
uint64_t start_offset = offset_of(root, start);
|
||||||
|
uint64_t end_offset =
|
||||||
|
(end + 1 == line_count)
|
||||||
|
? root->length
|
||||||
|
: offset_of(root, end + 1) - 1;
|
||||||
|
auto [left, rest] = Shard::split(root, start_offset);
|
||||||
|
auto [middle, right] = Shard::split(rest, end_offset - start_offset);
|
||||||
|
Shard *a = Shard::concat(left, text);
|
||||||
|
Shard *new_root = Shard::concat(a, right);
|
||||||
|
Shard::release(left);
|
||||||
|
Shard::release(rest);
|
||||||
|
Shard::release(middle);
|
||||||
|
Shard::release(right);
|
||||||
|
Shard::release(a);
|
||||||
|
Shard::release(root);
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
Shard *erase(Shard *root, uint64_t start, uint64_t end) {
|
Shard *erase(Shard *root, uint64_t start, uint64_t end) {
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
throw ed_error("Invalid range.");
|
throw ed_error("Invalid range.");
|
||||||
|
|||||||
Reference in New Issue
Block a user