- Switch to using PCRE for ts predicate matching
- Fix/use shebang hl for ruby and bash grammars
This commit is contained in:
2025-12-10 19:49:09 +00:00
parent 774a21241e
commit 303f008b6f
6 changed files with 44 additions and 56 deletions

View File

@@ -281,7 +281,7 @@
(extglob_pattern)
] @string.regexp
;; #fbb152 #000000 0 0 0 3
;; #51eeba #000000 0 0 0 3
((program
.
(comment) @keyword.directive @nospell)

View File

@@ -245,23 +245,11 @@
;; #AAAAAA #000000 0 1 0 1
(comment) @comment
(program
(comment)+ @comment.documentation
(class))
(module
(comment)+ @comment.documentation
(body_statement
(class)))
(class
(comment)+ @comment.documentation
(body_statement
(method)))
(body_statement
(comment)+ @comment.documentation
(method))
;; #51eeba #000000 0 0 0 3
((program
.
(comment) @shebang @nospell)
(#match? @shebang "^#!/"))
;; #ffffff #000000 0 0 0 1
[

View File

@@ -2,10 +2,14 @@
#define TS_H
#include "./editor.h"
#include <pcre2.h>
#define HEX(s) (static_cast<uint32_t>(std::stoul(s, nullptr, 16)))
extern std::unordered_map<std::string, pcre2_code *> regex_cache;
TSQuery *load_query(const char *query_path, Editor *editor);
void ts_collect_spans(Editor *editor);
void clear_regex_cache();
#endif

View File

@@ -12,8 +12,11 @@ Editor *new_editor(const char *filename, Coord position, Coord size) {
return nullptr;
uint32_t len = 0;
char *str = load_file(filename, &len);
if (!str)
if (!str) {
free_editor(editor);
log("me?");
return nullptr;
}
editor->filename = filename;
editor->position = position;
editor->size = size;

View File

@@ -5,22 +5,14 @@
#include <atomic>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <sys/ioctl.h>
#include <thread>
std::atomic<bool> running{true};
Queue<KeyEvent> event_queue;
std::atomic<uint64_t> render_frames{0};
std::atomic<uint64_t> worker_frames{0};
auto start_time = std::chrono::high_resolution_clock::now();
void background_worker(Editor *editor) {
while (running) {
worker_frames++;
ts_collect_spans(editor);
std::this_thread::sleep_for(std::chrono::milliseconds(16));
@@ -164,7 +156,7 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
int main(int argc, char *argv[]) {
Coord screen = start_screen();
const char *filename = (argc > 1) ? argv[1] : "ts.cpp";
const char *filename = (argc > 1) ? argv[1] : "";
Editor *editor = new_editor(filename, {0, 0}, {screen.row, screen.col});
if (!editor) {
@@ -173,14 +165,10 @@ int main(int argc, char *argv[]) {
return 1;
}
start_time = std::chrono::high_resolution_clock::now();
std::thread input_thread(input_listener);
std::thread work_thread(background_worker, editor);
while (running) {
render_frames++;
KeyEvent event;
while (event_queue.pop(event))
handle_editor_event(editor, event);
@@ -196,20 +184,9 @@ int main(int argc, char *argv[]) {
if (work_thread.joinable())
work_thread.join();
auto end_time = std::chrono::high_resolution_clock::now();
double seconds = std::chrono::duration<double>(end_time - start_time).count();
double render_fps = render_frames / seconds;
double worker_fps = worker_frames / seconds;
end_screen();
std::cout << "\n======= Performance Summary =======\n";
std::cout << "Runtime: " << seconds << "s\n";
std::cout << "Render loop FPS: " << render_fps << "Hz\n";
std::cout << "Worker loop FPS: " << worker_fps << "Hz\n";
std::cout << "===================================\n";
free_editor(editor);
clear_regex_cache();
return 0;
}

View File

@@ -8,7 +8,27 @@
#include <string>
#include <unordered_map>
static std::unordered_map<std::string, std::regex> regex_cache;
std::unordered_map<std::string, pcre2_code *> regex_cache;
void clear_regex_cache() {
for (auto &kv : regex_cache) {
pcre2_code_free(kv.second);
}
regex_cache.clear();
}
pcre2_code *get_re(const std::string &pattern) {
auto it = regex_cache.find(pattern);
if (it != regex_cache.end())
return it->second;
int errornum;
PCRE2_SIZE erroffset;
pcre2_code *re =
pcre2_compile((PCRE2_SPTR)pattern.c_str(), PCRE2_ZERO_TERMINATED, 0,
&errornum, &erroffset, nullptr);
regex_cache[pattern] = re;
return re;
}
static const std::regex scm_regex(
R"((@[A-Za-z0-9_.]+)|(;; \#[0-9a-fA-F]{6} \#[0-9a-fA-F]{6} [01] [01] [01] \d+))");
@@ -94,8 +114,6 @@ static inline bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
ts_query_predicates_for_pattern(query, match.pattern_index, &step_count);
if (!steps || step_count != 4)
return true;
if (source->char_count >= (16 * 1024))
return false;
std::string command;
std::string regex_txt;
uint32_t subject_id = 0;
@@ -124,15 +142,13 @@ static inline bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
}
const TSNode *node = find_capture_node(match, subject_id);
std::string subject = node_text(*node, source);
auto it = regex_cache.find(regex_txt);
if (it == regex_cache.end())
it = regex_cache.emplace(regex_txt, std::regex(regex_txt)).first;
const std::regex &re = it->second;
if (command == "match?")
return std::regex_match(subject, re);
else if (command == "not-match?")
return !std::regex_match(subject, re);
return false;
pcre2_code *re = get_re(regex_txt);
pcre2_match_data *md = pcre2_match_data_create_from_pattern(re, nullptr);
int rc = pcre2_match(re, (PCRE2_SPTR)subject.c_str(), subject.size(), 0, 0,
md, nullptr);
pcre2_match_data_free(md);
bool ok = (rc >= 0);
return (command == "match?" ? ok : !ok);
}
const char *read_ts(void *payload, uint32_t byte_index, TSPoint,