209 lines
6.4 KiB
C++
209 lines
6.4 KiB
C++
#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) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
void ClipBuffer::set_filename(std::filesystem::path) {}
|
|
|
|
std::filesystem::path ClipBuffer::filename() {
|
|
return "";
|
|
};
|
|
|
|
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 ? 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, line, text->lines + 1);
|
|
}
|
|
|
|
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 = std::min(start_line, s ? s->lines + 1 : 0);
|
|
ctx.prev().end = std::min(start_line, s ? s->lines + 1 : 0);
|
|
vase::Shard::release(s);
|
|
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);
|
|
}
|
|
}
|
|
|
|
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, new_lines);
|
|
}
|
|
);
|
|
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)
|
|
ctx.io.write_line(it.line);
|
|
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)
|
|
ctx.io.write_line(std::format("{:>{}}\t{}", start_line++, width, it.line));
|
|
vase::Shard::release(s);
|
|
}
|
|
|
|
void ClipBuffer::list_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)
|
|
ctx.io.write_line(list_string(it.line));
|
|
vase::Shard::release(s);
|
|
}
|
|
} // namespace bed::internal::buffer
|