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 remove(BEd &ctx, uint64_t start_line, uint64_t end_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 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;
|
||||
|
||||
@@ -43,6 +43,7 @@ struct Buffer {
|
||||
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 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 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;
|
||||
|
||||
@@ -28,6 +28,7 @@ struct GenericBuffer : Buffer {
|
||||
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 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 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;
|
||||
|
||||
@@ -22,7 +22,7 @@ struct MarksEngine {
|
||||
continue;
|
||||
if (marks[i].number == UINT64_MAX)
|
||||
continue;
|
||||
if (marks[i].number >= start)
|
||||
if (marks[i].number > start)
|
||||
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 *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 *copy(Shard *root, uint64_t start, uint64_t end);
|
||||
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) {
|
||||
if (!text)
|
||||
return;
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = line + 1;
|
||||
ctx.prev().end = line + text->lines + 1;
|
||||
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)
|
||||
parser->insert(root, ctx.prev().start, ctx.prev().end);
|
||||
parser->insert(root, line, text->lines + 1);
|
||||
state = Modified;
|
||||
}
|
||||
|
||||
@@ -72,6 +74,33 @@ void GenericBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
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) {
|
||||
root = vase::join(root, start_line, end_line);
|
||||
ctx.prev().buffername = name;
|
||||
@@ -107,9 +136,9 @@ void GenericBuffer::substitute(
|
||||
parser->erase(line, old_lines);
|
||||
}
|
||||
if (new_lines) {
|
||||
ctx.marks.insert(name, line, line + new_lines - 1);
|
||||
ctx.marks.insert(name, line, line + new_lines);
|
||||
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) {
|
||||
ctx.prev().buffername = name;
|
||||
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);
|
||||
s = vase::insert(&ctx.append, s, text, line);
|
||||
clip_write(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) {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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) {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
s = vase::join(s, start_line, end_line);
|
||||
|
||||
@@ -14,7 +14,13 @@ void Function::register_extented(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
const auto first = path.find_first_not_of(" \t");
|
||||
const auto last = path.find_last_not_of(" \t");
|
||||
@@ -46,7 +52,13 @@ void Function::register_extented(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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];
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
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
|
||||
|
||||
+183
-33
@@ -38,7 +38,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".",
|
||||
.accept_zero = true,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).append(ctx, text, addr.number);
|
||||
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
||||
@@ -56,10 +62,15 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).remove(ctx, addr.start, addr.end);
|
||||
ctx.buffer(addr.buffername).append(ctx, text, addr.start - 1);
|
||||
ctx.buffer(addr.buffername).replace(ctx, text, addr.start, addr.end);
|
||||
ctx.current() = {ctx.prev().buffername, ctx.prev().end};
|
||||
vase::Shard::release(text);
|
||||
}
|
||||
@@ -75,7 +86,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).remove(ctx, addr.start, addr.end);
|
||||
ctx.current() = {addr.buffername, addr.start};
|
||||
@@ -92,7 +109,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &arg,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<std::string>(addr_);
|
||||
auto &buf = ctx.buffer(addr);
|
||||
if (buf.state == buffer::Buffer::Modified) {
|
||||
@@ -136,7 +159,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &arg,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<std::string>(addr_);
|
||||
auto &buf = ctx.buffer(addr);
|
||||
vase::Shard *s = nullptr;
|
||||
@@ -176,7 +205,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &arg,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<std::string>(addr_);
|
||||
auto &buf_ = ctx.buffer(addr);
|
||||
if (buf_.kind != buffer::Buffer::Kind::Generic)
|
||||
@@ -202,7 +237,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -217,7 +258,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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;
|
||||
if (ctx.help_mode)
|
||||
ctx.io.write_line(ctx.last_help);
|
||||
@@ -234,7 +281,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".",
|
||||
.accept_zero = true,
|
||||
.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_);
|
||||
if (addr.number)
|
||||
addr.number--;
|
||||
@@ -254,7 +307,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.+1",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).join(ctx, addr.start, addr.end);
|
||||
ctx.current() = {addr.buffername, addr.start};
|
||||
@@ -271,7 +330,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &arg,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<buffer::Line>(addr_);
|
||||
ctx.mark(std::get<char>(arg), addr);
|
||||
}
|
||||
@@ -287,7 +352,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).list_print(ctx, addr.start, addr.end);
|
||||
ctx.current() = {addr.buffername, addr.end};
|
||||
@@ -304,7 +375,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.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::Line>(arg_);
|
||||
if (arg.buffername == addr.buffername
|
||||
@@ -343,7 +420,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).number_print(ctx, addr.start, addr.end);
|
||||
ctx.current() = {addr.buffername, addr.end};
|
||||
@@ -360,7 +443,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".,.",
|
||||
.accept_zero = false,
|
||||
.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_);
|
||||
ctx.buffer(addr.buffername).print(ctx, addr.start, addr.end);
|
||||
ctx.current() = {addr.buffername, addr.end};
|
||||
@@ -377,7 +466,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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;
|
||||
if (ctx.prompt_mode && !ctx.prompt) {
|
||||
ctx.prompt = [](BEd &) { return "*"; };
|
||||
@@ -395,7 +490,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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;
|
||||
for (auto &[name, buffer] : ctx.buffers) {
|
||||
if (buffer->state == buffer::Buffer::Modified) {
|
||||
@@ -420,7 +521,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -435,7 +542,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "$",
|
||||
.accept_zero = true,
|
||||
.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 &buf = ctx.buffer(addr.buffername);
|
||||
vase::Shard *s = nullptr;
|
||||
@@ -476,7 +589,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.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<RegexArg>(arg_);
|
||||
if (arg.expression == "")
|
||||
@@ -509,7 +628,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.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::Line>(arg_);
|
||||
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);
|
||||
vase::Shard::release(text);
|
||||
} catch (...) {
|
||||
if (!addr.start) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
ctx.buffer(addr.buffername).append(ctx, text, --addr.start);
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
@@ -539,7 +659,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "0,$",
|
||||
.accept_zero = true,
|
||||
.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 &buf = ctx.buffer(addr.buffername);
|
||||
vase::Shard *text;
|
||||
@@ -584,7 +710,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "$",
|
||||
.accept_zero = true,
|
||||
.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_);
|
||||
if (addr.start == addr.end)
|
||||
ctx.io.write_line(std::format(":{}:{}", addr.buffername, addr.start));
|
||||
@@ -604,7 +736,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.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> *) {
|
||||
.handle = [](
|
||||
BEd &ctx,
|
||||
const buffer::Address &addr_,
|
||||
vase::Shard *,
|
||||
const Argument &arg_,
|
||||
std::vector<buffer::Line> *
|
||||
) {
|
||||
auto &addr = std::get<std::string>(addr_);
|
||||
auto filename = ctx.buffer(addr).filename();
|
||||
auto &arg = std::get<ShellArg>(arg_);
|
||||
@@ -624,7 +762,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = ".+1",
|
||||
.accept_zero = true,
|
||||
.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_);
|
||||
if (addr.number != 0)
|
||||
ctx.buffer(addr.buffername).print(ctx, addr.number, addr.number);
|
||||
@@ -639,7 +783,13 @@ void Function::register_posix(BEd &ctx) {
|
||||
.default_address = "",
|
||||
.accept_zero = false,
|
||||
.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;
|
||||
for (auto &[name, buffer] : ctx.buffers) {
|
||||
if (buffer->state == buffer::Buffer::Modified) {
|
||||
|
||||
@@ -123,9 +123,14 @@ std::pair<vase::Shard *, bool> TextMode::run() {
|
||||
cursor = cmd.size();
|
||||
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;
|
||||
bed.io.move_cursor(last_row, 1);
|
||||
bed.io.write("\n", 1);
|
||||
|
||||
@@ -173,6 +173,8 @@ Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line) {
|
||||
Shard::retain(text);
|
||||
return text;
|
||||
}
|
||||
if (!text)
|
||||
return root;
|
||||
if (line > root->lines + 1)
|
||||
throw ed_error("line out of range");
|
||||
Shard::retain(text);
|
||||
@@ -201,6 +203,34 @@ Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line) {
|
||||
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) {
|
||||
if (!start || !end)
|
||||
throw ed_error("Invalid range.");
|
||||
|
||||
Reference in New Issue
Block a user