Syntax highlighting based on file type

This commit is contained in:
Timothy Warren 2019-08-20 16:33:17 -04:00
parent 337e4aa6bc
commit dad0cbea87

76
kilo.c
View File

@ -44,8 +44,16 @@ enum editorHighlight {
HL_MATCH
};
#define HL_HIGHLIGHT_NUMBERS (1<<0)
/*** data ***/
struct editorSyntax {
char *filetype;
char **filematch;
int flags;
};
typedef struct erow {
int size;
int rsize;
@ -67,11 +75,25 @@ struct editorConfig {
char *filename;
char statusmsg[80];
time_t statusmsg_time;
struct editorSyntax *syntax;
struct termios orig_termios;
};
struct editorConfig E;
/*** filetypes ***/
char *C_HL_extensions[] = { ".c", ".h", ".cpp", NULL };
struct editorSyntax HLDB[] = {
{
"c",
C_HL_extensions,
HL_HIGHLIGHT_NUMBERS
},
};
#define HLDB_ENTRIES (sizeof(HLDB) / sizeof(HLDB[0]))
/*** prototypes ***/
void editorSetStatusMessage(const char *fmt, ...);
@ -269,6 +291,11 @@ void editorUpdateSyntax(erow *row)
row->hl = realloc(row->hl, row->rsize);
memset(row->hl, HL_NORMAL, row->rsize);
if (E.syntax == NULL)
{
return;
}
int prev_sep = 1;
int i = 0;
@ -277,13 +304,17 @@ void editorUpdateSyntax(erow *row)
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))
if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS)
{
if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||
(c == '.' && prev_hl == HL_NUMBER))
{
row->hl[i] = HL_NUMBER;
i++;
prev_sep = 0;
continue;
}
}
prev_sep = is_separator(c);
i++;
@ -305,6 +336,41 @@ int editorSyntaxToColor(int hl)
}
}
void editorSelectSyntaxHighlight()
{
E.syntax = NULL;
if (E.filename == NULL)
{
return;
}
char *ext = strrchr(E.filename, '.');
for (unsigned int j = 0; j < HLDB_ENTRIES; j++)
{
struct editorSyntax *s = &HLDB[j];
unsigned int i = 0;
while (s->filematch[i])
{
int is_ext = (s->filematch[i][0] == '.');
if ((is_ext && ext && !strcmp(ext, s->filematch[i])) ||
( ! is_ext && strstr(E.filename, s->filematch[i])))
{
E.syntax = s;
int filerow;
for (filerow = 0; filerow < E.numrows; filerow++)
{
editorUpdateSyntax(&E.row[filerow]);
}
return;
}
i++;
}
}
}
/*** row operations ***/
int editorRowCxToRx(erow *row, int cx)
@ -552,6 +618,8 @@ void editorOpen(char *filename)
free(E.filename);
E.filename = strdup(filename);
editorSelectSyntaxHighlight();
FILE *fp = fopen(filename, "r");
if ( ! fp)
{
@ -587,6 +655,7 @@ void editorSave()
editorSetStatusMessage("Save aborted");
return;
}
editorSelectSyntaxHighlight();
}
int len;
@ -862,8 +931,8 @@ void editorDrawStatusBar(struct abuf *ab)
int len = snprintf(status, sizeof(status), "%.20s - %d lines %s",
E.filename ? E.filename : "[No Name]", E.numrows,
E.dirty ? "(modified)" : "");
int rlen = snprintf(rstatus, sizeof(rstatus), "%d/%d",
E.cy + 1, E.numrows);
int rlen = snprintf(rstatus, sizeof(rstatus), "%s | %d/%d",
E.syntax ? E.syntax->filetype : "no ft", E.cy + 1, E.numrows);
if (len > E.screencols)
{
@ -1166,6 +1235,7 @@ void initEditor()
E.filename = NULL;
E.statusmsg[0] = '\0';
E.statusmsg_time = 0;
E.syntax = NULL;
if (getWindowSize(&E.screenrows, &E.screencols) == -1)
{