Filetype detect, syntax highlight for single and multiline comment, strings, keywords

This commit is contained in:
Night Kaly 2024-07-04 17:03:37 +01:00
parent 6e225f0f52
commit cd8e86eac7
Signed by: night0721
GPG key ID: 957D67B8DB7A119B
3 changed files with 191 additions and 25 deletions

View file

@ -32,11 +32,12 @@ void draw_status_bar(struct abuf *ab)
abAppend(ab, "\x1b[22m", 5); 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 gitb_len = snprintf(git_branch, sizeof(git_branch), " %s ", "master");
int gitd_len = snprintf(git_diff, sizeof(git_diff), " %s ", "+1"); int gitd_len = snprintf(git_diff, sizeof(git_diff), " %s ", "+1");
int file_len = snprintf(file, sizeof(file), " %.20s %s", int file_len = snprintf(file, sizeof(file), " %.20s %s",
vip.filename ? vip.filename : "[No Name]", vip.dirty ? "[+]" : ""); vip.filename ? vip.filename : "[No Name]", vip.dirty ? "[+]" : "");
int info_len = snprintf(info, sizeof(info), " %s ", vip.syntax ? vip.syntax->filetype : "");
int lines_len; int lines_len;
if (vip.rows == 0 || vip.rows == vip.cy + 1) { if (vip.rows == 0 || vip.rows == vip.cy + 1) {
lines_len = snprintf(lines, sizeof(lines), " %s ", vip.rows == 0 ? "Top" : "Bot"); 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) { 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); abAppend(ab, SURFACE_1_BG, COLOR_LEN);
if (vip.mode == NORMAL) { if (vip.mode == NORMAL) {
abAppend(ab, BLUE_FG, COLOR_LEN); abAppend(ab, BLUE_FG, COLOR_LEN);

View file

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include "vip.h" #include "vip.h"
#include "row.h"
#include "syntax.h" #include "syntax.h"
extern editor vip; 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)); vip.row = realloc(vip.row, sizeof(row) * (vip.rows + 1));
memmove(&vip.row[at + 1], &vip.row[at], sizeof(row) * (vip.rows - at)); 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].size = len;
vip.row[at].chars = malloc(len + 1); 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_size = 0;
vip.row[at].render = NULL; vip.row[at].render = NULL;
vip.row[at].hl = NULL; vip.row[at].hl = NULL;
vip.row[at].opened_comment = 0;
update_row(&vip.row[at]); update_row(&vip.row[at]);
vip.rows++; vip.rows++;
@ -91,6 +98,9 @@ void del_row(int at)
if (at < 0 || at >= vip.rows) return; if (at < 0 || at >= vip.rows) return;
free_row(&vip.row[at]); free_row(&vip.row[at]);
memmove(&vip.row[at], &vip.row[at + 1], sizeof(row) * (vip.rows - at - 1)); 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.rows--;
vip.dirty++; vip.dirty++;
} }

View file

@ -4,46 +4,176 @@
#include <ctype.h> #include <ctype.h>
#include "vip.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; return isspace(c) || c == '\0' || strchr(",.()+-/*=~%<>[];", c) != NULL;
} }
void update_highlight(row *row) void update_highlight(row *row)
{ {
row->hl = realloc(row->hl, row->render_size); 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 prev_sep = 1;
int in_string = 0;
int in_comment = (row->idx > 0 && vip.row[row->idx - 1].opened_comment);
int i = 0; int i = 0;
while (i < row->render_size) { while (i < row->render_size) {
char c = row->render[i]; char c = row->render[i];
unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : HL_NORMAL; unsigned char prev_hl = (i > 0) ? row->hl[i - 1] : NORMAL;
if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||
(c == '.' && prev_hl == HL_NUMBER)) { if (scs_len && !in_string && !in_comment) {
row->hl[i] = HL_NUMBER; 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++; i++;
prev_sep = 0; prev_sep = 0;
continue; 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); prev_sep = is_separator(c);
i++; 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) char *syntax_to_color(int hl, size_t *len)
{ {
switch (hl) { switch (hl) {
case HL_NUMBER: case NUMBER:
*len = COLOR_LEN; *len = COLOR_LEN;
return strdup(PEACH_BG); return strdup(PEACH_BG);
case HL_MATCH:; 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); char *str = malloc(COLOR_LEN * 2 + 1);
snprintf(str, COLOR_LEN * 2 + 1, "%s%s", BLACK_BG, SKY_FG); snprintf(str, COLOR_LEN * 2 + 1, "%s%s", BLACK_BG, SKY_FG);
*len = COLOR_LEN * 2; *len = COLOR_LEN * 2;
return str; return str;
case HL_RESET:; case RESET:;
char *res = malloc(COLOR_LEN * 2 + 1); char *res = malloc(COLOR_LEN * 2 + 1);
snprintf(res, COLOR_LEN * 2 + 1, "%s%s", WHITE_BG, BLACK_FG); snprintf(res, COLOR_LEN * 2 + 1, "%s%s", WHITE_BG, BLACK_FG);
*len = COLOR_LEN * 2; *len = COLOR_LEN * 2;
@ -55,3 +185,27 @@ char *syntax_to_color(int hl, size_t *len)
} }
} }
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++;
}
}
}