Add clipboard buffer.
This commit is contained in:
+3
-3
@@ -28,6 +28,7 @@ BEd::BEd(std::vector<std::string> args, internal::io::IO &io)
|
||||
else
|
||||
prompt_mode = false;
|
||||
suppress_mode = suppress;
|
||||
buffers["clip"] = new internal::buffer::ClipBuffer("clip");
|
||||
try {
|
||||
if (file != "")
|
||||
handle(":default:E " + file, false);
|
||||
@@ -141,8 +142,7 @@ void BEd::handle(std::string_view cmd, bool eof) {
|
||||
temporary_current = false;
|
||||
for (auto it = buffers.begin(); it != buffers.end();) {
|
||||
internal::buffer::Buffer *buf = it->second;
|
||||
if (buf->save_path.empty()
|
||||
&& buf->root == nullptr) {
|
||||
if (buf->waste()) {
|
||||
delete buf;
|
||||
it = buffers.erase(it);
|
||||
} else {
|
||||
@@ -157,7 +157,7 @@ internal::buffer::Buffer &BEd::buffer(const std::string &name) {
|
||||
auto it = buffers.find(name);
|
||||
if (it != buffers.end())
|
||||
return *it->second;
|
||||
auto *buf = new internal::buffer::Buffer(name);
|
||||
auto *buf = new internal::buffer::GenericBuffer(name);
|
||||
buffers.emplace(name, buf);
|
||||
return *buf;
|
||||
}
|
||||
|
||||
+107
-18
@@ -2,31 +2,34 @@
|
||||
#include "bed.h"
|
||||
|
||||
namespace bed::internal::buffer {
|
||||
Buffer::Buffer(std::string name)
|
||||
: state(Unmodified), root(nullptr), name(name) {
|
||||
}
|
||||
|
||||
Buffer::~Buffer() {
|
||||
GenericBuffer::~GenericBuffer() {
|
||||
vase::Shard::release(root);
|
||||
}
|
||||
|
||||
uint64_t Buffer::lines() {
|
||||
bool GenericBuffer::waste() {
|
||||
return save_path.empty()
|
||||
&& root == nullptr;
|
||||
}
|
||||
|
||||
uint64_t GenericBuffer::lines() {
|
||||
if (root)
|
||||
return root->lines + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t Buffer::bytes() {
|
||||
uint64_t GenericBuffer::bytes() {
|
||||
if (root)
|
||||
return root->length + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buffer::load(BEd &ctx, vase::Shard *text) {
|
||||
void GenericBuffer::load(BEd &ctx, vase::Shard *text) {
|
||||
try {
|
||||
if (lines())
|
||||
ctx.marks.erase(name, 1, lines());
|
||||
vase::Shard::release(root);
|
||||
root = text;
|
||||
state = buffer::Buffer::Unmodified;
|
||||
state = buffer::GenericBuffer::Unmodified;
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
@@ -43,7 +46,61 @@ void Buffer::load(BEd &ctx, vase::Shard *text) {
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
||||
void GenericBuffer::load(BEd &ctx) {
|
||||
if (save_path.empty())
|
||||
throw ed_error("File cannot be implied.");
|
||||
load(ctx, save_path);
|
||||
}
|
||||
|
||||
void GenericBuffer::load(BEd &ctx, const char *cmd) {
|
||||
auto text = vase::Shard::from_command(cmd, true);
|
||||
try {
|
||||
if (lines())
|
||||
ctx.marks.erase(name, 1, lines());
|
||||
vase::Shard::release(root);
|
||||
root = text;
|
||||
state = buffer::GenericBuffer::Unmodified;
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
ctx.prev().end = 0;
|
||||
} else {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 1;
|
||||
ctx.prev().end = text->lines + 1;
|
||||
}
|
||||
parser.emplace(root, lines(), syntax::ruby::lang_ruby());
|
||||
} catch (...) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void GenericBuffer::load(BEd &ctx, std::filesystem::path path) {
|
||||
auto text = vase::Shard::from_file(path, true);
|
||||
try {
|
||||
if (lines())
|
||||
ctx.marks.erase(name, 1, lines());
|
||||
vase::Shard::release(root);
|
||||
root = text;
|
||||
state = buffer::GenericBuffer::Unmodified;
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
ctx.prev().end = 0;
|
||||
} else {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 1;
|
||||
ctx.prev().end = text->lines + 1;
|
||||
}
|
||||
parser.emplace(root, lines(), syntax::ruby::lang_ruby());
|
||||
} catch (...) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void GenericBuffer::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;
|
||||
@@ -54,7 +111,7 @@ void Buffer::append(BEd &ctx, vase::Shard *text, uint64_t line) {
|
||||
state = Modified;
|
||||
}
|
||||
|
||||
void Buffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
void GenericBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
root = vase::erase(root, start_line, end_line);
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = lines() ? 1 : 0;
|
||||
@@ -65,7 +122,7 @@ void Buffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
state = Modified;
|
||||
}
|
||||
|
||||
void Buffer::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);
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
@@ -76,7 +133,7 @@ void Buffer::join(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
state = Modified;
|
||||
}
|
||||
|
||||
void Buffer::substitute(
|
||||
void GenericBuffer::substitute(
|
||||
BEd &ctx, uint64_t start_line, uint64_t end_line,
|
||||
std::string ®ex, std::string &replacement, std::string &options
|
||||
) {
|
||||
@@ -112,10 +169,42 @@ void Buffer::substitute(
|
||||
state = Modified;
|
||||
}
|
||||
|
||||
vase::Shard *Buffer::copy(uint64_t start_line, uint64_t end_line) {
|
||||
vase::Shard *GenericBuffer::copy(uint64_t start_line, uint64_t end_line) {
|
||||
return vase::copy(root, start_line, end_line);
|
||||
}
|
||||
|
||||
uint64_t GenericBuffer::find_next(std::string_view pattern, uint64_t start) {
|
||||
return vase::find_next(root, pattern, start);
|
||||
}
|
||||
|
||||
uint64_t GenericBuffer::find_prev(std::string_view pattern, uint64_t start) {
|
||||
return vase::find_prev(root, pattern, start);
|
||||
}
|
||||
|
||||
uint64_t GenericBuffer::next_closing(uint64_t start) {
|
||||
if (parser.has_value()) {
|
||||
uint64_t closing = parser->next_closing(start - 1);
|
||||
if (closing == UINT64_MAX)
|
||||
return lines();
|
||||
return closing + 1;
|
||||
} else {
|
||||
start += 10;
|
||||
if (start > lines())
|
||||
return lines();
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t GenericBuffer::prev_closing(uint64_t start) {
|
||||
if (parser.has_value()) {
|
||||
return parser->prev_opening(start - 1) + 1;
|
||||
} else {
|
||||
if (start > 10)
|
||||
return start - 10;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void apply(std::ostream &out, const Highlight &hl) {
|
||||
out << "\x1b[0m";
|
||||
const uint8_t r = (hl.fg >> 16) & 0xff;
|
||||
@@ -148,7 +237,7 @@ inline void reset(std::ostream &out) {
|
||||
out << "\x1b[0m";
|
||||
}
|
||||
|
||||
void Buffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
void GenericBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = end_line;
|
||||
@@ -191,7 +280,7 @@ void Buffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
void GenericBuffer::number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = end_line;
|
||||
@@ -238,7 +327,7 @@ void Buffer::number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string Buffer::list_string(std::string_view s) {
|
||||
/*std::string GenericBuffer::list_string(std::string_view s) {
|
||||
uint32_t width = 80;
|
||||
winsize ws{};
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0)
|
||||
@@ -294,5 +383,5 @@ std::string Buffer::list_string(std::string_view s) {
|
||||
}
|
||||
out += '$';
|
||||
return out;
|
||||
}
|
||||
}*/
|
||||
} // namespace bed::internal::buffer
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
#include "bed.h"
|
||||
#include "internal/buffer/buffer.h"
|
||||
|
||||
namespace bed::internal::buffer {
|
||||
ClipBuffer::~ClipBuffer() {}
|
||||
|
||||
bool ClipBuffer::waste() {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::lines() {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
uint64_t lines = s ? s->lines + 1 : 0;
|
||||
vase::Shard::release(s);
|
||||
return lines;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::bytes() {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
uint64_t length = s ? s->length + 1 : 0;
|
||||
vase::Shard::release(s);
|
||||
return length;
|
||||
}
|
||||
|
||||
void ClipBuffer::clip_write(vase::Shard *text) {
|
||||
FILE *pipe = popen("xclip -selection clipboard -i", "w");
|
||||
if (!pipe)
|
||||
throw ed_error("can't access clipboard");
|
||||
auto s = vase::to_string(text);
|
||||
fwrite(s.data(), 1, s.length(), pipe);
|
||||
if (pclose(pipe) != 0)
|
||||
throw ed_error("can't write clipboard");
|
||||
}
|
||||
|
||||
void ClipBuffer::load(BEd &ctx, vase::Shard *text) {
|
||||
try {
|
||||
clip_write(text);
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
ctx.prev().end = 0;
|
||||
} else {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 1;
|
||||
ctx.prev().end = text->lines + 1;
|
||||
}
|
||||
vase::Shard::release(text);
|
||||
} catch (...) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBuffer::load(BEd &) {
|
||||
throw ed_error("File cannot be implied.");
|
||||
}
|
||||
|
||||
void ClipBuffer::load(BEd &ctx, const char *cmd) {
|
||||
auto text = vase::Shard::from_command(cmd, true);
|
||||
try {
|
||||
clip_write(text);
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
ctx.prev().end = 0;
|
||||
} else {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 1;
|
||||
ctx.prev().end = text->lines + 1;
|
||||
}
|
||||
vase::Shard::release(text);
|
||||
} catch (...) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBuffer::load(BEd &ctx, std::filesystem::path path) {
|
||||
auto text = vase::Shard::from_file(path, true);
|
||||
try {
|
||||
clip_write(text);
|
||||
if (!text) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 0;
|
||||
ctx.prev().end = 0;
|
||||
} else {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = 1;
|
||||
ctx.prev().end = text->lines + 1;
|
||||
}
|
||||
vase::Shard::release(text);
|
||||
} catch (...) {
|
||||
vase::Shard::release(text);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
void ClipBuffer::remove(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
s = vase::erase(s, start_line, end_line);
|
||||
clip_write(s);
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = (s ? s->length + 1 : 0) ? 1 : 0;
|
||||
ctx.prev().end = s ? s->length + 1 : 0;
|
||||
vase::Shard::release(s);
|
||||
ctx.marks.erase(name, start_line, end_line - start_line + 1);
|
||||
}
|
||||
|
||||
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);
|
||||
clip_write(s);
|
||||
vase::Shard::release(s);
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = start_line;
|
||||
ctx.marks.collapse(name, start_line, end_line - start_line);
|
||||
}
|
||||
|
||||
void ClipBuffer::substitute(
|
||||
BEd &ctx, uint64_t start_line, uint64_t end_line,
|
||||
std::string ®ex, std::string &replacement, std::string &options
|
||||
) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = end_line;
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
s = vase::substitute(
|
||||
&ctx.append,
|
||||
s,
|
||||
regex,
|
||||
start_line,
|
||||
end_line,
|
||||
replacement,
|
||||
options,
|
||||
[&](uint64_t line, uint64_t old_lines, uint64_t new_lines) {
|
||||
if (old_lines)
|
||||
ctx.marks.erase(name, line, old_lines);
|
||||
if (new_lines)
|
||||
ctx.marks.insert(name, line, line + new_lines - 1);
|
||||
}
|
||||
);
|
||||
clip_write(s);
|
||||
vase::Shard::release(s);
|
||||
ctx.prev().buffername = name;
|
||||
}
|
||||
|
||||
vase::Shard *ClipBuffer::copy(uint64_t start_line, uint64_t end_line) {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
vase::Shard *o = vase::copy(s, start_line, end_line);
|
||||
vase::Shard::release(s);
|
||||
return o;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::find_next(std::string_view pattern, uint64_t start) {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
uint64_t line = vase::find_next(s, pattern, start);
|
||||
vase::Shard::release(s);
|
||||
return line;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::find_prev(std::string_view pattern, uint64_t start) {
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
uint64_t line = vase::find_prev(s, pattern, start);
|
||||
vase::Shard::release(s);
|
||||
return line;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::next_closing(uint64_t start) {
|
||||
start += 10;
|
||||
uint64_t line = lines();
|
||||
if (start > line)
|
||||
return line;
|
||||
return start;
|
||||
}
|
||||
|
||||
uint64_t ClipBuffer::prev_closing(uint64_t start) {
|
||||
if (start > 10)
|
||||
return start - 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClipBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = end_line;
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
||||
while (it.next() && start_line++ <= end_line)
|
||||
std::cout << it.line << std::endl;
|
||||
vase::Shard::release(s);
|
||||
}
|
||||
|
||||
void ClipBuffer::number_print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||
ctx.prev().buffername = name;
|
||||
ctx.prev().start = start_line;
|
||||
ctx.prev().end = end_line;
|
||||
uint8_t width = 1;
|
||||
for (uint64_t n = end_line; n >= 10; n /= 10)
|
||||
++width;
|
||||
auto s = vase::Shard::from_command("xclip -selection clipboard -o", true);
|
||||
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
||||
while (it.next() && start_line <= end_line)
|
||||
std::cout << std::setw(width) << start_line++ << "\t" << it.line << std::endl;
|
||||
vase::Shard::release(s);
|
||||
}
|
||||
} // namespace bed::internal::buffer
|
||||
@@ -280,19 +280,12 @@ void Function::register_posix(BEd &ctx) {
|
||||
buf.state = buffer::Buffer::Warned;
|
||||
throw ed_error("Buffer modified.");
|
||||
}
|
||||
vase::Shard *s = nullptr;
|
||||
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
||||
s = vase::Shard::from_file(std::get<std::filesystem::path>(arg), true);
|
||||
buf.save_path = std::get<std::filesystem::path>(arg);
|
||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||
s = vase::Shard::from_command(std::get<ShellArg>(arg).cmd.c_str(), true);
|
||||
} else if (std::holds_alternative<std::monostate>(arg)) {
|
||||
if (buf.save_path != "")
|
||||
s = vase::Shard::from_file(buf.save_path, true);
|
||||
else
|
||||
throw ed_error("Need filename to load.");
|
||||
}
|
||||
buf.load(ctx, s);
|
||||
if (std::holds_alternative<std::filesystem::path>(arg))
|
||||
buf.load(ctx, std::get<std::filesystem::path>(arg));
|
||||
else if (std::holds_alternative<ShellArg>(arg))
|
||||
buf.load(ctx, std::get<ShellArg>(arg).cmd.c_str());
|
||||
else if (std::holds_alternative<std::monostate>(arg))
|
||||
buf.load(ctx);
|
||||
std::cout << buf.bytes() << std::endl;
|
||||
ctx.current() = {addr, buf.lines()};
|
||||
}
|
||||
@@ -310,20 +303,16 @@ void Function::register_posix(BEd &ctx) {
|
||||
.pre_text_mode = nullptr,
|
||||
.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;
|
||||
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
||||
s = vase::Shard::from_file(std::get<std::filesystem::path>(arg), true);
|
||||
buf.save_path = std::get<std::filesystem::path>(arg);
|
||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||
s = vase::Shard::from_command(std::get<ShellArg>(arg).cmd.c_str(), true);
|
||||
} else if (std::holds_alternative<std::monostate>(arg)) {
|
||||
if (buf.save_path != "")
|
||||
s = vase::Shard::from_file(buf.save_path, true);
|
||||
else
|
||||
throw ed_error("Need filename to load.");
|
||||
}
|
||||
buf.load(ctx, s);
|
||||
auto &buf_ = ctx.buffer(addr);
|
||||
if (buf_.kind != buffer::Buffer::Kind::Generic)
|
||||
return;
|
||||
auto &buf = *(buffer::GenericBuffer *)&buf_;
|
||||
if (std::holds_alternative<std::filesystem::path>(arg))
|
||||
buf.load(ctx, std::get<std::filesystem::path>(arg));
|
||||
else if (std::holds_alternative<ShellArg>(arg))
|
||||
buf.load(ctx, std::get<ShellArg>(arg).cmd.c_str());
|
||||
else if (std::holds_alternative<std::monostate>(arg))
|
||||
buf.load(ctx);
|
||||
std::cout << buf.bytes() << std::endl;
|
||||
ctx.current() = {addr, buf.lines()};
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ buffer::Line AddressPromise::resolve(BEd &ctx) {
|
||||
if (re.size() == 0)
|
||||
throw ed_error("No regex given.");
|
||||
if (addr.dir == Direction::Forward)
|
||||
line.number = vase::find_next(buf.root, re, line.number);
|
||||
line.number = buf.find_next(re, line.number);
|
||||
else
|
||||
line.number = vase::find_prev(buf.root, re, line.number);
|
||||
line.number = buf.find_prev(re, line.number);
|
||||
ctx.last_regex = re;
|
||||
} else if constexpr (std::is_same_v<T, Block>) {
|
||||
if (line.buffername == ctx.current().buffername)
|
||||
@@ -55,28 +55,10 @@ buffer::Line AddressPromise::resolve(BEd &ctx) {
|
||||
line.number = buf.lines();
|
||||
if (buf.lines() > 0 && line.number == 0)
|
||||
line.number = 1;
|
||||
if (addr.dir == Direction::Forward) {
|
||||
if (buf.parser.has_value()) {
|
||||
uint64_t closing = buf.parser->next_closing(line.number - 1);
|
||||
if (closing == UINT64_MAX)
|
||||
line.number = buf.lines();
|
||||
else
|
||||
line.number = closing + 1;
|
||||
} else {
|
||||
line.number += 10;
|
||||
if (line.number > buf.lines())
|
||||
line.number = buf.lines();
|
||||
}
|
||||
} else {
|
||||
if (buf.parser.has_value()) {
|
||||
line.number = buf.parser->prev_opening(line.number - 1) + 1;
|
||||
} else {
|
||||
if (line.number > 10)
|
||||
line.number -= 10;
|
||||
else
|
||||
line.number = 0;
|
||||
}
|
||||
}
|
||||
if (addr.dir == Direction::Forward)
|
||||
line.number = buf.next_closing(line.number);
|
||||
else
|
||||
line.number = buf.prev_closing(line.number);
|
||||
} else {
|
||||
throw ed_error("Unhandled address given.");
|
||||
}
|
||||
|
||||
@@ -179,6 +179,8 @@ Shard *substitute(
|
||||
}
|
||||
|
||||
uint64_t find_next(Shard *root, std::string_view pattern, uint64_t start) {
|
||||
if (!root)
|
||||
throw ed_error("Invalid line number.");
|
||||
if (start == 0 || start > root->lines + 1)
|
||||
throw ed_error("Invalid line number.");
|
||||
start--;
|
||||
@@ -241,6 +243,8 @@ uint64_t find_next(Shard *root, std::string_view pattern, uint64_t start) {
|
||||
}
|
||||
|
||||
uint64_t find_prev(Shard *root, std::string_view pattern, uint64_t start) {
|
||||
if (!root)
|
||||
throw ed_error("Invalid line number.");
|
||||
if (start == 0 || start > root->lines + 1)
|
||||
throw ed_error("Invalid line number.");
|
||||
start--;
|
||||
|
||||
@@ -273,7 +273,6 @@ Shard *copy(Shard *root, uint64_t start, uint64_t end) {
|
||||
Shard::release(left);
|
||||
Shard::release(rest);
|
||||
Shard::release(right);
|
||||
Shard::release(root);
|
||||
return middle;
|
||||
}
|
||||
} // namespace bed::internal::vase
|
||||
|
||||
Reference in New Issue
Block a user