Compare commits
2
Commits
bb3ce7549a
...
c325409dd0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c325409dd0
|
||
|
|
0e4422b0c8
|
@@ -70,9 +70,8 @@
|
|||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
make \
|
make \
|
||||||
MRBC=${mruby}/bin/mrbc \
|
MRUBY_CFLAGS="-I${mruby}/include" \
|
||||||
MRUBY_CFLAGS=-I${mruby}/include \
|
MRUBY_LIBS="-L${mruby}/lib -lmruby"
|
||||||
MRUBY_LIBS=-L${mruby}/lib -lmruby
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
@@ -110,7 +109,6 @@
|
|||||||
export CC="ccache $CC"
|
export CC="ccache $CC"
|
||||||
export CXX="ccache $CXX"
|
export CXX="ccache $CXX"
|
||||||
|
|
||||||
export MRBC=${mruby}/bin/mrbc
|
|
||||||
export MRUBY_CFLAGS=-I${mruby}/include
|
export MRUBY_CFLAGS=-I${mruby}/include
|
||||||
export MRUBY_LIBS="-L${mruby}/lib -lmruby"
|
export MRUBY_LIBS="-L${mruby}/lib -lmruby"
|
||||||
export PATH="$PWD/result/bin:$PATH"
|
export PATH="$PWD/result/bin:$PATH"
|
||||||
|
|||||||
+2
-2
@@ -22,6 +22,8 @@ struct BEd {
|
|||||||
std::unordered_map<std::string, internal::syntax::Language *> languages;
|
std::unordered_map<std::string, internal::syntax::Language *> languages;
|
||||||
internal::io::IO io;
|
internal::io::IO io;
|
||||||
internal::vase::AppendStorage append{"/tmp"};
|
internal::vase::AppendStorage append{"/tmp"};
|
||||||
|
std::unordered_map<std::string, internal::buffer::Buffer *> buffers;
|
||||||
|
|
||||||
mrb_state *mrb = nullptr;
|
mrb_state *mrb = nullptr;
|
||||||
int arena;
|
int arena;
|
||||||
|
|
||||||
@@ -37,8 +39,6 @@ struct BEd {
|
|||||||
std::string last_replacement = "";
|
std::string last_replacement = "";
|
||||||
std::string last_shell = "";
|
std::string last_shell = "";
|
||||||
|
|
||||||
std::unordered_map<std::string, internal::buffer::Buffer *> buffers;
|
|
||||||
|
|
||||||
internal::buffer::Range prev_1;
|
internal::buffer::Range prev_1;
|
||||||
internal::buffer::Range prev_2;
|
internal::buffer::Range prev_2;
|
||||||
internal::marks::MarksEngine marks;
|
internal::marks::MarksEngine marks;
|
||||||
|
|||||||
@@ -5,36 +5,93 @@
|
|||||||
|
|
||||||
namespace bed::internal::scripting {
|
namespace bed::internal::scripting {
|
||||||
struct Block {
|
struct Block {
|
||||||
mrb_value proc;
|
mrb_state *mrb = nullptr;
|
||||||
mrb_state *mrb;
|
mrb_value proc = mrb_nil_value();
|
||||||
|
|
||||||
Block(mrb_state *mrb, mrb_value proc)
|
Block(mrb_state *mrb, mrb_value proc) noexcept
|
||||||
: proc(proc), mrb(mrb) {
|
: mrb(mrb), proc(proc) {
|
||||||
mrb_gc_register(mrb, proc);
|
mrb_gc_register(mrb, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block() : proc(mrb_nil_value()) {}
|
Block() noexcept = default;
|
||||||
|
|
||||||
~Block() {
|
~Block() noexcept {
|
||||||
if (!mrb_nil_p(proc))
|
if (!mrb_nil_p(proc) && mrb)
|
||||||
mrb_gc_unregister(mrb, proc);
|
mrb_gc_unregister(mrb, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_proc(mrb_value new_proc) {
|
Block(const Block &other) noexcept
|
||||||
if (!mrb_nil_p(proc))
|
: mrb(other.mrb), proc(other.proc) {
|
||||||
|
if (mrb && !mrb_nil_p(proc))
|
||||||
|
mrb_gc_register(mrb, proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block &operator=(const Block &other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
if (mrb && !mrb_nil_p(proc))
|
||||||
|
mrb_gc_unregister(mrb, proc);
|
||||||
|
mrb = other.mrb;
|
||||||
|
proc = other.proc;
|
||||||
|
if (mrb && !mrb_nil_p(proc))
|
||||||
|
mrb_gc_register(mrb, proc);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block(Block &&other) noexcept
|
||||||
|
: mrb(other.mrb), proc(other.proc) {
|
||||||
|
other.mrb = nullptr;
|
||||||
|
other.proc = mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
Block &operator=(Block &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
if (mrb && !mrb_nil_p(proc))
|
||||||
|
mrb_gc_unregister(mrb, proc);
|
||||||
|
mrb = other.mrb;
|
||||||
|
proc = other.proc;
|
||||||
|
other.mrb = nullptr;
|
||||||
|
other.proc = mrb_nil_value();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_proc(mrb_state *mrb_, mrb_value new_proc) {
|
||||||
|
if (!mrb_nil_p(proc) && mrb)
|
||||||
mrb_gc_unregister(mrb, proc);
|
mrb_gc_unregister(mrb, proc);
|
||||||
|
mrb = mrb_;
|
||||||
proc = new_proc;
|
proc = new_proc;
|
||||||
mrb_gc_register(mrb, proc);
|
mrb_gc_register(mrb, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block(const Block &) = delete;
|
|
||||||
Block &operator=(const Block &) = delete;
|
|
||||||
|
|
||||||
mrb_value call(int argc = 0, mrb_value *argv = nullptr) const {
|
mrb_value call(int argc = 0, mrb_value *argv = nullptr) const {
|
||||||
if (mrb_nil_p(proc))
|
if (mrb_nil_p(proc))
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv);
|
mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv);
|
||||||
return result;
|
if (!mrb->exc)
|
||||||
|
return result;
|
||||||
|
mrb_value exc = mrb_obj_value(mrb->exc);
|
||||||
|
mrb_value msg = mrb_funcall(mrb, exc, "message", 0);
|
||||||
|
std::string error;
|
||||||
|
if (mrb_string_p(msg))
|
||||||
|
error.assign(RSTRING_PTR(msg), RSTRING_LEN(msg));
|
||||||
|
auto *fatal_class = mrb_class_get(mrb, "FatalError");
|
||||||
|
if (mrb_obj_is_kind_of(mrb, exc, fatal_class)) {
|
||||||
|
mrb_value code =
|
||||||
|
mrb_iv_get(mrb, exc, mrb_intern_lit(mrb, "@code"));
|
||||||
|
mrb->exc = nullptr;
|
||||||
|
int c = 1;
|
||||||
|
if (mrb_fixnum_p(code))
|
||||||
|
c = mrb_fixnum(code);
|
||||||
|
throw fatal_error(error, c);
|
||||||
|
}
|
||||||
|
auto *ed_class = mrb_class_get(mrb, "EdError");
|
||||||
|
if (mrb_obj_is_kind_of(mrb, exc, ed_class)) {
|
||||||
|
mrb->exc = nullptr;
|
||||||
|
throw ed_error(error);
|
||||||
|
}
|
||||||
|
mrb->exc = nullptr;
|
||||||
|
throw ed_error("Ruby Exception: " + error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ const static std::vector<std::string> builtins = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const static std::vector<std::string> methods = {
|
const static std::vector<std::string> methods = {
|
||||||
|
// BEd methods.
|
||||||
|
"handle",
|
||||||
|
"register",
|
||||||
|
"unregister",
|
||||||
|
// Normal:
|
||||||
"abort",
|
"abort",
|
||||||
"at_exit",
|
"at_exit",
|
||||||
"binding",
|
"binding",
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ static mrb_value mrb_bed_exit(mrb_state *mrb, mrb_value) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void raise_fatal(mrb_state *mrb, const fatal_error &e) {
|
||||||
raise_fatal(mrb_state *mrb, const fatal_error &e) {
|
|
||||||
struct RClass *klass = mrb_class_get(mrb, "FatalError");
|
struct RClass *klass = mrb_class_get(mrb, "FatalError");
|
||||||
mrb_value exc = mrb_exc_new_str(mrb, klass, mrb_str_new_cstr(mrb, e.what()));
|
mrb_value exc = mrb_exc_new_str(mrb, klass, mrb_str_new_cstr(mrb, e.what()));
|
||||||
mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "@code"), mrb_fixnum_value(e.code));
|
mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "@code"), mrb_fixnum_value(e.code));
|
||||||
@@ -27,19 +26,92 @@ static mrb_value mrb_bed_handle(mrb_state *mrb, mrb_value) {
|
|||||||
mrb_raise(mrb, mrb_class_get(mrb, "EdError"), e.what());
|
mrb_raise(mrb, mrb_class_get(mrb, "EdError"), e.what());
|
||||||
} catch (const fatal_error &f) {
|
} catch (const fatal_error &f) {
|
||||||
raise_fatal(mrb, f);
|
raise_fatal(mrb, f);
|
||||||
} catch (...) {
|
|
||||||
mrb_raise(mrb, E_RUNTIME_ERROR, "Unexpected error.");
|
|
||||||
}
|
}
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value hash_get(mrb_state *mrb, mrb_value hash, const char *name) {
|
||||||
|
if (mrb_nil_p(hash))
|
||||||
|
return mrb_nil_value();
|
||||||
|
return mrb_hash_get(mrb, hash, mrb_symbol_value(mrb_intern_cstr(mrb, name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static functions::Function::AddressKind parse_address_kind(mrb_state *mrb, mrb_value value) {
|
||||||
|
if (mrb_nil_p(value))
|
||||||
|
return functions::Function::AddressKind::None;
|
||||||
|
if (!mrb_symbol_p(value))
|
||||||
|
mrb_raise(mrb, E_TYPE_ERROR, "address must be a Symbol");
|
||||||
|
auto name = mrb_sym_name(mrb, mrb_symbol(value));
|
||||||
|
if (strcmp(name, "none") == 0)
|
||||||
|
return functions::Function::AddressKind::None;
|
||||||
|
if (strcmp(name, "line") == 0)
|
||||||
|
return functions::Function::AddressKind::Line;
|
||||||
|
if (strcmp(name, "range") == 0)
|
||||||
|
return functions::Function::AddressKind::Range;
|
||||||
|
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid address type: :%s", name);
|
||||||
|
return functions::Function::AddressKind::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value mrb_bed_register(mrb_state *mrb, mrb_value) {
|
||||||
|
auto &ctx = *(BEd *)mrb->ud;
|
||||||
|
mrb_sym r_cmd_name;
|
||||||
|
mrb_value proc;
|
||||||
|
mrb_value opts = mrb_nil_value();
|
||||||
|
mrb_get_args(mrb, "n&|H", &r_cmd_name, &proc, &opts);
|
||||||
|
mrb_int cmd_name_len;
|
||||||
|
const char *name = mrb_sym_name_len(mrb, r_cmd_name, &cmd_name_len);
|
||||||
|
std::string_view cmd_name(name, cmd_name_len);
|
||||||
|
std::string desc;
|
||||||
|
mrb_value r_desc = hash_get(mrb, opts, "desc");
|
||||||
|
if (mrb_string_p(r_desc))
|
||||||
|
desc.assign(RSTRING_PTR(r_desc), RSTRING_LEN(r_desc));
|
||||||
|
std::string default_address;
|
||||||
|
mrb_value r_default_address = hash_get(mrb, opts, "default");
|
||||||
|
if (mrb_string_p(r_default_address))
|
||||||
|
default_address.assign(RSTRING_PTR(r_default_address), RSTRING_LEN(r_default_address));
|
||||||
|
ctx.functions.insert(
|
||||||
|
cmd_name,
|
||||||
|
functions::Function{
|
||||||
|
.address_kind = parse_address_kind(mrb, hash_get(mrb, opts, "address")),
|
||||||
|
.argument_kind = functions::Function::ArgumentKind::None,
|
||||||
|
.input_mode = functions::Function::InputMode::None,
|
||||||
|
.desc = desc,
|
||||||
|
.default_address = default_address,
|
||||||
|
.accept_zero = true,
|
||||||
|
.pre_text_mode = nullptr,
|
||||||
|
.handle = [b = Block(mrb, proc)](
|
||||||
|
BEd &,
|
||||||
|
const buffer::Address &,
|
||||||
|
vase::Shard *,
|
||||||
|
const functions::Function::Argument &,
|
||||||
|
std::vector<buffer::Line> *
|
||||||
|
) {
|
||||||
|
b.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value mrb_bed_unregister(mrb_state *mrb, mrb_value) {
|
||||||
|
auto &ctx = *(BEd *)mrb->ud;
|
||||||
|
mrb_sym r_cmd_name;
|
||||||
|
mrb_get_args(mrb, "n", &r_cmd_name);
|
||||||
|
mrb_int cmd_name_len;
|
||||||
|
const char *name = mrb_sym_name_len(mrb, r_cmd_name, &cmd_name_len);
|
||||||
|
std::string_view cmd_name(name, cmd_name_len);
|
||||||
|
ctx.functions.remove(cmd_name);
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
void register_basic(BEd &ctx) {
|
void register_basic(BEd &ctx) {
|
||||||
auto *bed_error =
|
auto *bed_error =
|
||||||
mrb_define_class(ctx.mrb, "EdError", mrb_exc_get_id(ctx.mrb, MRB_ERROR_SYM(RuntimeError)));
|
mrb_define_class(ctx.mrb, "EdError", mrb_exc_get_id(ctx.mrb, MRB_ERROR_SYM(RuntimeError)));
|
||||||
mrb_define_class(ctx.mrb, "FatalError", bed_error);
|
mrb_define_class(ctx.mrb, "FatalError", bed_error);
|
||||||
|
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "exit", mrb_bed_exit, MRB_ARGS_NONE());
|
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "exit", mrb_bed_exit, MRB_ARGS_NONE());
|
||||||
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "handle", mrb_bed_handle, MRB_ARGS_REQ(1));
|
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "handle", mrb_bed_handle, MRB_ARGS_REQ(1));
|
||||||
|
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "register", mrb_bed_register, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
|
||||||
|
mrb_define_method(ctx.mrb, ctx.mrb->kernel_module, "unregister", mrb_bed_unregister, MRB_ARGS_REQ(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(BEd &ctx, const std::string &str) {
|
void run(BEd &ctx, const std::string &str) {
|
||||||
|
|||||||
Reference in New Issue
Block a user