Highlight things
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

335 řádky
8.1KB

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