Add basic scripting support.
- Fix certain bugs in ruby parser - And a lot more cleanup/minor fixes.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "internal/functions/suffixes.h"
|
||||
#include "internal/io/io.h"
|
||||
#include "internal/marks/marks.h"
|
||||
#include "internal/scripting/ruby.h"
|
||||
#include "internal/theme/theme.h"
|
||||
#include "internal/ui/command.h"
|
||||
#include "internal/ui/text_mode.h"
|
||||
@@ -21,6 +22,8 @@ struct BEd {
|
||||
std::unordered_map<std::string, internal::syntax::Language *> languages;
|
||||
internal::io::IO io;
|
||||
internal::vase::AppendStorage append{"/tmp"};
|
||||
mrb_state *mrb = nullptr;
|
||||
int arena;
|
||||
|
||||
bool help_mode = false;
|
||||
bool prompt_mode = true;
|
||||
|
||||
@@ -14,8 +14,8 @@ struct HistoryItem {
|
||||
|
||||
struct GenericBuffer : ShardBuffer {
|
||||
uint64_t base_version{0};
|
||||
std::chrono::system_clock::time_point timestamp;
|
||||
std::string action;
|
||||
std::chrono::system_clock::time_point timestamp{std::chrono::system_clock::now()};
|
||||
std::string action{"Created buffer."};
|
||||
std::filesystem::path save_path{};
|
||||
std::vector<HistoryItem> undo_stack;
|
||||
std::vector<HistoryItem> redo_stack;
|
||||
@@ -24,6 +24,7 @@ struct GenericBuffer : ShardBuffer {
|
||||
: ShardBuffer(name, nullptr, nullptr, Kind::Generic) {}
|
||||
~GenericBuffer();
|
||||
|
||||
void language(BEd &ctx, std::string name);
|
||||
void list_history(BEd &ctx);
|
||||
ReadonlyBuffer *get_history(uint64_t version);
|
||||
void snapshot(std::string action);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace bed::internal::scripting {
|
||||
struct Block {
|
||||
mrb_value proc;
|
||||
mrb_state *mrb;
|
||||
|
||||
Block(mrb_state *mrb, mrb_value proc)
|
||||
: proc(proc), mrb(mrb) {
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
|
||||
Block() : proc(mrb_nil_value()) {}
|
||||
|
||||
~Block() {
|
||||
if (!mrb_nil_p(proc))
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
}
|
||||
|
||||
void set_proc(mrb_value new_proc) {
|
||||
if (!mrb_nil_p(proc))
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
proc = new_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 {
|
||||
if (mrb_nil_p(proc))
|
||||
return mrb_nil_value();
|
||||
mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
void register_basic(BEd &ctx);
|
||||
void run(BEd &ctx, const std::string &str);
|
||||
}; // namespace bed::internal::scripting
|
||||
@@ -48,6 +48,7 @@ struct ParseState {
|
||||
uint64_t line, uint64_t original, uint64_t final
|
||||
);
|
||||
static ParseState *concat(Language &lang, ParseState *a, ParseState *b);
|
||||
static void *state_before(Language &lang, ParseState *root, vase::Shard *vase, uint64_t line);
|
||||
};
|
||||
|
||||
struct ParseStateBranch : ParseState {
|
||||
@@ -83,18 +84,25 @@ struct ParsePieceBuilder {
|
||||
std::vector<ParseState *> pieces;
|
||||
std::vector<uint16_t> blocks;
|
||||
void *piece_state{nullptr};
|
||||
void *prev_state{nullptr};
|
||||
uint64_t chunk_start{0};
|
||||
uint64_t chunk_lines{0};
|
||||
ParsePieceBuilder(Language &lang, uint64_t first_line)
|
||||
: lang(lang), chunk_start(first_line) {}
|
||||
void add(
|
||||
void *state,
|
||||
uint64_t line,
|
||||
const std::vector<ParseEvent> &events
|
||||
) {
|
||||
ParsePieceBuilder(Language &lang, uint64_t first_line, void *entry_state)
|
||||
: lang(lang), chunk_start(first_line) {
|
||||
prev_state = lang.copy(entry_state);
|
||||
}
|
||||
~ParsePieceBuilder() {
|
||||
if (prev_state)
|
||||
lang.destroy(prev_state);
|
||||
if (piece_state)
|
||||
lang.destroy(piece_state);
|
||||
}
|
||||
ParsePieceBuilder(const ParsePieceBuilder &) = delete;
|
||||
ParsePieceBuilder &operator=(const ParsePieceBuilder &) = delete;
|
||||
void add(void *state, uint64_t line, const std::vector<ParseEvent> &events) {
|
||||
if (chunk_lines == 0) {
|
||||
chunk_start = line;
|
||||
piece_state = lang.copy(state);
|
||||
piece_state = lang.copy(prev_state);
|
||||
}
|
||||
for (const auto &ev : events) {
|
||||
blocks.push_back(
|
||||
@@ -103,6 +111,9 @@ struct ParsePieceBuilder {
|
||||
);
|
||||
}
|
||||
++chunk_lines;
|
||||
if (prev_state)
|
||||
lang.destroy(prev_state);
|
||||
prev_state = lang.copy(state);
|
||||
if (chunk_lines == ParseStateLeaf::MAX_CHUNK)
|
||||
flush();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ ParserSnapshot make_parser(vase::Shard *vase, uint64_t lines, Language *lang);
|
||||
ParserSnapshot retain(const ParserSnapshot &snap);
|
||||
void release(ParserSnapshot &snap);
|
||||
|
||||
void *state_before(const ParserSnapshot &snap, vase::Shard *vase, uint64_t line);
|
||||
uint64_t next_closing(const ParserSnapshot &snap, uint64_t line);
|
||||
uint64_t prev_opening(const ParserSnapshot &snap, uint64_t line);
|
||||
|
||||
|
||||
@@ -4,10 +4,29 @@
|
||||
|
||||
#include <mruby.h>
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/boxing_word.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/compile.h>
|
||||
#include <mruby/data.h>
|
||||
#include <mruby/dump.h>
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/hash.h>
|
||||
#include <mruby/internal.h>
|
||||
#include <mruby/irep.h>
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/object.h>
|
||||
#include <mruby/opcode.h>
|
||||
#include <mruby/presym.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/range.h>
|
||||
#include <mruby/re.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/throw.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/variable.h>
|
||||
#include <mruby/version.h>
|
||||
#include <pcre2.h>
|
||||
extern "C" {
|
||||
#include <grapheme.h>
|
||||
|
||||
Reference in New Issue
Block a user