Filetype detect, syntax highlight for single and multiline comment, strings, keywords
This commit is contained in:
parent
6e225f0f52
commit
cd8e86eac7
3 changed files with 191 additions and 25 deletions
|
@ -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);
|
||||||
|
|
10
src/row.c
10
src/row.c
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
200
src/syntax.c
200
src/syntax.c
|
@ -4,54 +4,208 @@
|
||||||
#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)) {
|
||||||
i++;
|
memset(&row->hl[i], COMMENT, row->render_size - i);
|
||||||
prev_sep = 0;
|
break;
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
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:
|
||||||
char *str = malloc(COLOR_LEN * 2 + 1);
|
*len = COLOR_LEN;
|
||||||
snprintf(str, COLOR_LEN * 2 + 1, "%s%s", BLACK_BG, SKY_FG);
|
return strdup(GREEN_BG);
|
||||||
*len = COLOR_LEN * 2;
|
|
||||||
return str;
|
|
||||||
|
|
||||||
case HL_RESET:;
|
case COMMENT:
|
||||||
char *res = malloc(COLOR_LEN * 2 + 1);
|
case MLCOMMENT:
|
||||||
snprintf(res, COLOR_LEN * 2 + 1, "%s%s", WHITE_BG, BLACK_FG);
|
*len = COLOR_LEN;
|
||||||
*len = COLOR_LEN * 2;
|
return strdup(OVERLAY_0_BG);
|
||||||
return res;
|
|
||||||
|
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 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:
|
default:
|
||||||
*len = COLOR_LEN;
|
*len = COLOR_LEN;
|
||||||
return strdup(WHITE_BG);
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue