Files
bed/src/bed/run.cc
T
syedm bb3ce7549a Add basic scripting support.
- Fix certain bugs in ruby parser
- And a lot more cleanup/minor fixes.
2026-09-08 18:07:39 +01:00

114 lines
3.0 KiB
C++

#include "bed.h"
#include "internal/parser/parser.h"
namespace bed {
void BEd::run() {
while (true) {
internal::ui::CommandIO command(*this);
auto [cmd, eof] = command.run();
try {
handle(cmd, eof);
} catch (const ed_error &e) {
io.apply(internal::io::Token::Warning);
io.write_line("?");
if (help_mode)
io.write_line(e.what());
io.reset();
last_help = e.what();
}
}
}
internal::buffer::Buffer &BEd::buffer(const std::string &name) {
if (name.empty())
throw ed_error("Can't have empty buffer name");
{
auto it = buffers.find(name);
if (it != buffers.end())
return *it->second;
}
constexpr std::string_view prefix = "history/";
if (name == "cancel")
throw ed_error("Cancel buffer empty.");
if (name.starts_with(prefix)) {
std::string_view path{name};
path.remove_prefix(prefix.size());
auto slash = path.rfind('_');
if (slash == std::string_view::npos || slash == 0 || slash == path.size() - 1)
throw ed_error("invalid history");
std::string bufname(path.substr(0, slash));
auto version_str = path.substr(slash + 1);
std::size_t version;
try {
version = std::stoull(std::string(version_str));
} catch (...) {
throw ed_error("invalid history version");
}
auto it = buffers.find(bufname);
if (it != buffers.end()) {
auto &buf_ = *it->second;
if (buf_.kind != internal::buffer::Buffer::Kind::Generic)
throw ed_error("Only normal buffers can have history.");
auto &buf = *(internal::buffer::GenericBuffer *)&buf_;
auto *history_buf = buf.get_history(version);
buffers.emplace(name, history_buf);
return *history_buf;
}
throw ed_error("Buffer has no history.");
}
for (auto &c : name)
if (!(('0' <= c && c <= '9')
|| ('a' <= c && c <= 'z')
|| ('A' <= c && c <= 'Z')
|| c == '-' || c == '_'
|| c == '+' || c == '.'
|| c == ',' || c == '$'
|| c == '/' || c == '~'))
throw ed_error("Invalid buffer name.");
auto *buf = new internal::buffer::GenericBuffer(name);
buffers.emplace(name, buf);
return *buf;
}
internal::buffer::Line &BEd::current() {
return marks.get(250 + temporary_current);
}
internal::buffer::Range &BEd::prev() {
if (temporary_current)
return prev_2;
else
return prev_1;
}
void BEd::mark(uint8_t m, internal::buffer::Line 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