diff --git a/include/internal/scripting/ruby.h b/include/internal/scripting/ruby.h index d8a4fd1..38640ac 100644 --- a/include/internal/scripting/ruby.h +++ b/include/internal/scripting/ruby.h @@ -120,5 +120,5 @@ struct Block { }; void register_basic(BEd &ctx); -void run(BEd &ctx, const std::string &str); +std::string run(BEd &ctx, const std::string &str); }; // namespace bed::internal::scripting diff --git a/samples/bed.rb b/samples/bed.rb new file mode 100644 index 0000000..b017f46 --- /dev/null +++ b/samples/bed.rb @@ -0,0 +1,3 @@ +register :happy, address: :none do + puts "be nice" +end diff --git a/src/internal/functions/extended.cc b/src/internal/functions/extended.cc index 25d4025..fdc07dd 100644 --- a/src/internal/functions/extended.cc +++ b/src/internal/functions/extended.cc @@ -176,8 +176,8 @@ void Function::register_extented(BEd &ctx) { .address_kind = Function::AddressKind::Range, .argument_kind = Function::ArgumentKind::Ruby, .input_mode = Function::InputMode::None, - .desc = "Execute some ruby code", - .default_address = "", + .desc = "Execute given ruby code.", + .default_address = "0,0", .accept_zero = true, .pre_text_mode = nullptr, .handle = []( @@ -193,7 +193,30 @@ void Function::register_extented(BEd &ctx) { + ";$END=" + std::to_string(addr.end) + ";$BUFNAME=\"" + addr.buffername + "\""; scripting::run(ctx, pre_code); - scripting::run(ctx, arg.cmd); + auto line = scripting::run(ctx, arg.cmd); + ctx.io.write("=> ", 3); + auto parser = syntax::MiniParser( + *ctx.languages["ruby"], + vase::Shard::from_string(line.data(), line.size(), true), + nullptr + ); + const auto &tokens = parser.lines[0].second; + uint32_t cursor = 0; + for (const auto &token : tokens) { + const uint32_t start = token.start; + const uint32_t end = token.end; + if (start > line.size() || end > line.size()) + break; + if (cursor < start) + ctx.io.write(line.data() + cursor, start - cursor); + ctx.io.apply(token.type); + ctx.io.write(line.data() + start, end - start); + ctx.io.reset(); + cursor = end; + } + if (cursor < line.size()) + ctx.io.write(line.data() + cursor, line.size() - cursor); + ctx.io.write_line(""); }, } ); @@ -204,7 +227,7 @@ void Function::register_extented(BEd &ctx) { .argument_kind = Function::ArgumentKind::None, .input_mode = Function::InputMode::None, .desc = "Execute addressed lines as ruby code.", - .default_address = ".,.", + .default_address = "1,$", .accept_zero = false, .pre_text_mode = nullptr, .handle = []( @@ -230,38 +253,6 @@ void Function::register_extented(BEd &ctx) { }, } ); - ctx.functions.insert( - "```", - Function{ - .address_kind = Function::AddressKind::Range, - .argument_kind = Function::ArgumentKind::None, - .input_mode = Function::InputMode::Text, - .desc = "Execute some ruby code (taken from text mode)", - .default_address = "", - .accept_zero = true, - .pre_text_mode = []( - BEd &ctx, - const buffer::Address &, - const Argument & - ) -> std::tuple { - return {nullptr, ctx.languages["ruby"], nullptr}; - }, - .handle = []( - BEd &ctx, - const buffer::Address &addr_, - vase::Shard *code, - const Argument &, - std::vector * - ) { - auto &addr = std::get(addr_); - auto pre_code = "$START=" + std::to_string(addr.start) - + ";$END=" + std::to_string(addr.end) - + ";$BUFNAME=\"" + addr.buffername + "\""; - scripting::run(ctx, pre_code); - scripting::run(ctx, vase::to_string(code)); - vase::Shard::release(code); }, - } - ); ctx.functions.insert( "echo", Function{ diff --git a/src/internal/scripting/ruby.cc b/src/internal/scripting/ruby.cc index e45ef39..b136e71 100644 --- a/src/internal/scripting/ruby.cc +++ b/src/internal/scripting/ruby.cc @@ -115,11 +115,14 @@ void register_basic(BEd &ctx) { mrb_define_method(mrb, mrb->kernel_module, "unregister", mrb_bed_unregister, MRB_ARGS_REQ(1)); } -void run(BEd &ctx, const std::string &str) { +std::string run(BEd &ctx, const std::string &str) { mrb_state *mrb = ctx.mrb.state; - mrb_load_nstring(mrb, str.data(), str.size()); - if (!mrb->exc) - return; + mrb_value result = mrb_load_nstring(mrb, str.data(), str.size()); + if (!mrb->exc) { + mrb_value inspected = mrb_funcall(mrb, result, "inspect", 0); + std::string output(RSTRING_PTR(inspected), RSTRING_LEN(inspected)); + return output; + } mrb_value exc = mrb_obj_value(mrb->exc); mrb_value msg = mrb_funcall(mrb, exc, "message", 0); std::string error;