Highlight things
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
7.7KB

  1. /* hl.h
  2. * Copyright 2023 Anon Anonson, Ognjen 'xolatile' Milan Robovic, Emil Williams
  3. * SPDX Identifier: GPL-3.0-only / NO WARRANTY / NO GUARANTEE */
  4. #include <stdio.h>
  5. #include <uthash.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include "chad.h"
  9. #include "regex.h"
  10. // -------------------
  11. // ### Definitions ###
  12. // -------------------
  13. typedef enum {
  14. KEYSYMBOL,
  15. KEYWORD,
  16. MATCH,
  17. REGION
  18. } token_type_t;
  19. typedef void (*attribute_callback_t) (const char * const string,
  20. const int length,
  21. void * const attributes);
  22. typedef struct {
  23. char * key;
  24. attribute_callback_t callback;
  25. UT_hash_handle hh;
  26. } display_t;
  27. typedef struct {
  28. void * attributes;
  29. struct hl_group_t * link;
  30. } hl_group_t;
  31. typedef struct {
  32. hl_group_t * hl;
  33. regex_t * syntax;
  34. token_type_t t;
  35. char _pad[4];
  36. } token_t;
  37. extern vector_t token_table;
  38. extern display_t * display_table;
  39. extern hl_group_t * keyword_hl;
  40. extern hl_group_t * preprocessor_hl;
  41. extern hl_group_t * symbol_hl;
  42. extern void new_display_mode(display_t * mode);
  43. extern int free_token(token_t * token);
  44. extern int append_token(token_t * token);
  45. // TODO: ALIGN PROPERLY...
  46. extern token_t * new_symbol_token(const char * const c,
  47. hl_group_t * const g);
  48. extern int new_symbol_tokens(const char * const * symbols,
  49. hl_group_t * const g);
  50. extern int new_char_tokens(const char * characters,
  51. hl_group_t * const g);
  52. extern token_t * new_keyword_token(const char * const word,
  53. hl_group_t * const g);
  54. extern int new_keyword_tokens(const char * const * words,
  55. hl_group_t * const g);
  56. extern token_t * new_token(const char * const word,
  57. const token_type_t t,
  58. hl_group_t * const g);
  59. // TODO: ALIGN PROPERLY...
  60. extern int token_fits(const token_t * const token,
  61. const char * const to,
  62. const int string_offset,
  63. int * match_offset);
  64. extern void render_string(const char * const string,
  65. const char * const mode);
  66. extern int hl_init(void);
  67. extern int hl_deinit(void);
  68. // GLOBALS
  69. vector_t token_table = {
  70. .data = NULL,
  71. .element_size = sizeof(token_t *),
  72. .element_count = 0UL
  73. };
  74. display_t * display_table = NULL;
  75. // --------------------------------
  76. // ### Constructors/Destructors ###
  77. // --------------------------------
  78. void new_display_mode(display_t * mode) {
  79. HASH_ADD_STR(display_table,
  80. key,
  81. mode);
  82. }
  83. int free_token(token_t * token) {
  84. free(token->hl);
  85. regex_free(token->syntax);
  86. return 0;
  87. }
  88. int append_token(token_t * token) {
  89. vector_push(&token_table, &token);
  90. return 0;
  91. }
  92. token_t * new_symbol_token(const char * const c,
  93. hl_group_t * const g) {
  94. token_t * mt = (token_t*)malloc(sizeof(token_t));
  95. mt->hl = g;
  96. mt->t = KEYSYMBOL;
  97. mt->syntax = regex_compile(c);
  98. append_token(mt);
  99. return mt;
  100. }
  101. int new_symbol_tokens(const char * const * symbols,
  102. hl_group_t * const g) {
  103. int i = 0;
  104. while (*symbols) {
  105. if(new_symbol_token(*symbols, g)) {
  106. ++i;
  107. } else {
  108. assert(!(bool)"Kinda failed to new symbol token thing.");
  109. }
  110. ++symbols;
  111. }
  112. return i;
  113. }
  114. int new_char_tokens(const char * characters,
  115. hl_group_t * const g) {
  116. int i = 0;
  117. char buffer[3];
  118. buffer[0] = '\\';
  119. buffer[2] = '\0';
  120. for(const char * s = characters; *s != '\0'; s++) {
  121. buffer[1] = *s;
  122. if(new_symbol_token(is_magic(*s) ? buffer : buffer + 1, g)) {
  123. ++i;
  124. } else {
  125. assert(!(bool)"Kinda failed to new char token thing.");
  126. }
  127. }
  128. return i;
  129. }
  130. token_t * new_keyword_token(const char * const word,
  131. hl_group_t * const g) {
  132. //char * new_word = strdup(word);
  133. //size_t word_length = strlen(word);
  134. //char * new_word = (char*)malloc(word_length + 4 + 1);
  135. //memcpy(new_word, "\\<", 2);
  136. //memcpy(new_word + 2, word, word_length);
  137. //strcpy(new_word + 2 + word_length, "\\>");
  138. token_t * mt = (token_t*)malloc(sizeof(token_t));
  139. mt->hl = g;
  140. mt->t = KEYWORD;
  141. //mt->syntax = regex_compile(new_word);
  142. mt->syntax = regex_compile(word);
  143. append_token(mt);
  144. return mt;
  145. }
  146. int new_keyword_tokens(const char * const * words,
  147. hl_group_t * const g) {
  148. int i = 0;
  149. while (*words) {
  150. if(new_keyword_token(*words, g)) {
  151. ++i;
  152. }
  153. ++words;
  154. }
  155. return i;
  156. }
  157. token_t * new_region_token(const char * const * start,
  158. const char * const * end,
  159. hl_group_t * const g) {
  160. char buffer[100];
  161. buffer[0] = '\0';
  162. strcat(buffer, start);
  163. strcat(buffer, "[\\d\\D]*");
  164. strcat(buffer, end);
  165. token_t * mt = (token_t*)malloc(sizeof(token_t));
  166. mt->hl = g;
  167. mt->t = KEYSYMBOL;
  168. mt->syntax = regex_compile(buffer);
  169. append_token(mt);
  170. return mt;
  171. }
  172. token_t * new_token(const char * const word,
  173. const token_type_t t,
  174. hl_group_t * const g) {
  175. switch (t) {
  176. case KEYSYMBOL: {
  177. return new_symbol_token(word, g);
  178. }
  179. case KEYWORD: {
  180. return new_keyword_token(word, g);
  181. }
  182. case MATCH: {
  183. } break;
  184. case REGION: {
  185. } break;
  186. }
  187. return NULL;
  188. }
  189. // --------------------
  190. // ### Highlighting ###
  191. // --------------------
  192. int token_fits(const token_t * const token,
  193. const char * const to,
  194. const int string_offset,
  195. int * match_offset) {
  196. UNUSED(match_offset);
  197. //return regex_match(pattern, to, string_offset, match_offset);
  198. return regex_match(token->syntax, to + string_offset);
  199. }
  200. void render_string(const char * const string,
  201. const char * const mode) {
  202. for (const char * s = string; *s != '\00';) {
  203. int f = 0;
  204. size_t token_index = 0;
  205. int offset = 0;
  206. for (; token_index < token_table.element_count; token_index++) {
  207. token_t * t = *(token_t**)vector_get(&token_table,
  208. token_index);
  209. f = token_fits(t, string, (int) (s - string), &offset);
  210. if (f) {
  211. break;
  212. }
  213. }
  214. //
  215. display_t * display;
  216. HASH_FIND_STR(display_table,
  217. mode,
  218. display);
  219. //
  220. if (f) {
  221. for (int i = 0; i < offset; i++) {
  222. token_t * t = *(token_t**)vector_get(&token_table,
  223. token_index);
  224. display->callback(s + i,
  225. 0,
  226. t->hl->attributes);
  227. }
  228. token_t * t = *(token_t**)vector_get(&token_table,
  229. token_index);
  230. display->callback(s + offset,
  231. f,
  232. t->hl->attributes);
  233. s += f + offset;
  234. } else {
  235. display->callback(s,
  236. 0,
  237. NULL);
  238. ++s;
  239. }
  240. }
  241. }
  242. // -------------------------
  243. // ### Library Mangement ###
  244. // -------------------------
  245. hl_group_t * special_hl = NULL;
  246. hl_group_t * control_hl = NULL;
  247. hl_group_t * keyword_hl = NULL;
  248. hl_group_t * block_hl = NULL;
  249. hl_group_t * separator_hl = NULL;
  250. hl_group_t * operator_hl = NULL;
  251. hl_group_t * comment_hl = NULL;
  252. hl_group_t * string_literal_hl = NULL;
  253. int hl_init(void) {
  254. return 0;
  255. }
  256. int hl_deinit(void) {
  257. for (size_t i = 0; i < token_table.element_count; i++) {
  258. free_token(*(token_t**)vector_get(&token_table, i));
  259. }
  260. return 0;
  261. }