hilite.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /* hlite.c, generic syntax highlighting, Ait Emacs, Kevin Bloom, BSD 3-Clause, 2023-2024 */
  2. #include "header.h"
  3. #include "util.h"
  4. int state = ID_DEFAULT;
  5. int next_state = ID_DEFAULT;
  6. int skip_count = 0;
  7. int exclude_state = ID_DEFAULT;
  8. int exclude_count = 0;
  9. char_t get_at(buffer_t *bp, point_t pt)
  10. {
  11. return (*ptr(bp, pt));
  12. }
  13. void set_parse_state(buffer_t *bp, point_t pt, window_t *wp, int loop)
  14. {
  15. register point_t po;
  16. state = ID_DEFAULT;
  17. next_state = ID_DEFAULT;
  18. skip_count = 0;
  19. if(bp->b_keywords != NULL &&
  20. bp->b_keywords->mlc != NULL && bp->b_keywords->emlc != NULL &&
  21. loop) {
  22. for (po =0; po < pt; po++)
  23. parse_text(bp, po);
  24. wp->w_hilite = state;
  25. }
  26. }
  27. void write_parse_state(window_t *wp)
  28. {
  29. state = wp->w_hilite;
  30. next_state = wp->w_hilite;
  31. skip_count = 0;
  32. }
  33. int parse_text(buffer_t *bp, point_t pt)
  34. {
  35. // if(bp->b_keywords == NULL)
  36. // return state;
  37. if (skip_count-- > 0) {
  38. if(exclude_count != 0)
  39. exclude_count--;
  40. if(exclude_state != ID_DEFAULT &&
  41. exclude_count == 0) {
  42. state = exclude_state;
  43. exclude_state = ID_DEFAULT;
  44. }
  45. return state;
  46. }
  47. char_t c_now = get_at(bp, pt);
  48. char_t c_prev = get_at(bp, pt-1);
  49. char_t next = c_now;
  50. int valid = TRUE, k = 0;
  51. state = next_state;
  52. if (state == ID_DEFAULT &&
  53. bp->b_keywords != NULL &&
  54. bp->b_keywords->mlc != NULL) {
  55. next = c_now;
  56. for(int i = 0; bp->b_keywords->mlc[i] != '\0'; i++) {
  57. next = get_at(bp, pt + i);
  58. if(next != bp->b_keywords->mlc[i]) {
  59. valid = FALSE;
  60. break;
  61. }
  62. }
  63. if(valid) {
  64. skip_count = 1;
  65. return (next_state = state = ID_BLOCK_COMMENT);
  66. }
  67. valid = TRUE;
  68. }
  69. if (state == ID_BLOCK_COMMENT &&
  70. bp->b_keywords != NULL &&
  71. bp->b_keywords->emlc != NULL) {
  72. next = c_now;
  73. for(int i = 0; bp->b_keywords->emlc[i] != '\0'; i++) {
  74. next = get_at(bp, pt + i);
  75. if(next != bp->b_keywords->emlc[i]) {
  76. valid = FALSE;
  77. break;
  78. }
  79. }
  80. if(valid) {
  81. skip_count = strlen(bp->b_keywords->emlc) - 1;
  82. next_state = ID_DEFAULT;
  83. return ID_BLOCK_COMMENT;
  84. }
  85. valid = TRUE;
  86. }
  87. if (state == ID_DEFAULT &&
  88. bp->b_keywords != NULL &&
  89. bp->b_keywords->slc[0] != '\0') {
  90. next = c_now;
  91. for(int i = 0; bp->b_keywords->slc[i] != '\0'; i++) {
  92. next = get_at(bp, pt + i);
  93. if(next != bp->b_keywords->slc[i]) {
  94. valid = FALSE;
  95. break;
  96. }
  97. }
  98. if(valid) {
  99. skip_count = 1;
  100. return (next_state = state = ID_LINE_COMMENT);
  101. }
  102. valid = TRUE;
  103. }
  104. if (state == ID_LINE_COMMENT && c_now == '\n')
  105. return (next_state = ID_DEFAULT);
  106. if (state == ID_DEFAULT && c_now == '"') {
  107. int enable = FALSE;
  108. char_t z = get_at(bp, pt+1);
  109. point_t end = pos(bp, bp->b_ebuf);
  110. for(point_t i = pt+1; z != '\n' && i <= end; i++, z = get_at(bp, i)) {
  111. if(z == '"') {
  112. enable = TRUE;
  113. break;
  114. }
  115. if(z == '\\' && get_at(bp, i+1) == '\n') {
  116. enable = TRUE;
  117. break;
  118. }
  119. }
  120. if(enable)
  121. return (next_state = ID_DOUBLE_STRING);
  122. }
  123. if (state == ID_DEFAULT &&
  124. bp->b_keywords != NULL &&
  125. bp->b_keywords->bqas &&
  126. c_now == '`')
  127. return (next_state = ID_BACK_STRING);
  128. if (state == ID_DEFAULT &&
  129. bp->b_keywords != NULL &&
  130. bp->b_keywords->sqas &&
  131. c_now == '\'') {
  132. int enable = FALSE;
  133. char_t z = get_at(bp, pt+1);
  134. point_t end = pos(bp, bp->b_ebuf);
  135. for(point_t i = pt+1; z != '\n' && i <= end; i++, z = get_at(bp, i)) {
  136. if(z == '\'') {
  137. enable = TRUE;
  138. break;
  139. }
  140. }
  141. if(enable)
  142. return (next_state = ID_SINGLE_STRING);
  143. }
  144. if (state == ID_DOUBLE_STRING && c_now == '\\') {
  145. skip_count = 1;
  146. return (next_state = ID_DOUBLE_STRING);
  147. }
  148. if (state == ID_DOUBLE_STRING && c_now == '"') {
  149. next_state = ID_DEFAULT;
  150. return ID_DOUBLE_STRING;
  151. }
  152. if (state == ID_SINGLE_STRING && c_now == '\\') {
  153. skip_count = 1;
  154. return (next_state = ID_SINGLE_STRING);
  155. }
  156. if (state == ID_DEFAULT &&
  157. bp->b_keywords != NULL &&
  158. bp->b_keywords->bqas &&
  159. c_now == '`')
  160. return (next_state = ID_BACK_STRING);
  161. if (state == ID_BACK_STRING && c_now == '\\') {
  162. skip_count = 1;
  163. return (next_state = ID_BACK_STRING);
  164. }
  165. if (state == ID_SINGLE_STRING && c_now == '\'') {
  166. next_state = ID_DEFAULT;
  167. return ID_SINGLE_STRING;
  168. }
  169. if (state == ID_BACK_STRING && c_now == '`') {
  170. next_state = ID_DEFAULT;
  171. return ID_BACK_STRING;
  172. }
  173. if(bp->b_keywords != NULL &&
  174. bp->b_keywords->keywords != NULL &&
  175. state == ID_DEFAULT &&
  176. (pt == 0 ||
  177. (is_symbol(c_prev) &&
  178. (c_prev != '-' && c_prev != '_'))
  179. || isspace(c_prev))) {
  180. for(int i = 0; bp->b_keywords->keywords[i].word != NULL; i++) {
  181. int l = 0, t = 0;
  182. exclude_count = 0;
  183. exclude_state = ID_DEFAULT;
  184. for(k = 0; bp->b_keywords->keywords[i].word[l] != '\0'; k++, l++) {
  185. c_now = get_at(bp, pt+k);
  186. /* at the end */
  187. if(bp->b_keywords->keywords[i].word[l] == '') {
  188. if(bp->b_keywords->keywords[i].word[l+1] == '\0') {
  189. for(; !isspace(c_now); k++) {
  190. c_now = get_at(bp, pt+k);
  191. }
  192. k--;
  193. break;
  194. } else {
  195. l++;
  196. for(; !isspace(c_now) && (bp->b_keywords->keywords[i].word[l] < 32 ||
  197. !is_symboli(c_now, bp->b_keywords->keywords[i].word[l])); k++) {
  198. if(bp->b_keywords->keywords[i].word[l] == c_now) {
  199. t = 1;
  200. break;
  201. }
  202. if(bp->b_keywords->keywords[i].word[l] == '' &&
  203. bp->b_keywords->keywords[i].word[l+1] == c_now) {
  204. t = 2;
  205. break;
  206. }
  207. if(pt+k == pos(bp, bp->b_ebuf))
  208. break;
  209. c_now = get_at(bp, pt+k);
  210. }
  211. if(t == 0) {
  212. k = 0;
  213. break;
  214. }
  215. if(t == 1) {
  216. k--;
  217. continue;
  218. }
  219. if(t == 2) {
  220. l++;
  221. k--;
  222. break;
  223. }
  224. }
  225. }
  226. if(bp->b_keywords->keywords[i].word[l] == '') {
  227. if(bp->b_keywords->keywords[i].word[l+1] == c_now
  228. || bp->b_keywords->keywords[i].word[l+1] == '\0') {
  229. exclude_state = bp->b_keywords->keywords[i].color;
  230. exclude_count++;
  231. k--;
  232. continue;
  233. } else {
  234. k = 0;
  235. exclude_count = 0;
  236. break;
  237. }
  238. }
  239. if(bp->b_keywords->keywords[i].word[l] != c_now) {
  240. k = 0;
  241. break;
  242. }
  243. }
  244. c_now = get_at(bp, pt+k);
  245. if(k > 0 && (isspace(c_now) ||
  246. (is_symbol(c_now) && (c_now != '-' && (
  247. bp->b_keywords->keywords[i].word[l] == '_' || c_now != '_')))) &&
  248. (bp->b_keywords->keywords[i].word[l] == '\0' ||
  249. bp->b_keywords->keywords[i].word[l+1] == '\0')) {
  250. skip_count = k-1;
  251. next_state = ID_DEFAULT;
  252. if(exclude_state != ID_DEFAULT) {
  253. return (state = ID_DEFAULT);
  254. }
  255. return (state = bp->b_keywords->keywords[i].color);
  256. }
  257. }
  258. }
  259. if (state != ID_DEFAULT)
  260. return (next_state = state);
  261. // if (state == ID_DEFAULT && c_now >= '0' && c_now <= '9') {
  262. // next_state = ID_DEFAULT;
  263. // return (state = ID_DIGITS);
  264. // }
  265. // if (state == ID_DEFAULT && 1 == is_symbol(c_now)) {
  266. // next_state = ID_DEFAULT;
  267. // return (state = ID_SYMBOL);
  268. // }
  269. return (next_state = state);
  270. }