ajwillia-ms pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=95b0d7ca68c0b5c95cacb9e7cea7c80cf7520823

commit 95b0d7ca68c0b5c95cacb9e7cea7c80cf7520823
Author: Andy Williams <[email protected]>
Date:   Tue Nov 14 19:12:56 2017 +0000

    elm_code: Add basic scope parsing to syntax highlighting.
    
    This is currently displayed by showing scope in the widget gutter
---
 src/lib/elementary/elm_code_line.h          |  3 ++
 src/lib/elementary/elm_code_syntax.c        | 43 ++++++++++++++++++
 src/lib/elementary/elm_code_widget.c        | 68 ++++++++++++++++++++++++-----
 src/tests/elementary/elm_code_test_syntax.c | 31 +++++++++++++
 4 files changed, 133 insertions(+), 12 deletions(-)

diff --git a/src/lib/elementary/elm_code_line.h 
b/src/lib/elementary/elm_code_line.h
index 88196893de..8e832ff5ed 100644
--- a/src/lib/elementary/elm_code_line.h
+++ b/src/lib/elementary/elm_code_line.h
@@ -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);
 
 /**
diff --git a/src/lib/elementary/elm_code_syntax.c 
b/src/lib/elementary/elm_code_syntax.c
index 2cef6c33a2..39046a194a 100644
--- a/src/lib/elementary/elm_code_syntax.c
+++ b/src/lib/elementary/elm_code_syntax.c
@@ -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);
diff --git a/src/lib/elementary/elm_code_widget.c 
b/src/lib/elementary/elm_code_widget.c
index fc20eac6ec..8fa06023de 100644
--- a/src/lib/elementary/elm_code_widget.c
+++ b/src/lib/elementary/elm_code_widget.c
@@ -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,
diff --git a/src/tests/elementary/elm_code_test_syntax.c 
b/src/tests/elementary/elm_code_test_syntax.c
index f3f5c3acd9..7e1d0d13f6 100644
--- a/src/tests/elementary/elm_code_test_syntax.c
+++ b/src/tests/elementary/elm_code_test_syntax.c
@@ -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);
 }

-- 


Reply via email to