#include "hl.h" #include vector_t token_table = { .data = NULL, .element_size = sizeof(token_t *), .element_count = 0UL }; display_t * display_table = NULL; // ------------------------- // ### Library Mangement ### // ------------------------- hl_group_t * special_hl = NULL; hl_group_t * control_hl = NULL; hl_group_t * keyword_hl = NULL; hl_group_t * block_hl = NULL; hl_group_t * separator_hl = NULL; hl_group_t * operator_hl = NULL; hl_group_t * comment_hl = NULL; hl_group_t * string_literal_hl = NULL; // -------------------------------- // ### Constructors/Destructors ### // -------------------------------- void new_display_mode(display_t * mode) { HASH_ADD_STR(display_table, key, mode); } int free_token(token_t * token) { free(token->hl); regex_free(token->syntax); return 0; } int append_token(token_t * token) { vector_push(&token_table, &token); return 0; } token_t * new_symbol_token(const char * const c, hl_group_t * const g) { token_t * mt = (token_t*)malloc(sizeof(token_t)); mt->hl = g; mt->t = KEYSYMBOL; mt->syntax = regex_compile(c); append_token(mt); return mt; } int new_symbol_tokens(const char * const * symbols, hl_group_t * const g) { int i = 0; while (*symbols) { if(new_symbol_token(*symbols, g)) { ++i; } else { assert(!(bool)"Kinda failed to new symbol token thing."); } ++symbols; } return i; } int new_char_tokens(const char * str, hl_group_t * const g) { int i = 0; char buffer[3]; buffer[0] = '\\'; buffer[2] = '\0'; for(const char * s = str; *s != '\0'; s++) { buffer[1] = *s; if(new_symbol_token(is_magic(*s) ? buffer : buffer + 1, g)) { ++i; } else { assert(!(bool)"Kinda failed to new char token thing."); } } return i; } token_t * new_keyword_token(const char * const word, hl_group_t * const g) { size_t word_length = strlen(word); char * new_word = (char*)malloc(word_length + 4 + 1); memcpy(new_word, "\\<", 2); memcpy(new_word + 2, word, word_length); strcpy(new_word + 2 + word_length, "\\>"); token_t * mt = (token_t*)malloc(sizeof(token_t)); mt->hl = g; mt->t = KEYWORD; mt->syntax = regex_compile(new_word); append_token(mt); return mt; } int new_keyword_tokens(const char * const * words, hl_group_t * const g) { int i = 0; while (*words) { if(new_keyword_token(*words, g)) { ++i; } ++words; } return i; } token_t * new_region_token(const char * start, const char * end, hl_group_t * g) { char buffer[100]; buffer[0] = '\0'; strcat(buffer, start); strcat(buffer, "[\\d\\D]*"); strcat(buffer, end); token_t * mt = (token_t*)malloc(sizeof(token_t)); mt->hl = g; mt->t = KEYSYMBOL; mt->syntax = regex_compile(buffer); append_token(mt); return mt; } token_t * new_token(const char * const word, const token_type_t t, hl_group_t * const g) { switch (t) { case KEYSYMBOL: { return new_symbol_token(word, g); } case KEYWORD: { return new_keyword_token(word, g); } case MATCH: { token_t * mt = (token_t*)malloc(sizeof(token_t)); mt->hl = g; mt->t = MATCH; mt->syntax = regex_compile(word); append_token(mt); } break; case REGION: { } break; } return NULL; } // -------------------- // ### Highlighting ### // -------------------- void render_string(const char * const string, const char * const mode) { display_t * display; HASH_FIND_STR(display_table, mode, display); typedef struct { const token_t * t; const match_t * m; int i; } result_t; result_t * const r = (result_t *)malloc(sizeof(result_t) * 1024); // XXX: dont int rrs = 0; for (size_t i = 0; i < token_table.element_count; i++) { token_t * t = *(token_t**)vector_get(&token_table, i); match_t * match = regex_match(t->syntax, string, true); if (is_sentinel(match)) { free(match); continue; } r[rrs++] = (result_t){ .t = t, .m = match, .i = 0, }; } for (const char * s = string; *s != '\00';) { const result_t sentinel = (result_t){NULL, &(match_t){ -1, -1}, -1}; const result_t * max; max = &sentinel; for (int h = 0; h < rrs; h++) { result_t * const current_result = r + h; for (int j = 0; !is_sentinel(&(current_result->m[j])); j++) { if (current_result->m[j].position == (s - string)) { if (current_result->m[j].width > max->m->width) { current_result->i = j; max = current_result; } break; } } } if (max != &sentinel) { const match_t * mymatch = &(max->m[max->i]); const int padding = mymatch->position - (s - string); if (padding) { display->callback(s, padding, NULL); } display->callback(s + padding, mymatch->width, max->t->hl->attributes); s += padding + mymatch->width; } else { display->callback(s, 1, NULL); ++s; } } } int hl_init(void) { return 0; } int hl_deinit(void) { //for (size_t i = 0; i < token_table.element_count; i++) { // free_token(*(token_t**)vector_get(&token_table, i)); //} return 0; }