forked from enlightenment/efl
elm_code: Add basic scope parsing to syntax highlighting.
This is currently displayed by showing scope in the widget gutter
This commit is contained in:
parent
1227f914e2
commit
95b0d7ca68
|
@ -30,6 +30,7 @@ typedef struct _Elm_Code_Line
|
|||
|
||||
Elm_Code_Status_Type status;
|
||||
Eina_List *tokens;
|
||||
unsigned int scope;
|
||||
|
||||
void *data;
|
||||
char *status_text;
|
||||
|
@ -104,6 +105,8 @@ EAPI void elm_code_line_token_add(Elm_Code_Line *line, int start, int end, int l
|
|||
|
||||
EAPI void elm_code_line_tokens_clear(Elm_Code_Line *line);
|
||||
|
||||
EAPI unsigned int elm_code_line_scope_get(Elm_Code_Line *line);
|
||||
|
||||
EAPI Eina_Bool elm_code_line_contains_widget_cursor(Elm_Code_Line *line);
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,9 +15,30 @@ typedef struct _Elm_Code_Syntax
|
|||
const char *comment_single;
|
||||
const char *comment_start;
|
||||
const char *comment_end;
|
||||
int (*scope_change)(Elm_Code_Line *line);
|
||||
const char *keywords[];
|
||||
} Elm_Code_Syntax;
|
||||
|
||||
static int
|
||||
_elm_code_syntax_scope_change_braces(Elm_Code_Line *line)
|
||||
{
|
||||
unsigned int length, i;
|
||||
const char *content;
|
||||
int change = 0;
|
||||
|
||||
content = elm_code_line_text_get(line, &length);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (*(content + i) == '{')
|
||||
change++;
|
||||
else if (*(content + i) == '}')
|
||||
change--;
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
static Elm_Code_Syntax _elm_code_syntax_c =
|
||||
{
|
||||
"{}()[]:;%^/*+&|~!=<->,.",
|
||||
|
@ -26,6 +47,7 @@ static Elm_Code_Syntax _elm_code_syntax_c =
|
|||
"//",
|
||||
"/*",
|
||||
"*/",
|
||||
_elm_code_syntax_scope_change_braces,
|
||||
{"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", \
|
||||
"float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", \
|
||||
"struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL}
|
||||
|
@ -39,6 +61,7 @@ static Elm_Code_Syntax _elm_code_syntax_rust =
|
|||
"//",
|
||||
NULL,
|
||||
NULL,
|
||||
_elm_code_syntax_scope_change_braces,
|
||||
{"as", "break", "const", "continue", "create", "else", "enum", "extern", "false", "fn", "for", "if", \
|
||||
"impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "Self", "self", \
|
||||
"static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while",
|
||||
|
@ -53,6 +76,7 @@ static Elm_Code_Syntax _elm_code_syntax_py =
|
|||
"#",
|
||||
"\"\"\"",
|
||||
"\"\"\"",
|
||||
NULL,
|
||||
{"False", "None", "True", "and", "as", "assert", "break", "class", \
|
||||
"continue", "def", "del", "elif", "else", "except", "finally", "for", \
|
||||
"from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", \
|
||||
|
@ -67,6 +91,7 @@ static Elm_Code_Syntax _elm_code_syntax_eo =
|
|||
"//",
|
||||
"[[",
|
||||
"]]",
|
||||
_elm_code_syntax_scope_change_braces,
|
||||
{"byte", "ubyte", "char", "short", "ushort", "int", "uint", "long", "ulong", \
|
||||
"llong", "ullong", "int8", "uint8", "int16", "uint16", "int32", "uint32", \
|
||||
"int64", "uint64", "int128", "uint128", "size", "ssize", "intptr", "uintptr", \
|
||||
|
@ -88,6 +113,7 @@ static Elm_Code_Syntax _elm_code_syntax_go =
|
|||
"//",
|
||||
"/*",
|
||||
"*/",
|
||||
_elm_code_syntax_scope_change_braces,
|
||||
{ "break", "case", "chan", "const", "default", "defer", "else", "fallthrough", "for", "func", "go", "goto", \
|
||||
"if", "import", "interface", "map", "package", "range", "return", "select", "struct", "switch", "type", "var", \
|
||||
"true", "false", "iota", "nil", \
|
||||
|
@ -104,6 +130,7 @@ static Elm_Code_Syntax _elm_code_syntax_md =
|
|||
NULL,
|
||||
"<!--",
|
||||
"-->",
|
||||
NULL,
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -223,6 +250,21 @@ _previous_line_continue_type(Elm_Code_Line *line)
|
|||
return ELM_CODE_TOKEN_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_previous_line_scope(Elm_Code_Line *line)
|
||||
{
|
||||
Elm_Code_Line *prev;
|
||||
|
||||
if (line->number < 2)
|
||||
return 0;
|
||||
|
||||
prev = elm_code_file_line_get(line->file, line->number - 1);
|
||||
if (!prev)
|
||||
return 0;
|
||||
|
||||
return prev->scope;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line)
|
||||
{
|
||||
|
@ -232,6 +274,7 @@ elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line)
|
|||
Elm_Code_Token_Type previous_type;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(syntax);
|
||||
line->scope = _previous_line_scope(line) + _elm_code_syntax_scope_change_braces(line);
|
||||
|
||||
i = 0;
|
||||
content = elm_code_line_text_get(line, &length);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
typedef enum {
|
||||
ELM_CODE_WIDGET_COLOR_GUTTER_BG = ELM_CODE_TOKEN_TYPE_COUNT,
|
||||
ELM_CODE_WIDGET_COLOR_GUTTER_SCOPE_BG,
|
||||
ELM_CODE_WIDGET_COLOR_GUTTER_FG,
|
||||
ELM_CODE_WIDGET_COLOR_WHITESPACE,
|
||||
ELM_CODE_WIDGET_COLOR_SELECTION,
|
||||
|
@ -189,13 +190,45 @@ _elm_code_widget_fill_line_tokens(Elm_Code_Widget *widget, Evas_Textgrid_Cell *c
|
|||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_elm_code_widget_line_in_scope(Elm_Code_Line *line, Elm_Code_Line *fromline)
|
||||
{
|
||||
Elm_Code_Line *midline;
|
||||
unsigned int number;
|
||||
|
||||
if (line->scope == 0 || fromline->scope == 0)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (line->number == fromline->number)
|
||||
return EINA_TRUE;
|
||||
|
||||
if (line->scope < fromline->scope)
|
||||
return EINA_FALSE;
|
||||
|
||||
number = fromline->number;
|
||||
while (number != line->number)
|
||||
{
|
||||
midline = elm_code_file_line_get(line->file, number);
|
||||
|
||||
if (midline->scope < fromline->scope)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (line->number < fromline->number)
|
||||
number--;
|
||||
else
|
||||
number++;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_elm_code_widget_fill_gutter(Elm_Code_Widget *widget, Evas_Textgrid_Cell *cells,
|
||||
int width, Elm_Code_Status_Type status, int line)
|
||||
_elm_code_widget_fill_line_gutter(Elm_Code_Widget *widget, Evas_Textgrid_Cell *cells,
|
||||
int width, Elm_Code_Line *line)
|
||||
{
|
||||
char *number = NULL;
|
||||
int gutter, g;
|
||||
Elm_Code_Widget_Data *pd;
|
||||
Elm_Code_Line *cursor_line;
|
||||
|
||||
pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
|
||||
gutter = elm_code_widget_text_left_gutter_width_get(widget);
|
||||
|
@ -203,17 +236,28 @@ _elm_code_widget_fill_gutter(Elm_Code_Widget *widget, Evas_Textgrid_Cell *cells,
|
|||
if (width < gutter)
|
||||
return;
|
||||
|
||||
cells[gutter-1].codepoint = status_icons[status];
|
||||
cells[gutter-1].codepoint = status_icons[line->status];
|
||||
cells[gutter-1].bold = 1;
|
||||
cells[gutter-1].fg = ELM_CODE_WIDGET_COLOR_GUTTER_FG;
|
||||
cells[gutter-1].bg = (status == ELM_CODE_STATUS_TYPE_DEFAULT) ? ELM_CODE_WIDGET_COLOR_GUTTER_BG : status;
|
||||
if (line->status == ELM_CODE_STATUS_TYPE_DEFAULT)
|
||||
{
|
||||
cursor_line = elm_code_file_line_get(line->file, pd->cursor_line);
|
||||
if (_elm_code_widget_line_in_scope(line, cursor_line))
|
||||
cells[gutter-1].bg = ELM_CODE_WIDGET_COLOR_GUTTER_SCOPE_BG;
|
||||
else
|
||||
cells[gutter-1].bg = ELM_CODE_WIDGET_COLOR_GUTTER_BG;
|
||||
}
|
||||
else
|
||||
{
|
||||
cells[gutter-1].bg = line->status;
|
||||
}
|
||||
|
||||
if (pd->show_line_numbers)
|
||||
{
|
||||
if (line > 0)
|
||||
if (line->number > 0)
|
||||
{
|
||||
number = malloc(sizeof(char) * gutter);
|
||||
snprintf(number, gutter, "%*d", gutter - 1, line);
|
||||
snprintf(number, gutter, "%*d", gutter - 1, line->number);
|
||||
}
|
||||
for (g = 0; g < gutter - 1; g++)
|
||||
{
|
||||
|
@ -375,7 +419,7 @@ _elm_code_widget_fill_line(Elm_Code_Widget *widget, Elm_Code_Line *line)
|
|||
cells[x].bg = _elm_code_widget_status_type_get(widget, line, x - gutter + 1);
|
||||
}
|
||||
|
||||
_elm_code_widget_fill_gutter(widget, cells, w, line->status, line->number);
|
||||
_elm_code_widget_fill_line_gutter(widget, cells, w, line);
|
||||
_elm_code_widget_fill_line_tokens(widget, cells, w, line);
|
||||
|
||||
_elm_code_widget_fill_selection(widget, line, cells, gutter, w);
|
||||
|
@ -634,11 +678,9 @@ _elm_code_widget_cursor_move(Elm_Code_Widget *widget, Elm_Code_Widget_Data *pd,
|
|||
_elm_code_widget_cursor_ensure_visible(widget);
|
||||
|
||||
if (oldrow != pd->cursor_line)
|
||||
{
|
||||
if (oldrow <= elm_code_file_lines_get(code->file))
|
||||
_elm_code_widget_fill_line(widget, elm_code_file_line_get(pd->code->file, oldrow));
|
||||
}
|
||||
_elm_code_widget_fill_line(widget, elm_code_file_line_get(pd->code->file, pd->cursor_line));
|
||||
_elm_code_widget_refresh(widget, line_obj);
|
||||
else
|
||||
_elm_code_widget_fill_line(widget, elm_code_file_line_get(pd->code->file, pd->cursor_line));
|
||||
elm_layout_signal_emit(pd->cursor_rect, "elm,action,show,cursor", "elm");
|
||||
}
|
||||
|
||||
|
@ -1813,6 +1855,8 @@ _elm_code_widget_setup_palette(Evas_Object *o)
|
|||
51, 153, 255, 255);
|
||||
evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_GUTTER_BG,
|
||||
75, 75, 75, 255);
|
||||
evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_GUTTER_SCOPE_BG,
|
||||
54, 54, 54, 255);
|
||||
evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_GUTTER_FG,
|
||||
139, 139, 139, 255);
|
||||
evas_object_textgrid_palette_set(o, EVAS_TEXTGRID_PALETTE_STANDARD, ELM_CODE_WIDGET_COLOR_WHITESPACE,
|
||||
|
|
|
@ -116,8 +116,39 @@ START_TEST (elm_code_syntax_c)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (elm_code_syntax_scope_change_braces_test)
|
||||
{
|
||||
Elm_Code_File *file;
|
||||
Elm_Code_Line *line;
|
||||
Elm_Code *code;
|
||||
|
||||
elm_init(1, NULL);
|
||||
code = elm_code_create();
|
||||
code->file->mime = "text/x-csrc";
|
||||
elm_code_parser_standard_add(code, ELM_CODE_PARSER_STANDARD_SYNTAX);
|
||||
file = code->file;
|
||||
|
||||
elm_code_file_line_append(file, "#include <stdio.h>", 18, NULL);
|
||||
line = elm_code_file_line_get(file, 1);
|
||||
ck_assert_int_eq(0, line->scope);
|
||||
|
||||
elm_code_file_line_append(file, "int main() {", 12, NULL);
|
||||
line = elm_code_file_line_get(file, 2);
|
||||
ck_assert_int_eq(1, line->scope);
|
||||
|
||||
elm_code_file_line_append(file, "}", 1, NULL);
|
||||
elm_code_file_line_append(file, "", 0, NULL);
|
||||
line = elm_code_file_line_get(file, 4);
|
||||
ck_assert_int_eq(0, line->scope);
|
||||
|
||||
elm_code_free(code);
|
||||
elm_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void elm_code_test_syntax(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, elm_code_syntax_lookup);
|
||||
tcase_add_test(tc, elm_code_syntax_c);
|
||||
tcase_add_test(tc, elm_code_syntax_scope_change_braces_test);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue