639 lines
21 KiB
C++
Executable File
639 lines
21 KiB
C++
Executable File
#include "io/sysio.h"
|
|
#include "main.h"
|
|
#include "pch.h"
|
|
#include "ruby/decl.h"
|
|
#include "ruby/ruby_compiled.h"
|
|
#include "utils/utils.h"
|
|
|
|
std::unordered_map<std::string, std::pair<mrb_value, mrb_value>>
|
|
custom_highlighters;
|
|
|
|
struct R_ThemeEntry {
|
|
std::string key;
|
|
uint32_t fg = 0xFFFFFF;
|
|
uint32_t bg = 0x000000;
|
|
bool italic = false;
|
|
bool bold = false;
|
|
bool underline = false;
|
|
bool strikethrough = false;
|
|
};
|
|
|
|
struct R_Language {
|
|
std::string name;
|
|
uint32_t color = 0xFFFFFF;
|
|
std::vector<std::string> extensions;
|
|
std::vector<std::string> filenames;
|
|
std::string lsp_command; // link to LSP by name
|
|
};
|
|
|
|
mrb_state *mrb = nullptr;
|
|
RClass *C_module;
|
|
fs::path ruby_config_path;
|
|
|
|
void ruby_start() {
|
|
mrb = mrb_open();
|
|
if (!mrb) {
|
|
fprintf(stderr, "Failed to init mruby\n");
|
|
return;
|
|
}
|
|
fs::path exe_dir = get_exe_dir();
|
|
std::vector<fs::path> candidates;
|
|
const char *crib_config = std::getenv("CRIB_CONFIG");
|
|
if (crib_config)
|
|
candidates.emplace_back(fs::path(crib_config));
|
|
const char *crib_config_dir = std::getenv("CRIB_CONFIG_DIR");
|
|
if (crib_config_dir) {
|
|
candidates.emplace_back(fs::path(crib_config_dir) / "crib.rb");
|
|
candidates.emplace_back(fs::path(crib_config_dir) / "main.rb");
|
|
}
|
|
candidates.emplace_back("./crib.rb");
|
|
const char *xdg = std::getenv("XDG_CONFIG_HOME");
|
|
const char *home = std::getenv("HOME");
|
|
if (xdg) {
|
|
candidates.emplace_back(fs::path(xdg) / "crib/crib.rb");
|
|
candidates.emplace_back(fs::path(xdg) / "crib/main.rb");
|
|
candidates.emplace_back(fs::path(xdg) / "crib.rb");
|
|
}
|
|
if (home) {
|
|
fs::path base = fs::path(home) / ".config";
|
|
candidates.emplace_back(base / "crib/crib.rb");
|
|
candidates.emplace_back(base / "crib/main.rb");
|
|
candidates.emplace_back(base / "crib.rb");
|
|
}
|
|
mrb_load_irep(mrb, _tmp___crib_precompiled_mrb);
|
|
C_module = mrb_module_get(mrb, "C");
|
|
setup_ruby_bindings(mrb, C_module);
|
|
for (const auto &p : candidates) {
|
|
if (fs::exists(p)) {
|
|
FILE *f = fopen(p.string().c_str(), "r");
|
|
if (f) {
|
|
ruby_config_path = p;
|
|
mrb_load_file(mrb, f);
|
|
if (mrb->exc)
|
|
exit(1);
|
|
fclose(f);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_startup", 0);
|
|
if (!mrb_nil_p(block))
|
|
mrb_funcall(mrb, block, "call", 0);
|
|
mrb_garbage_collect(mrb);
|
|
}
|
|
|
|
static mrb_value sym_fg;
|
|
static mrb_value sym_bg;
|
|
static mrb_value sym_flags;
|
|
static mrb_value sym_start;
|
|
static mrb_value sym_length;
|
|
static mrb_value sym_mode;
|
|
static mrb_value sym_data;
|
|
static mrb_value sym_foldername;
|
|
static mrb_value sym_width;
|
|
static mrb_value sym_normal;
|
|
static mrb_value sym_insert;
|
|
static mrb_value sym_select;
|
|
static mrb_value sym_runner;
|
|
static mrb_value sym_jumper;
|
|
|
|
inline void initialize_symbols() {
|
|
sym_fg = mrb_symbol_value(mrb_intern_cstr(mrb, "fg"));
|
|
sym_bg = mrb_symbol_value(mrb_intern_cstr(mrb, "bg"));
|
|
sym_flags = mrb_symbol_value(mrb_intern_cstr(mrb, "flags"));
|
|
sym_start = mrb_symbol_value(mrb_intern_cstr(mrb, "start"));
|
|
sym_length = mrb_symbol_value(mrb_intern_cstr(mrb, "length"));
|
|
sym_mode = mrb_symbol_value(mrb_intern_cstr(mrb, "mode"));
|
|
sym_data = mrb_symbol_value(mrb_intern_cstr(mrb, "data"));
|
|
sym_foldername = mrb_symbol_value(mrb_intern_cstr(mrb, "foldername"));
|
|
sym_width = mrb_symbol_value(mrb_intern_cstr(mrb, "width"));
|
|
sym_normal = mrb_symbol_value(mrb_intern_cstr(mrb, "normal"));
|
|
sym_insert = mrb_symbol_value(mrb_intern_cstr(mrb, "insert"));
|
|
sym_select = mrb_symbol_value(mrb_intern_cstr(mrb, "select"));
|
|
sym_runner = mrb_symbol_value(mrb_intern_cstr(mrb, "runner"));
|
|
sym_jumper = mrb_symbol_value(mrb_intern_cstr(mrb, "jumper"));
|
|
}
|
|
|
|
inline static std::vector<BarLight>
|
|
convert_highlights(mrb_state *mrb, mrb_value highlights_val) {
|
|
std::vector<BarLight> result;
|
|
if (!mrb_array_p(highlights_val))
|
|
return result;
|
|
mrb_int len = RARRAY_LEN(highlights_val);
|
|
for (mrb_int i = 0; i < len; i++) {
|
|
mrb_value item = mrb_ary_ref(mrb, highlights_val, i);
|
|
if (!mrb_hash_p(item))
|
|
continue;
|
|
mrb_value fg_v = mrb_hash_get(mrb, item, sym_fg);
|
|
mrb_value bg_v = mrb_hash_get(mrb, item, sym_bg);
|
|
mrb_value flags_v = mrb_hash_get(mrb, item, sym_flags);
|
|
mrb_value start_v = mrb_hash_get(mrb, item, sym_start);
|
|
mrb_value length_v = mrb_hash_get(mrb, item, sym_length);
|
|
BarLight bl{};
|
|
if (!mrb_nil_p(fg_v))
|
|
bl.highlight.fg = (uint32_t)mrb_fixnum(fg_v);
|
|
if (!mrb_nil_p(bg_v))
|
|
bl.highlight.bg = (uint32_t)mrb_fixnum(bg_v);
|
|
if (!mrb_nil_p(flags_v))
|
|
bl.highlight.flags = (uint32_t)mrb_fixnum(flags_v);
|
|
uint32_t start = !mrb_nil_p(start_v) ? (uint32_t)mrb_fixnum(start_v) : 0;
|
|
uint32_t length = !mrb_nil_p(length_v) ? (uint32_t)mrb_fixnum(length_v) : 0;
|
|
bl.start = start;
|
|
bl.end = start + length;
|
|
result.push_back(bl);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BarLine bar_contents(uint8_t mode, uint32_t width, std::string foldername,
|
|
Window *window) {
|
|
BarLine bar_line;
|
|
static bool initialed = false;
|
|
if (!initialed) {
|
|
initialize_symbols();
|
|
initialed = true;
|
|
}
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
mrb_value info = mrb_hash_new(mrb);
|
|
mrb_value val_mode;
|
|
switch (mode) {
|
|
case NORMAL:
|
|
val_mode = sym_normal;
|
|
break;
|
|
case INSERT:
|
|
val_mode = sym_insert;
|
|
break;
|
|
case SELECT:
|
|
val_mode = sym_select;
|
|
break;
|
|
case RUNNER:
|
|
val_mode = sym_runner;
|
|
break;
|
|
case JUMPER:
|
|
val_mode = sym_jumper;
|
|
break;
|
|
}
|
|
mrb_hash_set(mrb, info, sym_mode, val_mode);
|
|
mrb_value val_foldername =
|
|
mrb_str_new(mrb, foldername.c_str(), foldername.length());
|
|
mrb_hash_set(mrb, info, sym_foldername, val_foldername);
|
|
std::array<std::string, 5> arr = window->bar_info();
|
|
mrb_value ary = mrb_ary_new(mrb);
|
|
mrb_ary_push(mrb, ary, mrb_str_new(mrb, arr[0].c_str(), arr[0].length()));
|
|
mrb_ary_push(mrb, ary, mrb_str_new(mrb, arr[1].c_str(), arr[1].length()));
|
|
mrb_ary_push(mrb, ary, mrb_str_new(mrb, arr[2].c_str(), arr[2].length()));
|
|
mrb_ary_push(mrb, ary, mrb_str_new(mrb, arr[3].c_str(), arr[3].length()));
|
|
mrb_ary_push(mrb, ary, mrb_str_new(mrb, arr[4].c_str(), arr[4].length()));
|
|
mrb_hash_set(mrb, info, sym_data, ary);
|
|
mrb_value val_width = mrb_fixnum_value(width);
|
|
mrb_hash_set(mrb, info, sym_width, val_width);
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_bar", 0);
|
|
mrb_value val_line = mrb_funcall(mrb, block, "call", 1, info);
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
mrb_value text_val = mrb_hash_get(
|
|
mrb, val_line, mrb_symbol_value(mrb_intern_cstr(mrb, "text")));
|
|
const char *ptr = RSTRING_PTR(text_val);
|
|
mrb_int len = RSTRING_LEN(text_val);
|
|
bar_line.line = std::string(ptr, len);
|
|
mrb_value highlights_val = mrb_hash_get(
|
|
mrb, val_line, mrb_symbol_value(mrb_intern_cstr(mrb, "highlights")));
|
|
bar_line.highlights = convert_highlights(mrb, highlights_val);
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return bar_line;
|
|
}
|
|
|
|
std::string serialize_value(mrb_state *mrb, mrb_value val) {
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
mrb_value marshal_module = mrb_obj_value(mrb_module_get(mrb, "Marshal"));
|
|
mrb_value dumped = mrb_funcall(mrb, marshal_module, "dump", 1, val);
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
std::string bytes(RSTRING_PTR(dumped), RSTRING_LEN(dumped));
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return bytes;
|
|
}
|
|
|
|
mrb_value deserialize_value(mrb_state *mrb, std::string bytes) {
|
|
if (bytes.empty())
|
|
return mrb_nil_value();
|
|
mrb_value marshal_module = mrb_obj_value(mrb_module_get(mrb, "Marshal"));
|
|
mrb_value val = mrb_funcall(mrb, marshal_module, "load", 1,
|
|
mrb_str_new(mrb, bytes.c_str(), bytes.length()));
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
void ruby_copy(const char *text, size_t len) {
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
if (C_module == nullptr)
|
|
return;
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_copy", 0);
|
|
if (!mrb_nil_p(block))
|
|
mrb_funcall(mrb, block, "call", 1, mrb_str_new(mrb, text, len));
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
}
|
|
|
|
std::string ruby_file_detect(std::string filename) {
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
if (C_module == nullptr)
|
|
return "";
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_file_detect", 0);
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
if (!mrb_nil_p(block)) {
|
|
mrb_value val =
|
|
mrb_funcall(mrb, block, "call", 1,
|
|
mrb_str_new(mrb, filename.c_str(), filename.length()));
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
mrb_value s_val = mrb_funcall(mrb, val, "to_s", 0);
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
if (mrb_string_p(s_val)) {
|
|
std::string result = std::string(RSTRING_PTR(s_val), RSTRING_LEN(s_val));
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return result;
|
|
}
|
|
}
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return "";
|
|
}
|
|
|
|
std::string ruby_paste() {
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
if (C_module == nullptr)
|
|
return "";
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_paste", 0);
|
|
if (!mrb_nil_p(block)) {
|
|
mrb_value val = mrb_funcall(mrb, block, "call", 0);
|
|
if (mrb->exc) {
|
|
end_screen();
|
|
fputs("Error when executing Ruby code:\n", stderr);
|
|
mrb_print_error(mrb);
|
|
mrb_close(mrb);
|
|
exit(1);
|
|
}
|
|
if (mrb_string_p(val)) {
|
|
std::string result = std::string(RSTRING_PTR(val), RSTRING_LEN(val));
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return result;
|
|
}
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return "";
|
|
}
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return "";
|
|
}
|
|
|
|
void ruby_shutdown() {
|
|
if (C_module == nullptr)
|
|
return;
|
|
mrb_value mod_val = mrb_obj_value(C_module);
|
|
mrb_value block = mrb_funcall(mrb, mod_val, "b_shutdown", 0);
|
|
if (!mrb_nil_p(block))
|
|
mrb_funcall(mrb, block, "call", 0);
|
|
mrb_close(mrb);
|
|
mrb = nullptr;
|
|
C_module = nullptr;
|
|
}
|
|
|
|
std::vector<std::string> array_to_vector(mrb_value ary) {
|
|
std::vector<std::string> result;
|
|
if (mrb_nil_p(ary) || mrb_type(ary) != MRB_TT_ARRAY)
|
|
return result;
|
|
mrb_int len = RARRAY_LEN(ary);
|
|
for (mrb_int i = 0; i < len; i++) {
|
|
mrb_value item = mrb_ary_ref(mrb, ary, i);
|
|
if (mrb_string_p(item))
|
|
result.push_back(std::string(RSTRING_PTR(item), RSTRING_LEN(item)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void load_custom_highlighters() {
|
|
if (!C_module)
|
|
return;
|
|
mrb_value mod_val = mrb_obj_value((struct RObject *)C_module);
|
|
mrb_value hashmap = mrb_funcall(mrb, mod_val, "highlighters", 0);
|
|
if (mrb_nil_p(hashmap) || mrb_type(hashmap) != MRB_TT_HASH)
|
|
return;
|
|
mrb_value keys = mrb_funcall(mrb, hashmap, "keys", 0);
|
|
mrb_int len = RARRAY_LEN(keys);
|
|
for (mrb_int i = 0; i < len; i++) {
|
|
mrb_value key_sym = mrb_ary_ref(mrb, keys, i);
|
|
mrb_sym sym_id = mrb_symbol(key_sym);
|
|
const char *key_cstr = mrb_sym_dump(mrb, sym_id);
|
|
std::string key(key_cstr);
|
|
mrb_value val_hash = mrb_hash_get(mrb, hashmap, key_sym);
|
|
if (mrb_nil_p(val_hash) || mrb_type(val_hash) != MRB_TT_HASH)
|
|
continue;
|
|
mrb_sym parser_sym = mrb_intern_lit(mrb, "parser");
|
|
mrb_sym matcher_sym = mrb_intern_lit(mrb, "matcher");
|
|
mrb_value parse_block =
|
|
mrb_hash_get(mrb, val_hash, mrb_symbol_value(parser_sym));
|
|
mrb_value match_block =
|
|
mrb_hash_get(mrb, val_hash, mrb_symbol_value(matcher_sym));
|
|
custom_highlighters[key] = {parse_block, match_block};
|
|
}
|
|
mrb_garbage_collect(mrb);
|
|
}
|
|
|
|
bool custom_compare(mrb_value match_block, std::string state1,
|
|
std::string state2) {
|
|
if (state1.empty() || state2.empty())
|
|
return false;
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
if (mrb_type(match_block) != MRB_TT_PROC)
|
|
return false;
|
|
mrb_value ret =
|
|
mrb_funcall(mrb, match_block, "call", 2, deserialize_value(mrb, state1),
|
|
deserialize_value(mrb, state2));
|
|
bool result = mrb_test(ret);
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return result;
|
|
}
|
|
|
|
std::string parse_custom(std::vector<Token> *tokens, mrb_value parser_block,
|
|
const char *line, uint32_t len, std::string state,
|
|
uint32_t c_line) {
|
|
int ai = mrb_gc_arena_save(mrb);
|
|
tokens->clear();
|
|
if (mrb_nil_p(parser_block))
|
|
return "";
|
|
mrb_value ruby_line = mrb_str_new(mrb, line, len);
|
|
mrb_value line_idx = mrb_fixnum_value(c_line);
|
|
mrb_value tokens_and_state_hash =
|
|
mrb_funcall(mrb, parser_block, "call", 3, ruby_line,
|
|
deserialize_value(mrb, state), line_idx);
|
|
mrb_sym tokens_sym = mrb_intern_lit(mrb, "tokens");
|
|
mrb_value tokens_rb =
|
|
mrb_hash_get(mrb, tokens_and_state_hash, mrb_symbol_value(tokens_sym));
|
|
if (mrb_type(tokens_rb) == MRB_TT_ARRAY) {
|
|
mrb_int len_tokens = RARRAY_LEN(tokens_rb);
|
|
for (mrb_int i = 0; i < len_tokens; i++) {
|
|
mrb_value token = mrb_ary_ref(mrb, tokens_rb, i);
|
|
Token tok;
|
|
tok.type = (TokenKind)mrb_fixnum(mrb_hash_get(
|
|
mrb, token, mrb_symbol_value(mrb_intern_lit(mrb, "type"))));
|
|
tok.start = (uint32_t)mrb_fixnum(mrb_hash_get(
|
|
mrb, token, mrb_symbol_value(mrb_intern_lit(mrb, "start"))));
|
|
tok.end = (uint32_t)mrb_fixnum(mrb_hash_get(
|
|
mrb, token, mrb_symbol_value(mrb_intern_lit(mrb, "end"))));
|
|
if (tok.type < TokenKind::Count && tok.end > tok.start && tok.end <= len)
|
|
tokens->push_back(tok);
|
|
}
|
|
}
|
|
mrb_sym state_sym = mrb_intern_lit(mrb, "state");
|
|
mrb_value state_rb =
|
|
mrb_hash_get(mrb, tokens_and_state_hash, mrb_symbol_value(state_sym));
|
|
std::string result;
|
|
if (mrb_type(state_rb) == MRB_TT_STRING)
|
|
result = std::string(RSTRING_PTR(state_rb), RSTRING_LEN(state_rb));
|
|
mrb_gc_arena_restore(mrb, ai);
|
|
return result;
|
|
}
|
|
|
|
static std::vector<R_ThemeEntry> read_theme() {
|
|
std::vector<R_ThemeEntry> result;
|
|
if (!C_module)
|
|
return result;
|
|
mrb_value mod_val = mrb_obj_value((struct RObject *)C_module);
|
|
mrb_value theme_hash = mrb_funcall(mrb, mod_val, "theme", 0);
|
|
if (mrb_nil_p(theme_hash) || mrb_type(theme_hash) != MRB_TT_HASH)
|
|
return result;
|
|
mrb_value keys = mrb_funcall(mrb, theme_hash, "keys", 0);
|
|
mrb_int len_keys = RARRAY_LEN(keys);
|
|
for (mrb_int i = 0; i < len_keys; i++) {
|
|
mrb_value key_sym = mrb_ary_ref(mrb, keys, i);
|
|
mrb_sym sym_id = mrb_symbol(key_sym);
|
|
const char *key_cstr = mrb_sym_dump(mrb, sym_id);
|
|
std::string key(key_cstr);
|
|
mrb_value val_hash = mrb_hash_get(mrb, theme_hash, key_sym);
|
|
if (mrb_nil_p(val_hash) || mrb_type(val_hash) != MRB_TT_HASH)
|
|
continue;
|
|
R_ThemeEntry entry;
|
|
entry.key = key;
|
|
mrb_value fg = mrb_hash_get(mrb, val_hash,
|
|
mrb_symbol_value(mrb_intern_lit(mrb, "fg")));
|
|
mrb_value bg = mrb_hash_get(mrb, val_hash,
|
|
mrb_symbol_value(mrb_intern_lit(mrb, "bg")));
|
|
mrb_value italic = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "italic")));
|
|
mrb_value bold = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "bold")));
|
|
mrb_value underline = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "underline")));
|
|
mrb_value strikethrough = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "strikethrough")));
|
|
if (!mrb_nil_p(fg))
|
|
entry.fg = (uint32_t)mrb_fixnum(fg);
|
|
if (!mrb_nil_p(bg))
|
|
entry.bg = (uint32_t)mrb_fixnum(bg);
|
|
if (!mrb_nil_p(italic))
|
|
entry.italic = mrb_test(italic);
|
|
if (!mrb_nil_p(bold))
|
|
entry.bold = mrb_test(bold);
|
|
if (!mrb_nil_p(underline))
|
|
entry.underline = mrb_test(underline);
|
|
if (!mrb_nil_p(strikethrough))
|
|
entry.strikethrough = mrb_test(strikethrough);
|
|
result.push_back(entry);
|
|
}
|
|
mrb_garbage_collect(mrb);
|
|
return result;
|
|
}
|
|
|
|
void load_theme() {
|
|
std::vector<R_ThemeEntry> entries = read_theme();
|
|
Highlight default_hl = {0xFFFFFF, 0, 0};
|
|
for (auto &entry : entries) {
|
|
if (entry.key == "default") {
|
|
default_hl.fg = entry.fg;
|
|
default_hl.bg = entry.bg;
|
|
if (entry.italic)
|
|
default_hl.flags |= CF_ITALIC;
|
|
if (entry.bold)
|
|
default_hl.flags |= CF_BOLD;
|
|
if (entry.underline)
|
|
default_hl.flags |= CF_UNDERLINE;
|
|
if (entry.strikethrough)
|
|
default_hl.flags |= CF_STRIKETHROUGH;
|
|
break;
|
|
}
|
|
}
|
|
for (auto &hl : highlights)
|
|
hl = default_hl;
|
|
for (auto &entry : entries) {
|
|
if (entry.key == "default")
|
|
continue;
|
|
std::string key = "k_" + entry.key;
|
|
for (char &c : key)
|
|
c = std::toupper(static_cast<unsigned char>(c));
|
|
auto it = kind_map.find(key);
|
|
if (it == kind_map.end())
|
|
continue;
|
|
Highlight hl = {0xFFFFFF, 0, 0};
|
|
hl.fg = entry.fg;
|
|
hl.bg = entry.bg;
|
|
if (entry.italic)
|
|
hl.flags |= CF_ITALIC;
|
|
if (entry.bold)
|
|
hl.flags |= CF_BOLD;
|
|
if (entry.underline)
|
|
hl.flags |= CF_UNDERLINE;
|
|
if (entry.strikethrough)
|
|
hl.flags |= CF_STRIKETHROUGH;
|
|
highlights[static_cast<uint8_t>(it->second)] = hl;
|
|
}
|
|
}
|
|
|
|
std::vector<LSP> read_lsps() {
|
|
std::vector<LSP> result;
|
|
if (!C_module)
|
|
return result;
|
|
mrb_value mod_val = mrb_obj_value((struct RObject *)C_module);
|
|
mrb_value lsp_hash = mrb_funcall(mrb, mod_val, "lsp_config", 0);
|
|
if (mrb_nil_p(lsp_hash) || mrb_type(lsp_hash) != MRB_TT_HASH)
|
|
return result;
|
|
mrb_value keys = mrb_funcall(mrb, lsp_hash, "keys", 0);
|
|
mrb_int len_keys = RARRAY_LEN(keys);
|
|
for (mrb_int i = 0; i < len_keys; i++) {
|
|
mrb_value key = mrb_ary_ref(mrb, keys, i);
|
|
std::string cmd;
|
|
if (mrb_string_p(key))
|
|
cmd = std::string(RSTRING_PTR(key), RSTRING_LEN(key));
|
|
else if (mrb_symbol_p(key))
|
|
cmd = std::string(mrb_sym_dump(mrb, mrb_symbol(key)));
|
|
mrb_value args_array = mrb_hash_get(mrb, lsp_hash, key);
|
|
std::vector<std::string> args = array_to_vector(args_array);
|
|
result.push_back({cmd, args});
|
|
}
|
|
mrb_garbage_collect(mrb);
|
|
return result;
|
|
}
|
|
|
|
std::vector<R_Language> read_languages() {
|
|
std::vector<R_Language> result;
|
|
if (!C_module)
|
|
return result;
|
|
mrb_value mod_val = mrb_obj_value((struct RObject *)C_module);
|
|
mrb_value lang_hash = mrb_funcall(mrb, mod_val, "languages", 0);
|
|
if (mrb_nil_p(lang_hash) || mrb_type(lang_hash) != MRB_TT_HASH)
|
|
return result;
|
|
mrb_value keys = mrb_funcall(mrb, lang_hash, "keys", 0);
|
|
mrb_int len_keys = RARRAY_LEN(keys);
|
|
for (mrb_int i = 0; i < len_keys; i++) {
|
|
mrb_value key = mrb_ary_ref(mrb, keys, i);
|
|
mrb_value val_hash = mrb_hash_get(mrb, lang_hash, key);
|
|
if (mrb_nil_p(val_hash) || mrb_type(val_hash) != MRB_TT_HASH)
|
|
continue;
|
|
R_Language lang;
|
|
if (mrb_symbol_p(key))
|
|
lang.name = std::string(mrb_sym_dump(mrb, mrb_symbol(key)));
|
|
else if (mrb_string_p(key))
|
|
lang.name = std::string(RSTRING_PTR(key), RSTRING_LEN(key));
|
|
mrb_value fg = mrb_hash_get(mrb, val_hash,
|
|
mrb_symbol_value(mrb_intern_lit(mrb, "color")));
|
|
mrb_value extensions = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "extensions")));
|
|
mrb_value filenames = mrb_hash_get(
|
|
mrb, val_hash, mrb_symbol_value(mrb_intern_lit(mrb, "filenames")));
|
|
mrb_value lsp = mrb_hash_get(mrb, val_hash,
|
|
mrb_symbol_value(mrb_intern_lit(mrb, "lsp")));
|
|
if (!mrb_nil_p(fg))
|
|
lang.color = (uint32_t)mrb_fixnum(fg);
|
|
lang.extensions = array_to_vector(extensions);
|
|
if (!mrb_nil_p(filenames))
|
|
lang.filenames = array_to_vector(filenames);
|
|
if (!mrb_nil_p(lsp))
|
|
lang.lsp_command = std::string(RSTRING_PTR(lsp), RSTRING_LEN(lsp));
|
|
result.push_back(lang);
|
|
}
|
|
mrb_garbage_collect(mrb);
|
|
return result;
|
|
}
|
|
|
|
void load_languages_info() {
|
|
auto langs = read_languages();
|
|
auto lsps_t = read_lsps();
|
|
languages.clear();
|
|
for (auto &lang : langs) {
|
|
Language l;
|
|
l.name = lang.name;
|
|
l.color = lang.color;
|
|
l.lsp_name = lang.lsp_command;
|
|
languages[lang.name] = l;
|
|
for (auto &ext : lang.extensions)
|
|
language_extensions[ext] = lang.name;
|
|
// TODO: seperate extensions and filenames
|
|
for (auto &filename : lang.filenames)
|
|
language_extensions[filename] = lang.name;
|
|
}
|
|
for (auto &lsp : lsps_t)
|
|
lsps[lsp.command] = lsp;
|
|
}
|
|
|
|
uint8_t read_line_endings() {
|
|
if (!C_module)
|
|
return 1;
|
|
mrb_value mod_val = mrb_obj_value((struct RObject *)C_module);
|
|
mrb_value le = mrb_funcall(mrb, mod_val, "line_endings", 0);
|
|
if (!mrb_symbol_p(le))
|
|
return 1;
|
|
uint8_t flags = 1;
|
|
const char *name = mrb_sym_dump(mrb, mrb_symbol(le));
|
|
if (std::strcmp(name, "unix") == 0)
|
|
flags = 0b01;
|
|
else if (std::strcmp(name, "windows") == 0)
|
|
flags = 0b00;
|
|
else if (std::strcmp(name, "auto_unix") == 0)
|
|
flags = 0b11;
|
|
else if (std::strcmp(name, "auto_windows") == 0)
|
|
flags = 0b10;
|
|
return flags;
|
|
}
|