commit cd8e86eac700777e4aeb47aa659cf3d5319cd379
parent 6e225f0f5242d3187e58adfb2decee788025ebcc
Author: night0721 <[email protected]>
Date: Thu, 4 Jul 2024 17:03:37 +0100
Filetype detect, syntax highlight for single and multiline comment, strings, keywords
Diffstat:
3 files changed, 191 insertions(+), 25 deletions(-)
diff --git a/src/bar.c b/src/bar.c
@@ -32,11 +32,12 @@ void draw_status_bar(struct abuf *ab)
abAppend(ab, "\x1b[22m", 5);
- char git_branch[80], git_diff[80], file[80], lines[80], coord[80];
+ char git_branch[80], git_diff[80], file[80], info[80], lines[80], coord[80];
int gitb_len = snprintf(git_branch, sizeof(git_branch), " %s ", "master");
int gitd_len = snprintf(git_diff, sizeof(git_diff), " %s ", "+1");
int file_len = snprintf(file, sizeof(file), " %.20s %s",
vip.filename ? vip.filename : "[No Name]", vip.dirty ? "[+]" : "");
+ int info_len = snprintf(info, sizeof(info), " %s ", vip.syntax ? vip.syntax->filetype : "");
int lines_len;
if (vip.rows == 0 || vip.rows == vip.cy + 1) {
lines_len = snprintf(lines, sizeof(lines), " %s ", vip.rows == 0 ? "Top" : "Bot");
@@ -63,7 +64,8 @@ void draw_status_bar(struct abuf *ab)
while (file_len < vip.screencols) {
- if (vip.screencols - mode_len - file_len - gitb_len - gitd_len - 1 == lines_len + coord_len) {
+ if (vip.screencols - mode_len - file_len - gitb_len - gitd_len - 1 == info_len + lines_len + coord_len) {
+ abAppend(ab, info, info_len);
abAppend(ab, SURFACE_1_BG, COLOR_LEN);
if (vip.mode == NORMAL) {
abAppend(ab, BLUE_FG, COLOR_LEN);
diff --git a/src/row.c b/src/row.c
@@ -3,6 +3,7 @@
#include <string.h>
#include "vip.h"
+#include "row.h"
#include "syntax.h"
extern editor vip;
@@ -64,6 +65,11 @@ void insert_row(int at, char *s, size_t len)
vip.row = realloc(vip.row, sizeof(row) * (vip.rows + 1));
memmove(&vip.row[at + 1], &vip.row[at], sizeof(row) * (vip.rows - at));
+ for (int j = at + 1; j <= vip.rows; j++) {
+ vip.row[j].idx++;
+ }
+
+ vip.row[at].idx = at;
vip.row[at].size = len;
vip.row[at].chars = malloc(len + 1);
@@ -73,6 +79,7 @@ void insert_row(int at, char *s, size_t len)
vip.row[at].render_size = 0;
vip.row[at].render = NULL;
vip.row[at].hl = NULL;
+ vip.row[at].opened_comment = 0;
update_row(&vip.row[at]);
vip.rows++;
@@ -91,6 +98,9 @@ void del_row(int at)
if (at < 0 || at >= vip.rows) return;
free_row(&vip.row[at]);
memmove(&vip.row[at], &vip.row[at + 1], sizeof(row) * (vip.rows - at - 1));
+ for (int j = at; j < vip.rows - 1; j++) {
+ vip.row[j].idx--;
+ }
vip.rows--;
vip.dirty++;
}
diff --git a/src/syntax.c b/src/syntax.c
@@ -4,54 +4,208 @@
#include <ctype.h>
#include "vip.h"
+#include "row.h"
+#include "syntax.h"
-int is_separator(int c) {
+char *c_keywords[] = { "switch", "if", "while", "for", "break", "continue", "return", "else", "struct", "union", "typedef", "static", "enum", "case", "sizeof", "int|", "long|", "double|", "float|", "char|", "unsigned|", "void|", NULL };
+char *c_ext[] = { ".c", ".h", ".cpp", NULL };
+
+language langs[] = {
+ {
+ "c",
+ HL_NUMBERS | HL_STRINGS,
+ "//",
+ "/*",
+ "*/",
+ c_keywords,
+ c_ext,
+ },
+};
+
+#define LANGS_LEN (sizeof(langs) / sizeof(langs[0]))
+
+int is_separator(int c)
+{
return isspace(c) || c == '\0' || strchr(",.()+-/*=~%<>[];", c) != NULL;
}
void update_highlight(row *row)
{
row->hl = realloc(row->hl, row->render_size);
- memset(row->hl, HL_NORMAL, row->render_size);
+ memset(row->hl, NORMAL, row->render_size);
+
+ if (vip.syntax == NULL) return;
+
+ char **keywords = vip.syntax->keywords;
+
+ char *scs = vip.syntax->singleline_comment_start;
+ char *mcs = vip.syntax->multiline_comment_start;
+ char *mce = vip.syntax->multiline_comment_end;
+
+ int scs_len = scs ? strlen(scs) : 0;
+ int mcs_len = mcs ? strlen(mcs) : 0;
+ int mce_len = mce ? strlen(mce) : 0;
int prev_sep = 1;
+ int in_string = 0;
+ int in_comment = (row->idx > 0 && vip.row[row->idx - 1].opened_comment);
+
int i = 0;
while (i < row->render_size) {
char c = row->render[i];
- unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL;
- if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||
- (c == '.' && prev_hl == HL_NUMBER)) {
- row->hl[i] = HL_NUMBER;
- i++;
- prev_sep = 0;
- continue;
+ unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : NORMAL;
+
+ if (scs_len && !in_string && !in_comment) {
+ if (!strncmp(&row->render[i], scs, scs_len)) {
+ memset(&row->hl[i], COMMENT, row->render_size - i);
+ break;
+ }
+ }
+
+ if (mcs_len && mce_len && !in_string) {
+ if (in_comment) {
+ row->hl[i] = MLCOMMENT;
+ if (!strncmp(&row->render[i], mce, mce_len)) {
+ memset(&row->hl[i], MLCOMMENT, mce_len);
+ i += mce_len;
+ in_comment = 0;
+ prev_sep = 1;
+ continue;
+ } else {
+ i++;
+ continue;
+ }
+ } else if (!strncmp(&row->render[i], mcs, mcs_len)) {
+ memset(&row->hl[i], MLCOMMENT, mcs_len);
+ i += mcs_len;
+ in_comment = 1;
+ continue;
+ }
+ }
+
+ if (vip.syntax->flags & HL_STRINGS) {
+ if (in_string) {
+ row->hl[i] = STRING;
+ if (c == '\\' && i + 1 < row->render_size) {
+ row->hl[i + 1] = STRING;
+ i += 2;
+ continue;
+ }
+ if (c == in_string) in_string = 0;
+ i++;
+ prev_sep = 1;
+ continue;
+ } else {
+ if (c == '"') {
+ in_string = c;
+ row->hl[i] = STRING;
+ i++;
+ continue;
+ }
+ }
+ }
+
+ if (vip.syntax->flags & HL_NUMBERS) {
+ if ((isdigit(c) && (prev_sep || prev_hl == NUMBER)) ||
+ (c == '.' && prev_hl == NUMBER)) {
+ row->hl[i] = NUMBER;
+ i++;
+ prev_sep = 0;
+ continue;
+ }
+ }
+
+ if (prev_sep) {
+ int j;
+ for (j = 0; keywords[j]; j++) {
+ int klen = strlen(keywords[j]);
+ int type_keyword = keywords[j][klen - 1] == '|';
+ if (type_keyword) klen--;
+ if (!strncmp(&row->render[i], keywords[j], klen) &&
+ is_separator(row->render[i + klen])) {
+ memset(&row->hl[i], type_keyword ? KEYWORD2 : KEYWORD1, klen);
+ i += klen;
+ break;
+ }
+ }
+ if (keywords[j] != NULL) {
+ prev_sep = 0;
+ continue;
+ }
}
+
prev_sep = is_separator(c);
i++;
- }}
+ }
+ int changed = (row->opened_comment != in_comment);
+ row->opened_comment = in_comment;
+ if (changed && row->idx + 1 < vip.rows)
+ update_highlight(&vip.row[row->idx + 1]);
+}
char *syntax_to_color(int hl, size_t *len)
{
switch (hl) {
- case HL_NUMBER:
+ case NUMBER:
*len = COLOR_LEN;
return strdup(PEACH_BG);
- case HL_MATCH:;
- char *str = malloc(COLOR_LEN * 2 + 1);
- snprintf(str, COLOR_LEN * 2 + 1, "%s%s", BLACK_BG, SKY_FG);
- *len = COLOR_LEN * 2;
- return str;
+ case STRING:
+ *len = COLOR_LEN;
+ return strdup(GREEN_BG);
+
+ case COMMENT:
+ case MLCOMMENT:
+ *len = COLOR_LEN;
+ return strdup(OVERLAY_0_BG);
+
+ case KEYWORD1:
+ *len = COLOR_LEN;
+ return strdup(MAUVE_BG);
+
+ case KEYWORD2:
+ *len = COLOR_LEN;
+ return strdup(YELLOW_BG);
+
+ case MATCH:;
+ char *str = malloc(COLOR_LEN * 2 + 1);
+ snprintf(str, COLOR_LEN * 2 + 1, "%s%s", BLACK_BG, SKY_FG);
+ *len = COLOR_LEN * 2;
+ return str;
- case HL_RESET:;
- char *res = malloc(COLOR_LEN * 2 + 1);
- snprintf(res, COLOR_LEN * 2 + 1, "%s%s", WHITE_BG, BLACK_FG);
- *len = COLOR_LEN * 2;
- return res;
+ case RESET:;
+ char *res = malloc(COLOR_LEN * 2 + 1);
+ snprintf(res, COLOR_LEN * 2 + 1, "%s%s", WHITE_BG, BLACK_FG);
+ *len = COLOR_LEN * 2;
+ return res;
default:
- *len = COLOR_LEN;
- return strdup(WHITE_BG);
+ *len = COLOR_LEN;
+ return strdup(WHITE_BG);
+ }
+}
+
+void select_syntax_highlight()
+{
+ vip.syntax = NULL;
+ if (vip.filename == NULL) return;
+ char *ext = strrchr(vip.filename, '.');
+ for (unsigned int j = 0; j < LANGS_LEN; j++) {
+ language *s = &langs[j];
+ unsigned int i = 0;
+ while (s->extensions[i]) {
+ int is_ext = (s->extensions[i][0] == '.');
+ if ((is_ext && ext && !strcmp(ext, s->extensions[i])) ||
+ (!is_ext && strstr(vip.filename, s->extensions[i]))) {
+ vip.syntax = s;
+
+ for (int row = 0; row < vip.rows; row++) {
+ update_highlight(&vip.row[row]);
+ }
+ return;
+ }
+ i++;
+ }
}
}