Cleanup io calls and add cd function.
This commit is contained in:
@@ -50,5 +50,6 @@ struct BEd {
|
|||||||
void handle(std::string_view cmd, bool eof);
|
void handle(std::string_view cmd, bool eof);
|
||||||
void run();
|
void run();
|
||||||
void suffix_handle(char s);
|
void suffix_handle(char s);
|
||||||
|
bool escape_command(std::string &cmd, std::string_view filename);
|
||||||
};
|
};
|
||||||
} // namespace bed
|
} // namespace bed
|
||||||
|
|||||||
@@ -81,5 +81,6 @@ struct Function {
|
|||||||
handle;
|
handle;
|
||||||
|
|
||||||
static void register_posix(BEd &ctx);
|
static void register_posix(BEd &ctx);
|
||||||
|
static void register_extented(BEd &ctx);
|
||||||
};
|
};
|
||||||
} // namespace bed::internal::functions
|
} // namespace bed::internal::functions
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ struct IO {
|
|||||||
KeyEvent read_key();
|
KeyEvent read_key();
|
||||||
void write(const char *, uint64_t);
|
void write(const char *, uint64_t);
|
||||||
void write(std::string_view);
|
void write(std::string_view);
|
||||||
|
void write_line(std::string_view);
|
||||||
void run_pty(const std::string &);
|
void run_pty(const std::string &);
|
||||||
|
|
||||||
std::deque<char> input_queue;
|
std::deque<char> input_queue;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ extern "C" {
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|||||||
+31
-4
@@ -5,6 +5,7 @@ namespace bed {
|
|||||||
BEd::BEd(std::vector<std::string> args, internal::io::IO &io)
|
BEd::BEd(std::vector<std::string> args, internal::io::IO &io)
|
||||||
: theme(internal::theme::Theme::default_theme()), io(io) {
|
: theme(internal::theme::Theme::default_theme()), io(io) {
|
||||||
internal::functions::Function::register_posix(*this);
|
internal::functions::Function::register_posix(*this);
|
||||||
|
internal::functions::Function::register_extented(*this);
|
||||||
internal::functions::Suffix::register_suffixes(*this);
|
internal::functions::Suffix::register_suffixes(*this);
|
||||||
std::string prompt_ = "";
|
std::string prompt_ = "";
|
||||||
std::string file = "";
|
std::string file = "";
|
||||||
@@ -36,9 +37,9 @@ BEd::BEd(std::vector<std::string> args, internal::io::IO &io)
|
|||||||
if (file != "")
|
if (file != "")
|
||||||
handle(":default:E " + file, false);
|
handle(":default:E " + file, false);
|
||||||
} catch (ed_error &e) {
|
} catch (ed_error &e) {
|
||||||
std::cout << "?" << std::endl;
|
io.write_line("?");
|
||||||
if (help_mode)
|
if (help_mode)
|
||||||
std::cout << e.what() << std::endl;
|
io.write_line(e.what());
|
||||||
last_help = e.what();
|
last_help = e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,9 +56,9 @@ void BEd::run() {
|
|||||||
try {
|
try {
|
||||||
handle(cmd, eof);
|
handle(cmd, eof);
|
||||||
} catch (ed_error &e) {
|
} catch (ed_error &e) {
|
||||||
std::cout << "?" << std::endl;
|
io.write_line("?");
|
||||||
if (help_mode)
|
if (help_mode)
|
||||||
std::cout << e.what() << std::endl;
|
io.write_line(e.what());
|
||||||
last_help = e.what();
|
last_help = e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,4 +184,30 @@ internal::buffer::Range &BEd::prev() {
|
|||||||
void BEd::mark(uint8_t m, internal::buffer::Line line) {
|
void BEd::mark(uint8_t m, internal::buffer::Line line) {
|
||||||
marks.get(m) = line;
|
marks.get(m) = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BEd::escape_command(std::string &cmd, std::string_view filename) {
|
||||||
|
bool modified = false;
|
||||||
|
if (cmd == "!") {
|
||||||
|
cmd = last_shell;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
last_shell = cmd;
|
||||||
|
for (size_t i = 0; i < cmd.size();) {
|
||||||
|
if (cmd[i] == '\\') {
|
||||||
|
if (i + 1 >= cmd.size())
|
||||||
|
break;
|
||||||
|
cmd.erase(i++, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cmd[i] == '%') {
|
||||||
|
cmd.erase(i, 1);
|
||||||
|
cmd.insert(i, filename);
|
||||||
|
i += filename.size();
|
||||||
|
modified = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
} // namespace bed
|
} // namespace bed
|
||||||
|
|||||||
@@ -155,36 +155,30 @@ uint64_t GenericBuffer::prev_closing(uint64_t start) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void apply(std::ostream &out, const Highlight &hl) {
|
inline void apply(io::IO &io, const Highlight &hl) {
|
||||||
out << "\x1b[0m";
|
io.write("\x1b[0m");
|
||||||
const uint8_t r = (hl.fg >> 16) & 0xff;
|
const uint8_t r = (hl.fg >> 16) & 0xff;
|
||||||
const uint8_t g = (hl.fg >> 8) & 0xff;
|
const uint8_t g = (hl.fg >> 8) & 0xff;
|
||||||
const uint8_t b = hl.fg & 0xff;
|
const uint8_t b = hl.fg & 0xff;
|
||||||
out << "\x1b[38;2;"
|
io.write(std::format("\x1b[38;2;{};{};{}m", r, g, b));
|
||||||
<< (unsigned)r << ';'
|
|
||||||
<< (unsigned)g << ';'
|
|
||||||
<< (unsigned)b << 'm';
|
|
||||||
if (hl.bg != 0) {
|
if (hl.bg != 0) {
|
||||||
const uint8_t br = (hl.bg >> 16) & 0xff;
|
const uint8_t br = (hl.bg >> 16) & 0xff;
|
||||||
const uint8_t bg = (hl.bg >> 8) & 0xff;
|
const uint8_t bg = (hl.bg >> 8) & 0xff;
|
||||||
const uint8_t bb = hl.bg & 0xff;
|
const uint8_t bb = hl.bg & 0xff;
|
||||||
out << "\x1b[48;2;"
|
io.write(std::format("\x1b[48;2;{};{};{}m", br, bg, bb));
|
||||||
<< (unsigned)br << ';'
|
|
||||||
<< (unsigned)bg << ';'
|
|
||||||
<< (unsigned)bb << 'm';
|
|
||||||
}
|
}
|
||||||
if (hl.flags & Highlight::Bold)
|
if (hl.flags & Highlight::Bold)
|
||||||
out << "\x1b[1m";
|
io.write("\x1b[1m");
|
||||||
if (hl.flags & Highlight::Italic)
|
if (hl.flags & Highlight::Italic)
|
||||||
out << "\x1b[3m";
|
io.write("\x1b[3m");
|
||||||
if (hl.flags & Highlight::Underline)
|
if (hl.flags & Highlight::Underline)
|
||||||
out << "\x1b[4m";
|
io.write("\x1b[4m");
|
||||||
if (hl.flags & Highlight::Strikethrough)
|
if (hl.flags & Highlight::Strikethrough)
|
||||||
out << "\x1b[9m";
|
io.write("\x1b[9m");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reset(std::ostream &out) {
|
inline void reset(io::IO &io) {
|
||||||
out << "\x1b[0m";
|
io.write("\x1b[0m");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
void GenericBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
||||||
@@ -192,7 +186,7 @@ void GenericBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
|||||||
ctx.prev().start = start_line;
|
ctx.prev().start = start_line;
|
||||||
ctx.prev().end = end_line;
|
ctx.prev().end = end_line;
|
||||||
if (parser) {
|
if (parser) {
|
||||||
std::optional<syntax::Parser::Iterator> it_o = parser->get_hl(root, start_line - 1);
|
auto it_o = parser->get_hl(root, start_line - 1);
|
||||||
auto &it = *it_o;
|
auto &it = *it_o;
|
||||||
while (start_line <= end_line) {
|
while (start_line <= end_line) {
|
||||||
it.next();
|
it.next();
|
||||||
@@ -202,31 +196,25 @@ void GenericBuffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) {
|
|||||||
for (const auto &token : tokens) {
|
for (const auto &token : tokens) {
|
||||||
const uint32_t start = token.start;
|
const uint32_t start = token.start;
|
||||||
const uint32_t end = token.end;
|
const uint32_t end = token.end;
|
||||||
if (start > line.size())
|
if (start > line.size() || end > line.size())
|
||||||
break;
|
break;
|
||||||
if (end > line.size())
|
if (cursor < start)
|
||||||
break;
|
ctx.io.write(line.data() + cursor, start - cursor);
|
||||||
if (cursor < start) {
|
|
||||||
std::cout.write(
|
|
||||||
line.data() + cursor,
|
|
||||||
start - cursor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const auto highlight = ctx.theme.get(token);
|
const auto highlight = ctx.theme.get(token);
|
||||||
apply(std::cout, highlight);
|
apply(ctx.io, highlight);
|
||||||
std::cout.write(line.data() + start, end - start);
|
ctx.io.write(line.data() + start, end - start);
|
||||||
reset(std::cout);
|
reset(ctx.io);
|
||||||
cursor = end;
|
cursor = end;
|
||||||
}
|
}
|
||||||
if (cursor < line.size())
|
if (cursor < line.size())
|
||||||
std::cout.write(line.data() + cursor, line.size() - cursor);
|
ctx.io.write(line.data() + cursor, line.size() - cursor);
|
||||||
std::cout << std::endl;
|
ctx.io.write_line("");
|
||||||
++start_line;
|
++start_line;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line++ <= end_line)
|
while (it.next() && start_line++ <= end_line)
|
||||||
std::cout << it.line << std::endl;
|
ctx.io.write_line(it.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,38 +230,32 @@ void GenericBuffer::number_print(BEd &ctx, uint64_t start_line, uint64_t end_lin
|
|||||||
auto &it = *it_o;
|
auto &it = *it_o;
|
||||||
while (start_line <= end_line) {
|
while (start_line <= end_line) {
|
||||||
it.next();
|
it.next();
|
||||||
std::cout << std::setw(width) << start_line << "\t";
|
ctx.io.write(std::format("{:>{}}\t", start_line, width));
|
||||||
const std::string &line = it.it->line;
|
const std::string &line = it.it->line;
|
||||||
const auto &tokens = it.tokens;
|
const auto &tokens = it.tokens;
|
||||||
uint32_t cursor = 0;
|
uint32_t cursor = 0;
|
||||||
for (const auto &token : tokens) {
|
for (const auto &token : tokens) {
|
||||||
const uint32_t start = token.start;
|
const uint32_t start = token.start;
|
||||||
const uint32_t end = token.end;
|
const uint32_t end = token.end;
|
||||||
if (start > line.size())
|
if (start > line.size() || end > line.size())
|
||||||
break;
|
break;
|
||||||
if (end > line.size())
|
if (cursor < start)
|
||||||
break;
|
ctx.io.write(line.data() + cursor, start - cursor);
|
||||||
if (cursor < start) {
|
|
||||||
std::cout.write(
|
|
||||||
line.data() + cursor,
|
|
||||||
start - cursor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const auto highlight = ctx.theme.get(token);
|
const auto highlight = ctx.theme.get(token);
|
||||||
apply(std::cout, highlight);
|
apply(ctx.io, highlight);
|
||||||
std::cout.write(line.data() + start, end - start);
|
ctx.io.write(line.data() + start, end - start);
|
||||||
reset(std::cout);
|
reset(ctx.io);
|
||||||
cursor = end;
|
cursor = end;
|
||||||
}
|
}
|
||||||
if (cursor < line.size())
|
if (cursor < line.size())
|
||||||
std::cout.write(line.data() + cursor, line.size() - cursor);
|
ctx.io.write(line.data() + cursor, line.size() - cursor);
|
||||||
std::cout << std::endl;
|
ctx.io.write_line("");
|
||||||
++start_line;
|
++start_line;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line <= end_line)
|
while (it.next() && start_line <= end_line)
|
||||||
std::cout << std::setw(width) << start_line++ << "\t" << it.line << std::endl;
|
ctx.io.write_line(std::format("{:>{}}\t{}", start_line++, width, it.line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +265,6 @@ void GenericBuffer::list_print(BEd &ctx, uint64_t start_line, uint64_t end_line)
|
|||||||
ctx.prev().end = end_line;
|
ctx.prev().end = end_line;
|
||||||
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
vase::Iterator it(root, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line++ <= end_line)
|
while (it.next() && start_line++ <= end_line)
|
||||||
std::cout << list_string(it.line) << std::endl;
|
ctx.io.write_line(list_string(it.line));
|
||||||
}
|
}
|
||||||
} // namespace bed::internal::buffer
|
} // namespace bed::internal::buffer
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ void ClipBuffer::print(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);
|
||||||
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line++ <= end_line)
|
while (it.next() && start_line++ <= end_line)
|
||||||
std::cout << it.line << std::endl;
|
ctx.io.write_line(it.line);
|
||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ void ClipBuffer::number_print(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);
|
||||||
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line <= end_line)
|
while (it.next() && start_line <= end_line)
|
||||||
std::cout << std::setw(width) << start_line++ << "\t" << it.line << std::endl;
|
ctx.io.write_line(std::format("{:>{}}\t{}", start_line++, width, it.line));
|
||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ void ClipBuffer::list_print(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);
|
||||||
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
vase::Iterator it(s, start_line - 1, Direction::Forward);
|
||||||
while (it.next() && start_line++ <= end_line)
|
while (it.next() && start_line++ <= end_line)
|
||||||
std::cout << list_string(it.line) << std::endl;
|
ctx.io.write_line(list_string(it.line));
|
||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
}
|
}
|
||||||
} // namespace bed::internal::buffer
|
} // namespace bed::internal::buffer
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include "bed.h"
|
||||||
|
#include "internal/functions/functions.h"
|
||||||
|
#include "internal/functions/suffixes.h"
|
||||||
|
|
||||||
|
namespace bed::internal::functions {
|
||||||
|
void Function::register_extented(BEd &ctx) {
|
||||||
|
ctx.functions.insert(
|
||||||
|
"cd",
|
||||||
|
Function{
|
||||||
|
.address_kind = Function::AddressKind::None,
|
||||||
|
.argument_kind = Function::ArgumentKind::Any,
|
||||||
|
.input_mode = Function::InputMode::None,
|
||||||
|
.desc = "Change directory.",
|
||||||
|
.default_address = "",
|
||||||
|
.accept_zero = false,
|
||||||
|
.pre_text_mode = nullptr,
|
||||||
|
.handle = [](BEd &ctx, 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");
|
||||||
|
path = path.substr(first, last - first + 1);
|
||||||
|
if (path == "~")
|
||||||
|
path = std::getenv("HOME");
|
||||||
|
if (path.starts_with("~/")) {
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
if (home)
|
||||||
|
path = std::string(home) + path.substr(1);
|
||||||
|
}
|
||||||
|
if (first != std::string::npos)
|
||||||
|
if (chdir(path.c_str()) == -1)
|
||||||
|
throw ed_error("Can't change directory.");
|
||||||
|
char cwd[PATH_MAX];
|
||||||
|
if (!getcwd(cwd, sizeof(cwd)))
|
||||||
|
throw ed_error("Directory changed, but couldn't determine current directory.");
|
||||||
|
ctx.io.write_line(cwd);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} // namespace bed::internal::functions
|
||||||
@@ -1,34 +1,8 @@
|
|||||||
#include "internal/functions/functions.h"
|
|
||||||
#include "bed.h"
|
#include "bed.h"
|
||||||
|
#include "internal/functions/functions.h"
|
||||||
#include "internal/functions/suffixes.h"
|
#include "internal/functions/suffixes.h"
|
||||||
|
|
||||||
namespace bed::internal::functions {
|
namespace bed::internal::functions {
|
||||||
static bool escape_command(BEd &ctx, std::string &cmd, std::string_view filename) {
|
|
||||||
bool modified = false;
|
|
||||||
if (cmd == "!") {
|
|
||||||
cmd = ctx.last_shell;
|
|
||||||
modified = true;
|
|
||||||
}
|
|
||||||
ctx.last_shell = cmd;
|
|
||||||
for (size_t i = 0; i < cmd.size();) {
|
|
||||||
if (cmd[i] == '\\') {
|
|
||||||
if (i + 1 >= cmd.size())
|
|
||||||
break;
|
|
||||||
cmd.erase(i++, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cmd[i] == '%') {
|
|
||||||
cmd.erase(i, 1);
|
|
||||||
cmd.insert(i, filename);
|
|
||||||
i += filename.size();
|
|
||||||
modified = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Suffix::register_suffixes(BEd &ctx) {
|
void Suffix::register_suffixes(BEd &ctx) {
|
||||||
ctx.suffixes['p' - 'a'] = Suffix{
|
ctx.suffixes['p' - 'a'] = Suffix{
|
||||||
.desc = "Prints current line.",
|
.desc = "Prints current line.",
|
||||||
@@ -54,24 +28,6 @@ void Suffix::register_suffixes(BEd &ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Function::register_posix(BEd &ctx) {
|
void Function::register_posix(BEd &ctx) {
|
||||||
ctx.eof_op = Function{
|
|
||||||
.address_kind = Function::AddressKind::None,
|
|
||||||
.argument_kind = Function::ArgumentKind::None,
|
|
||||||
.input_mode = Function::InputMode::None,
|
|
||||||
.desc = "Try quitting.",
|
|
||||||
.default_address = "",
|
|
||||||
.accept_zero = false,
|
|
||||||
.pre_text_mode = nullptr,
|
|
||||||
.handle = [](BEd &ctx, const buffer::Address &, vase::Shard *, const Argument &, std::vector<buffer::Line> *) {
|
|
||||||
for (auto &[name, buffer] : ctx.buffers) {
|
|
||||||
if (buffer->state == buffer::Buffer::Modified) {
|
|
||||||
buffer->state = buffer::Buffer::Warned;
|
|
||||||
throw ed_error("Buffer " + name + " modified.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw fatal_error("Quitting", 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ctx.functions.insert(
|
ctx.functions.insert(
|
||||||
"a",
|
"a",
|
||||||
Function{
|
Function{
|
||||||
@@ -150,7 +106,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
buf.set_filename(path);
|
buf.set_filename(path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
escape_command(ctx, cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
s = vase::Shard::from_command(cmd.c_str(), true);
|
s = vase::Shard::from_command(cmd.c_str(), true);
|
||||||
} else {
|
} else {
|
||||||
auto path = buf.filename();
|
auto path = buf.filename();
|
||||||
@@ -165,7 +121,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
std::cout << buf.bytes() << std::endl;
|
ctx.io.write_line(std::format("{}", buf.bytes()));
|
||||||
ctx.current() = {addr, buf.lines()};
|
ctx.current() = {addr, buf.lines()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +146,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
buf.set_filename(path);
|
buf.set_filename(path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
escape_command(ctx, cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
s = vase::Shard::from_command(cmd.c_str(), true);
|
s = vase::Shard::from_command(cmd.c_str(), true);
|
||||||
} else {
|
} else {
|
||||||
auto path = buf.filename();
|
auto path = buf.filename();
|
||||||
@@ -205,7 +161,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
std::cout << buf.bytes() << std::endl;
|
ctx.io.write_line(std::format("{}", buf.bytes()));
|
||||||
ctx.current() = {addr, buf.lines()};
|
ctx.current() = {addr, buf.lines()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +188,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
throw ed_error("Can't save shell command as save path.");
|
throw ed_error("Can't save shell command as save path.");
|
||||||
if (buf.filename().empty())
|
if (buf.filename().empty())
|
||||||
throw ed_error("Filename needed.");
|
throw ed_error("Filename needed.");
|
||||||
std::cout << buf.filename() << std::endl;
|
ctx.io.write_line(buf.filename().string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -247,7 +203,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.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::cout << ctx.last_help << std::endl;
|
ctx.io.write_line(ctx.last_help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -264,7 +220,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.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)
|
||||||
std::cout << ctx.last_help << std::endl;
|
ctx.io.write_line(ctx.last_help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -490,7 +446,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
buf.set_filename(path);
|
buf.set_filename(path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
escape_command(ctx, cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
s = vase::Shard::from_command(cmd.c_str(), true);
|
s = vase::Shard::from_command(cmd.c_str(), true);
|
||||||
} else {
|
} else {
|
||||||
auto path = buf.filename();
|
auto path = buf.filename();
|
||||||
@@ -500,7 +456,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
buf.append(ctx, s, addr.number);
|
buf.append(ctx, s, addr.number);
|
||||||
std::cout << (s ? s->length + 1 : 0) << std::endl;
|
ctx.io.write_line(std::format("{}", s ? s->length + 1 : 0));
|
||||||
ctx.current() = {addr.buffername, addr.number + (s ? s->lines + 1 : 0)};
|
ctx.current() = {addr.buffername, addr.number + (s ? s->lines + 1 : 0)};
|
||||||
vase::Shard::release(s);
|
vase::Shard::release(s);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -601,7 +557,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
buf.set_filename(path);
|
buf.set_filename(path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
escape_command(ctx, cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
vase::write_command(cmd.c_str(), text);
|
vase::write_command(cmd.c_str(), text);
|
||||||
} else {
|
} else {
|
||||||
auto path = buf.filename();
|
auto path = buf.filename();
|
||||||
@@ -631,9 +587,9 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
.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)
|
||||||
std::cout << ':' << addr.buffername << ':' << addr.start << "\n";
|
ctx.io.write_line(std::format(":{}:{}", addr.buffername, addr.start));
|
||||||
else
|
else
|
||||||
std::cout << ':' << addr.buffername << ':' << addr.start << "," << addr.end << "\n";
|
ctx.io.write_line(std::format(":{}:{},{}", addr.buffername, addr.start, addr.end));
|
||||||
ctx.current() = {addr.buffername, addr.end};
|
ctx.current() = {addr.buffername, addr.end};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -653,7 +609,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
auto filename = ctx.buffer(addr).filename();
|
auto filename = ctx.buffer(addr).filename();
|
||||||
auto &arg = std::get<ShellArg>(arg_);
|
auto &arg = std::get<ShellArg>(arg_);
|
||||||
auto cmd = arg.cmd;
|
auto cmd = arg.cmd;
|
||||||
if (escape_command(ctx, cmd, filename.string()))
|
if (ctx.escape_command(cmd, filename.string()))
|
||||||
ctx.io.write(cmd + "\n");
|
ctx.io.write(cmd + "\n");
|
||||||
ctx.io.run_pty(cmd);
|
ctx.io.run_pty(cmd);
|
||||||
ctx.io.write("!\n");
|
ctx.io.write("!\n");
|
||||||
@@ -675,5 +631,27 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
ctx.current() = addr;
|
ctx.current() = addr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
ctx.eof_op = Function{
|
||||||
|
.address_kind = Function::AddressKind::None,
|
||||||
|
.argument_kind = Function::ArgumentKind::None,
|
||||||
|
.input_mode = Function::InputMode::None,
|
||||||
|
.desc = "Try quitting.",
|
||||||
|
.default_address = "",
|
||||||
|
.accept_zero = false,
|
||||||
|
.pre_text_mode = nullptr,
|
||||||
|
.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) {
|
||||||
|
buffer->state = buffer::Buffer::Warned;
|
||||||
|
modified_buffers.append(name + ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!modified_buffers.size())
|
||||||
|
throw fatal_error("Quitting", 0);
|
||||||
|
modified_buffers.erase(modified_buffers.size() - 2);
|
||||||
|
throw ed_error("Buffer(s) " + modified_buffers + " modified.");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} // namespace bed::internal::functions
|
} // namespace bed::internal::functions
|
||||||
+11
-1
@@ -106,6 +106,11 @@ void IO::write(std::string_view s) {
|
|||||||
write_all(STDOUT_FILENO, s.data(), s.size());
|
write_all(STDOUT_FILENO, s.data(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IO::write_line(std::string_view s) {
|
||||||
|
write(s);
|
||||||
|
write("\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
void IO::run_pty(const std::string &cmd) {
|
void IO::run_pty(const std::string &cmd) {
|
||||||
int master_fd = -1;
|
int master_fd = -1;
|
||||||
struct winsize ws{};
|
struct winsize ws{};
|
||||||
@@ -120,7 +125,12 @@ void IO::run_pty(const std::string &cmd) {
|
|||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
throw fatal_error("Can't create PTY.", 1);
|
throw fatal_error("Can't create PTY.", 1);
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
execl("/bin/sh", "sh", "-c", cmd.c_str(), (char *)nullptr);
|
const char *shell = getenv("BED_SHELL");
|
||||||
|
if (!shell || !*shell)
|
||||||
|
shell = getenv("SHELL");
|
||||||
|
if (!shell || !*shell)
|
||||||
|
shell = "/bin/sh";
|
||||||
|
execl(shell, shell, "-i", "-c", cmd.c_str(), (char *)nullptr);
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
struct pollfd fds[2];
|
struct pollfd fds[2];
|
||||||
|
|||||||
+2
-2
@@ -9,12 +9,12 @@ int main(int argc, char *argv[]) {
|
|||||||
ed.run();
|
ed.run();
|
||||||
} catch (bed::fatal_error &e) {
|
} catch (bed::fatal_error &e) {
|
||||||
if (e.code)
|
if (e.code)
|
||||||
std::cout << "Fatal error: " << e.what() << std::endl;
|
printf("Fatal error: %s\n", e.what());
|
||||||
return e.code;
|
return e.code;
|
||||||
}
|
}
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
catch (...) {
|
catch (...) {
|
||||||
std::cout << "Unexpected error." << std::endl;
|
printf("Unexpected error.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user