summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Williams <andy@andywilliams.me>2017-01-22 21:58:20 +0000
committerAndy Williams <andy@andywilliams.me>2017-01-22 21:58:20 +0000
commite4fef248987840ae95351119ce48b9855148a2cc (patch)
tree286bf129b562148ee67bd666116bceee49c3b07c
parent633bcfbefbd24d1699a10cec537e2209f0e7a7e0 (diff)
elm_code: Syntax highlighting for multiline comments
-rw-r--r--src/lib/elementary/elm_code_syntax.c116
-rw-r--r--src/tests/elementary/elm_code_test_syntax.c24
2 files changed, 125 insertions, 15 deletions
diff --git a/src/lib/elementary/elm_code_syntax.c b/src/lib/elementary/elm_code_syntax.c
index 96becb9236..a0f4a9e1ea 100644
--- a/src/lib/elementary/elm_code_syntax.c
+++ b/src/lib/elementary/elm_code_syntax.c
@@ -10,12 +10,18 @@
10typedef struct _Elm_Code_Syntax 10typedef struct _Elm_Code_Syntax
11{ 11{
12 const char *symbols; 12 const char *symbols;
13 const char *comment_single;
14 const char *comment_start;
15 const char *comment_end;
13 const char *keywords[]; 16 const char *keywords[];
14} Elm_Code_Syntax; 17} Elm_Code_Syntax;
15 18
16static Elm_Code_Syntax _elm_code_syntax_c = 19static Elm_Code_Syntax _elm_code_syntax_c =
17{ 20{
18 "{}()[]:;*&|!=<->,.", 21 "{}()[]:;/*+&|!=<->,.",
22 "//",
23 "/*",
24 "*/",
19 {"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", \ 25 {"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", \
20 "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", \ 26 "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", \
21 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL} 27 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL}
@@ -52,19 +58,97 @@ _elm_code_syntax_parse_token(Elm_Code_Syntax *syntax, Elm_Code_Line *line, unsig
52 } 58 }
53} 59}
54 60
61static Eina_Bool
62_content_starts_with(const char *content, const char *prefix, unsigned int length)
63{
64 unsigned int i;
65 unsigned int prefix_length;
66
67 prefix_length = strlen(prefix);
68 if (!content || length < prefix_length)
69 return EINA_FALSE;
70
71 for (i = 0; i < prefix_length; i++)
72 if (content[i] != prefix[i])
73 return EINA_FALSE;
74
75 return EINA_TRUE;
76}
77
78static Eina_Bool
79_starts_single_comment(Elm_Code_Syntax *syntax, const char *content, unsigned int length)
80{
81 return _content_starts_with(content, syntax->comment_single, length);
82}
83
84static Eina_Bool
85_starts_comment(Elm_Code_Syntax *syntax, const char *content, unsigned int length)
86{
87 return _content_starts_with(content, syntax->comment_start, length);
88}
89
90static Eina_Bool
91_ends_comment(Elm_Code_Syntax *syntax, const char *content, unsigned int length)
92{
93 return _content_starts_with(content, syntax->comment_end, length);
94}
95
96static Elm_Code_Token_Type
97_previous_line_continue_type(Elm_Code_Line *line)
98{
99 Elm_Code_Line *prev;
100 Elm_Code_Token *token;
101 Eina_List *item;
102
103 if (line->number < 2)
104 return ELM_CODE_TOKEN_TYPE_DEFAULT;
105
106 prev = elm_code_file_line_get(line->file, line->number - 1);
107 if (!prev || !prev->tokens)
108 return ELM_CODE_TOKEN_TYPE_DEFAULT;
109
110 EINA_LIST_FOREACH(prev->tokens, item, token)
111 if (token->continues)
112 return token->type;
113
114 return ELM_CODE_TOKEN_TYPE_DEFAULT;
115}
116
55EAPI void 117EAPI void
56elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line) 118elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line)
57{ 119{
58 unsigned int i, count, length; 120 unsigned int i, i2, count, length;
59 const char *content; 121 const char *content;
60 const char *sym, *ptr; 122 const char *sym, *ptr;
123 Elm_Code_Token_Type previous_type;
61 124
62 EINA_SAFETY_ON_NULL_RETURN(syntax); 125 EINA_SAFETY_ON_NULL_RETURN(syntax);
63 126
64 content = elm_code_line_text_get(line, &length); 127 i = 0;
128 content = elm_code_line_text_get(line, &length);
129 previous_type = _previous_line_continue_type(line);
130 if (previous_type == ELM_CODE_TOKEN_TYPE_COMMENT)
131 {
132 for (i2 = i; i2 < length; i2++)
133 if (_ends_comment(syntax, content + i2, length - i2))
134 {
135 i2 += strlen(syntax->comment_end) - 1;
136 break;
137 }
138
139 elm_code_line_token_add(line, 1, i2, 1, ELM_CODE_TOKEN_TYPE_COMMENT);
140 if (i2 == length)
141 {
142 Elm_Code_Token *token = eina_list_last_data_get(line->tokens);
143 token->continues = EINA_TRUE;
144 return;
145 }
146 i = i2 + 1;
147 }
148
65 ptr = content; 149 ptr = content;
66 count = 0; 150 count = 0;
67 for (i = 0; i < length; i++) 151 for (; i < length; i++)
68 { 152 {
69 if (_elm_code_text_char_is_whitespace(content[i])) 153 if (_elm_code_text_char_is_whitespace(content[i]))
70 { 154 {
@@ -81,11 +165,31 @@ elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line)
81 elm_code_line_token_add(line, i, length - 1, 1, ELM_CODE_TOKEN_TYPE_PREPROCESSOR); 165 elm_code_line_token_add(line, i, length - 1, 1, ELM_CODE_TOKEN_TYPE_PREPROCESSOR);
82 return; 166 return;
83 } 167 }
84 else if (count == 1 && content[i-1] == '/' && content[i] == '/') 168 else if (_starts_single_comment(syntax, content + i, length - i))
85 { 169 {
86 elm_code_line_token_add(line, i - 1, length - 1, 1, ELM_CODE_TOKEN_TYPE_COMMENT); 170 elm_code_line_token_add(line, i, length, 1, ELM_CODE_TOKEN_TYPE_COMMENT);
87 return; 171 return;
88 } 172 }
173 else if (_starts_comment(syntax, content + i, length - i))
174 {
175 for (i2 = i+strlen(syntax->comment_start); i2 < length; i2++)
176 if (_ends_comment(syntax, content + i2, length - i2))
177 {
178 i2 += strlen(syntax->comment_end) - 1;
179 break;
180 }
181
182 elm_code_line_token_add(line, i, i2, 1, ELM_CODE_TOKEN_TYPE_COMMENT);
183 if (i2 == length)
184 {
185 Elm_Code_Token *token = eina_list_last_data_get(line->tokens);
186 token->continues = EINA_TRUE;
187 return;
188 }
189 i = i2;
190 count = 0;
191 continue;
192 }
89 else if (content[i] == '"') 193 else if (content[i] == '"')
90 { 194 {
91 unsigned int start = i, end; 195 unsigned int start = i, end;
diff --git a/src/tests/elementary/elm_code_test_syntax.c b/src/tests/elementary/elm_code_test_syntax.c
index 0eeea6d0c6..8d088789f9 100644
--- a/src/tests/elementary/elm_code_test_syntax.c
+++ b/src/tests/elementary/elm_code_test_syntax.c
@@ -67,6 +67,9 @@ START_TEST (elm_code_syntax_c)
67 elm_code_widget_syntax_enabled_set(widget, EINA_TRUE); 67 elm_code_widget_syntax_enabled_set(widget, EINA_TRUE);
68 68
69 _append_line(file, "#include <stdio.h>"); 69 _append_line(file, "#include <stdio.h>");
70 _append_line(file, "/**");
71 _append_line(file, " * The main method.");
72 _append_line(file, " */");
70 _append_line(file, "int main(int argc, char **argv)"); 73 _append_line(file, "int main(int argc, char **argv)");
71 _append_line(file, "{"); 74 _append_line(file, "{");
72 _append_line(file, " // display a welcome greeting"); 75 _append_line(file, " // display a welcome greeting");
@@ -78,22 +81,25 @@ START_TEST (elm_code_syntax_c)
78 _append_line(file, "}"); 81 _append_line(file, "}");
79 82
80 _assert_line_token_types(file, 1, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_PREPROCESSOR}); 83 _assert_line_token_types(file, 1, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_PREPROCESSOR});
81 _assert_line_token_types(file, 2, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, 84 _assert_line_token_types(file, 2, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT});
85 _assert_line_token_types(file, 3, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT});
86 _assert_line_token_types(file, 4, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT});
87 _assert_line_token_types(file, 5, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE,
82 ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, 88 ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE,
83 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); 89 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE});
84 _assert_line_token_types(file, 3, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE}); 90 _assert_line_token_types(file, 6, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE});
85 _assert_line_token_types(file, 4, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT}); 91 _assert_line_token_types(file, 7, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT});
86 _assert_line_token_types(file, 5, 5, (Elm_Code_Token_Type[5]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, 92 _assert_line_token_types(file, 8, 5, (Elm_Code_Token_Type[5]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE,
87 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE}); 93 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE});
88 _assert_line_token_types(file, 6, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING, 94 _assert_line_token_types(file, 9, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING,
89 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE, 95 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE,
90 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); 96 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE});
91 _assert_line_token_types(file, 7, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_KEYWORD}); 97 _assert_line_token_types(file, 10, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_KEYWORD});
92 _assert_line_token_types(file, 8, 4, (Elm_Code_Token_Type[4]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING, 98 _assert_line_token_types(file, 11, 4, (Elm_Code_Token_Type[4]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING,
93 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); 99 ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE});
94 _assert_line_token_types(file, 9, 3, (Elm_Code_Token_Type[3]){ELM_CODE_TOKEN_TYPE_KEYWORD, 100 _assert_line_token_types(file, 12, 3, (Elm_Code_Token_Type[3]){ELM_CODE_TOKEN_TYPE_KEYWORD,
95 ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE}); 101 ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE});
96 _assert_line_token_types(file, 10, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE}); 102 _assert_line_token_types(file, 13, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE});
97 103
98 elm_code_free(code); 104 elm_code_free(code);
99 elm_shutdown(); 105 elm_shutdown();