diff --git a/include/bed.h b/include/bed.h index de5813a..2313c2d 100644 --- a/include/bed.h +++ b/include/bed.h @@ -15,6 +15,7 @@ struct BEd { internal::commands::Command eof_op; std::array, 26> suffixes; internal::theme::Theme theme; + std::unordered_map languages; bool help_mode = false; std::string last_help = ""; diff --git a/include/internal/buffer/buffer.h b/include/internal/buffer/buffer.h index b3d208a..8a9fe9a 100644 --- a/include/internal/buffer/buffer.h +++ b/include/internal/buffer/buffer.h @@ -11,8 +11,8 @@ namespace bed::internal::buffer { struct Buffer { vase::Vase vase; marks::MarksEngine marks; - syntax::Language lang; - syntax::Parser parser; + std::string language; + std::optional parser; uint64_t line = 0; bool modified; std::filesystem::path save_path = ""; diff --git a/include/internal/syntax/decl.h b/include/internal/syntax/decl.h index 9f7ba9d..903a69c 100644 --- a/include/internal/syntax/decl.h +++ b/include/internal/syntax/decl.h @@ -164,7 +164,7 @@ struct TreeCursor { } }; -/*struct Symbol { +struct Symbol { uint64_t definition; std::vector references; }; @@ -178,5 +178,5 @@ struct Scope { uint32_t type; trie::Trie symbols; std::vector> children; -};*/ +}; } // namespace bed::internal::syntax diff --git a/include/internal/syntax/parser.h b/include/internal/syntax/parser.h index c349eb4..c87d9b6 100644 --- a/include/internal/syntax/parser.h +++ b/include/internal/syntax/parser.h @@ -6,12 +6,17 @@ namespace bed::internal::syntax { struct Parser { - ParseState *root; - Language ⟨ + static constexpr const uint64_t MAX_CHUNK = 256; - Parser(vase::Vase &, uint64_t, Language &); + ParseState *root; + Language lang; + + Parser(vase::Vase &, uint64_t, Language); ~Parser(); - void reset(vase::Vase &, uint64_t, Language &); + Parser(const Parser &) = delete; + Parser &operator=(const Parser &) = delete; + + void reset(vase::Vase &, uint64_t, Language); void erase(vase::Vase &, uint64_t, uint64_t); void insert(vase::Vase &, uint64_t, uint64_t); void modify(vase::Vase &, uint64_t, uint64_t); @@ -19,8 +24,9 @@ struct Parser { std::pair split_tree(ParseState *node, uint64_t line); ParseState *join_tree(ParseState *a, ParseState *b); - // Scope root; - // Scope &get_scope(uint64_t); + Scope scope_root; + Scope &get_scope(uint64_t); + struct Iterator { Parser *p; std::optional it; diff --git a/src/internal/buffer/buffer.cc b/src/internal/buffer/buffer.cc index b96f303..6d2db04 100644 --- a/src/internal/buffer/buffer.cc +++ b/src/internal/buffer/buffer.cc @@ -2,17 +2,14 @@ #include "bed.h" namespace bed::internal::buffer { -Buffer::Buffer() - : vase("/tmp"), lang(syntax::ruby::lang_ruby()), - parser(vase, vase.lines(), lang) { +Buffer::Buffer() : vase("/tmp") { + parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby()); line = vase.lines(); modified = false; } -Buffer::Buffer(std::string command) - : vase(command, "/tmp"), - lang(syntax::ruby::lang_ruby()), - parser(vase, vase.lines(), lang) { +Buffer::Buffer(std::string command) : vase(command, "/tmp") { + parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby()); line = vase.lines(); if (!line) return; @@ -21,10 +18,8 @@ Buffer::Buffer(std::string command) modified = false; } -Buffer::Buffer(std::filesystem::path path) - : vase(path, "/tmp"), - lang(syntax::ruby::lang_ruby()), - parser(vase, vase.lines(), lang) { +Buffer::Buffer(std::filesystem::path path) : vase(path, "/tmp") { + parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby()); line = vase.lines(); if (!line) return; @@ -37,7 +32,7 @@ Buffer::Buffer(std::filesystem::path path) void Buffer::load(std::string command) { vase::Vase new_vase = vase::Vase(command, "/tmp"); vase = std::move(new_vase); - parser.reset(vase, vase.lines(), lang); + parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby()); line = vase.lines(); if (!line) { prev_range.start = 0; @@ -52,7 +47,7 @@ void Buffer::load(std::string command) { void Buffer::load(std::filesystem::path path) { vase::Vase new_vase = vase::Vase(path, "/tmp"); vase = std::move(new_vase); - parser.reset(vase, vase.lines(), lang); + parser.emplace(vase, vase.lines(), syntax::ruby::lang_ruby()); line = vase.lines(); if (!line) { prev_range.start = 0; @@ -110,17 +105,17 @@ inline void apply(std::ostream &out, const theme::Highlight &hl) { const uint8_t g = (hl.fg >> 8) & 0xff; const uint8_t b = hl.fg & 0xff; out << "\x1b[38;2;" - << static_cast(r) << ';' - << static_cast(g) << ';' - << static_cast(b) << 'm'; + << (unsigned)r << ';' + << (unsigned)g << ';' + << (unsigned)b << 'm'; if (hl.bg != 0) { const uint8_t br = (hl.bg >> 16) & 0xff; const uint8_t bg = (hl.bg >> 8) & 0xff; const uint8_t bb = hl.bg & 0xff; out << "\x1b[48;2;" - << static_cast(br) << ';' - << static_cast(bg) << ';' - << static_cast(bb) << 'm'; + << (unsigned)br << ';' + << (unsigned)bg << ';' + << (unsigned)bb << 'm'; } if (hl.flags & theme::Highlight::Bold) out << "\x1b[1m"; @@ -137,38 +132,42 @@ inline void reset(std::ostream &out) { } void Buffer::print(BEd &ctx, uint64_t start_line, uint64_t end_line) { - std::optional it_o = parser.get_hl(vase, start_line - 1); - if (!it_o) - throw ed_error("shouldn't be possible if line existed, which is checked by print's callers."); - auto &it = *it_o; - while (start_line <= end_line) { - it.next(); - const std::string &line = it.it->line; - const auto &tokens = it.tokens; - 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()) - break; - if (end > line.size()) - break; - if (cursor < start) { - std::cout.write( - line.data() + cursor, - start - cursor - ); + if (parser) { + std::optional it_o = parser->get_hl(vase, start_line - 1); + auto &it = *it_o; + while (start_line <= end_line) { + it.next(); + const std::string &line = it.it->line; + const auto &tokens = it.tokens; + 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()) + break; + if (end > line.size()) + break; + if (cursor < start) { + std::cout.write( + line.data() + cursor, + start - cursor + ); + } + const auto highlight = ctx.theme.get(token); + apply(std::cout, highlight); + std::cout.write(line.data() + start, end - start); + reset(std::cout); + cursor = end; } - const auto highlight = ctx.theme.get(token); - apply(std::cout, highlight); - std::cout.write(line.data() + start, end - start); - reset(std::cout); - cursor = end; + if (cursor < line.size()) + std::cout.write(line.data() + cursor, line.size() - cursor); + std::cout << std::endl; + ++start_line; } - if (cursor < line.size()) - std::cout.write(line.data() + cursor, line.size() - cursor); - std::cout << '\n'; - ++start_line; + } else { + vase::Iterator it = vase.iterate(start_line - 1, Direction::Forward); + while (it.next() && start_line++ <= end_line) + std::cout << it.line << std::endl; } prev_range.start = start_line; prev_range.end = end_line; diff --git a/src/internal/syntax/parser.cc b/src/internal/syntax/parser.cc index 3f0221b..1101e95 100644 --- a/src/internal/syntax/parser.cc +++ b/src/internal/syntax/parser.cc @@ -42,7 +42,7 @@ static ParseState *build_tree(std::vector &leaves, size_t begi return make_branch(left, right); } -Parser::Parser(vase::Vase &vase, uint64_t lines, Language &lang) +Parser::Parser(vase::Vase &vase, uint64_t lines, Language lang) : root(nullptr), lang(lang) { reset(vase, lines, lang); } @@ -51,17 +51,17 @@ Parser::~Parser() { destroy_tree(root, lang); } -void Parser::reset(vase::Vase &vase, uint64_t lines, Language &lang_) { +void Parser::reset(vase::Vase &vase, uint64_t lines, Language lang_) { destroy_tree(root, lang); root = nullptr; if (lines == 0) return; - lang = lang_; + lang = std::move(lang_); vase::Iterator it = vase.iterate(0, Direction::Forward); it.next(); std::vector leaves; std::vector tokens; - leaves.reserve((lines + 63) / 64); + leaves.reserve((lines + MAX_CHUNK - 1) / MAX_CHUNK); void *state = lang.none_state(); uint32_t consumed = 0; while (consumed < lines) { @@ -69,7 +69,7 @@ void Parser::reset(vase::Vase &vase, uint64_t lines, Language &lang_) { leaf->header = 0; leaf->state = lang.copy(state); uint32_t chunk_lines = 0; - while (chunk_lines < 64 && consumed < lines) { + while (chunk_lines < MAX_CHUNK && consumed < lines) { tokens.clear(); lang.parse(&state, it.line, consumed == 0, &tokens); ++chunk_lines; @@ -140,17 +140,15 @@ void Parser::insert(vase::Vase &vase, uint64_t start, uint64_t count) { if (count == 0) return; std::vector leaves; - leaves.reserve((count + 63) / 64); + leaves.reserve((count + MAX_CHUNK - 1) / MAX_CHUNK); uint64_t consumed = 0; while (consumed < count) { auto *leaf = new ParseStateLeaf; leaf->state = nullptr; uint64_t chunk = 0; - while (chunk < 64 && consumed < count) { + while (chunk < MAX_CHUNK && consumed < count) { ++chunk; ++consumed; - if (consumed < count) - break; } leaf->header = chunk; leaves.push_back(leaf); @@ -277,6 +275,6 @@ Parser::Iterator &Parser::Iterator::operator=(Iterator &&other) { void Parser::Iterator::next() { it->next(); tokens.clear(); - p->lang.parse(&state, it->line, at == 0, &tokens); + p->lang.parse(&state, it->line, at++ == 0, &tokens); } } // namespace bed::internal::syntax