summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Williams <andy@andywilliams.me>2017-01-20 22:09:16 +0000
committerAndy Williams <andy@andywilliams.me>2017-01-20 22:11:01 +0000
commit5851a9d4a82b1fb5638d46f510fe9e8b6c7bdbb4 (patch)
tree9f457827fa32944125d607cff6c5218a5234a85b
parent3090e9c3ae3b12e36cf62dff224d6f6146bcc9d4 (diff)
elm_code: Add initial simple syntax highlighting for C code
For c source and headers lookup a simple syntax definition. Use a very simple text processing line by line to tokenise. Simple but it gets us one step closer to cross-language syntax
-rw-r--r--src/Makefile_Elementary.am5
-rw-r--r--src/bin/elementary/test.c2
-rw-r--r--src/bin/elementary/test_code.c48
-rw-r--r--src/lib/elementary/elm_code.h1
-rw-r--r--src/lib/elementary/elm_code_file.c1
-rw-r--r--src/lib/elementary/elm_code_file.h1
-rw-r--r--src/lib/elementary/elm_code_parse.c31
-rw-r--r--src/lib/elementary/elm_code_parse.h1
-rw-r--r--src/lib/elementary/elm_code_private.h2
-rw-r--r--src/lib/elementary/elm_code_syntax.c135
-rw-r--r--src/lib/elementary/elm_code_syntax.h65
-rw-r--r--src/lib/elementary/elm_code_text.c12
-rw-r--r--src/lib/elementary/elm_code_widget.c24
-rw-r--r--src/lib/elementary/elm_code_widget.eo13
-rw-r--r--src/tests/elementary/elm_code_test_syntax.c107
-rw-r--r--src/tests/elementary/elm_suite.c1
-rw-r--r--src/tests/elementary/elm_suite.h1
17 files changed, 446 insertions, 4 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 6e4122b443..c3c685e11e 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -278,7 +278,8 @@ includesunstable_HEADERS = \
278 lib/elementary/elm_code_text.h \ 278 lib/elementary/elm_code_text.h \
279 lib/elementary/elm_code_indent.h \ 279 lib/elementary/elm_code_indent.h \
280 lib/elementary/elm_code_file.h \ 280 lib/elementary/elm_code_file.h \
281 lib/elementary/elm_code_parse.h 281 lib/elementary/elm_code_parse.h \
282 lib/elementary/elm_code_syntax.h
282includesunstabledir = $(includedir)/elementary-@VMAJ@ 283includesunstabledir = $(includedir)/elementary-@VMAJ@
283 284
284nodist_includesunstable_HEADERS = \ 285nodist_includesunstable_HEADERS = \
@@ -557,6 +558,7 @@ lib_elementary_libelementary_la_SOURCES = \
557 lib/elementary/elm_code_indent.c \ 558 lib/elementary/elm_code_indent.c \
558 lib/elementary/elm_code_file.c \ 559 lib/elementary/elm_code_file.c \
559 lib/elementary/elm_code_parse.c \ 560 lib/elementary/elm_code_parse.c \
561 lib/elementary/elm_code_syntax.c \
560 lib/elementary/elm_code_widget_selection.c \ 562 lib/elementary/elm_code_widget_selection.c \
561 lib/elementary/elm_code_widget.c \ 563 lib/elementary/elm_code_widget.c \
562 lib/elementary/elm_code_diff_widget.c \ 564 lib/elementary/elm_code_diff_widget.c \
@@ -1321,6 +1323,7 @@ tests_elementary_elm_suite_SOURCES = \
1321 tests/elementary/elm_code_test_basic.c \ 1323 tests/elementary/elm_code_test_basic.c \
1322 tests/elementary/elm_code_test_line.c \ 1324 tests/elementary/elm_code_test_line.c \
1323 tests/elementary/elm_code_test_parse.c \ 1325 tests/elementary/elm_code_test_parse.c \
1326 tests/elementary/elm_code_test_syntax.c \
1324 tests/elementary/elm_code_test_text.c \ 1327 tests/elementary/elm_code_test_text.c \
1325 tests/elementary/elm_code_test_indent.c \ 1328 tests/elementary/elm_code_test_indent.c \
1326 tests/elementary/elm_code_test_widget.c \ 1329 tests/elementary/elm_code_test_widget.c \
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index cf9f568aa1..479474a965 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -294,6 +294,7 @@ void test_colorclass(void *data, Evas_Object *obj, void *event_info);
294 294
295void test_code_welcome(void *data, Evas_Object *obj, void *event_info); 295void test_code_welcome(void *data, Evas_Object *obj, void *event_info);
296void test_code_editor(void *data, Evas_Object *obj, void *event_info); 296void test_code_editor(void *data, Evas_Object *obj, void *event_info);
297void test_code_syntax(void *data, Evas_Object *obj, void *event_info);
297void test_code_mirror(void *data, Evas_Object *obj, void *event_info); 298void test_code_mirror(void *data, Evas_Object *obj, void *event_info);
298void test_code_log(void *data, Evas_Object *obj, void *event_info); 299void test_code_log(void *data, Evas_Object *obj, void *event_info);
299void test_code_diff(void *data, Evas_Object *obj, void *event_info); 300void test_code_diff(void *data, Evas_Object *obj, void *event_info);
@@ -732,6 +733,7 @@ add_tests:
732 //------------------------------// 733 //------------------------------//
733 ADD_TEST(NULL, "Advanced Entries", "Code Entry Markup", test_code_welcome); 734 ADD_TEST(NULL, "Advanced Entries", "Code Entry Markup", test_code_welcome);
734 ADD_TEST(NULL, "Advanced Entries", "Code Editor", test_code_editor); 735 ADD_TEST(NULL, "Advanced Entries", "Code Editor", test_code_editor);
736 ADD_TEST(NULL, "Advanced Entries", "Code Syntax", test_code_syntax);
735 ADD_TEST(NULL, "Advanced Entries", "Mirrored Editor", test_code_mirror); 737 ADD_TEST(NULL, "Advanced Entries", "Mirrored Editor", test_code_mirror);
736 ADD_TEST(NULL, "Advanced Entries", "Logger", test_code_log); 738 ADD_TEST(NULL, "Advanced Entries", "Logger", test_code_log);
737 ADD_TEST(NULL, "Advanced Entries", "Diff Comparison", test_code_diff); 739 ADD_TEST(NULL, "Advanced Entries", "Diff Comparison", test_code_diff);
diff --git a/src/bin/elementary/test_code.c b/src/bin/elementary/test_code.c
index 4f3408a082..906a36a802 100644
--- a/src/bin/elementary/test_code.c
+++ b/src/bin/elementary/test_code.c
@@ -109,6 +109,39 @@ _elm_code_test_editor_setup(Evas_Object *parent, Eina_Bool log)
109} 109}
110 110
111static Evas_Object * 111static Evas_Object *
112_elm_code_test_syntax_setup(Evas_Object *parent)
113{
114 Elm_Code *code;
115 Elm_Code_Widget *widget;
116
117 code = elm_code_create();
118 widget = efl_add(ELM_CODE_WIDGET_CLASS, parent, elm_obj_code_widget_code_set(efl_added, code));
119 elm_obj_code_widget_font_set(widget, NULL, 14);
120 elm_obj_code_widget_editable_set(widget, EINA_TRUE);
121 elm_obj_code_widget_syntax_enabled_set(widget, EINA_TRUE);
122 elm_obj_code_widget_code_get(widget)->file->mime = "text/x-csrc";
123 elm_obj_code_widget_show_whitespace_set(widget, EINA_TRUE);
124 elm_obj_code_widget_line_numbers_set(widget, EINA_TRUE);
125
126 _append_line(code->file, "#include <stdio.h>");
127 _append_line(code->file, "int main(int argc, char **argv)");
128 _append_line(code->file, "{");
129 _append_line(code->file, " // display a welcome greeting");
130 _append_line(code->file, " if (argc > 0)");
131 _append_line(code->file, " printf(\"Hello, %s!\\n\", argv[0]);");
132 _append_line(code->file, " else");
133 _append_line(code->file, " printf(\"Hello, World!\\n\");");
134 _append_line(code->file, " return 0;");
135 _append_line(code->file, "}");
136
137 evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
138 evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
139 evas_object_show(widget);
140
141 return widget;
142}
143
144static Evas_Object *
112_elm_code_test_mirror_setup(Elm_Code *code, char *font_name, Evas_Object *parent) 145_elm_code_test_mirror_setup(Elm_Code *code, char *font_name, Evas_Object *parent)
113{ 146{
114 Elm_Code_Widget *widget; 147 Elm_Code_Widget *widget;
@@ -202,6 +235,21 @@ test_code_editor(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve
202} 235}
203 236
204void 237void
238test_code_syntax(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
239{
240 Evas_Object *win, *screen;
241
242 win = _test_code_win_create("code-syntax", "Code Syntax");
243 screen = elm_box_add(win);
244 evas_object_size_hint_weight_set(screen, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
245 elm_box_pack_end(screen, _elm_code_test_syntax_setup(screen));
246 elm_win_resize_object_add(win, screen);
247 evas_object_show(screen);
248
249 evas_object_show(win);
250}
251
252void
205test_code_log(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 253test_code_log(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
206{ 254{
207 Evas_Object *win, *screen, *o, *code; 255 Evas_Object *win, *screen, *o, *code;
diff --git a/src/lib/elementary/elm_code.h b/src/lib/elementary/elm_code.h
index 7b96c04f4b..9ffd0e9ad1 100644
--- a/src/lib/elementary/elm_code.h
+++ b/src/lib/elementary/elm_code.h
@@ -9,6 +9,7 @@
9#include "elm_code_indent.h" 9#include "elm_code_indent.h"
10#include "elm_code_file.h" 10#include "elm_code_file.h"
11#include "elm_code_parse.h" 11#include "elm_code_parse.h"
12#include "elm_code_syntax.h"
12#include "elm_code_widget.eo.h" 13#include "elm_code_widget.eo.h"
13#include "elm_code_widget_legacy.h" 14#include "elm_code_widget_legacy.h"
14#include "elm_code_widget_selection.h" 15#include "elm_code_widget_selection.h"
diff --git a/src/lib/elementary/elm_code_file.c b/src/lib/elementary/elm_code_file.c
index 8e015de6f0..9188050649 100644
--- a/src/lib/elementary/elm_code_file.c
+++ b/src/lib/elementary/elm_code_file.c
@@ -128,6 +128,7 @@ EAPI Elm_Code_File *elm_code_file_open(Elm_Code *code, const char *path)
128 ret = elm_code_file_new(code); 128 ret = elm_code_file_new(code);
129 file = eina_file_open(path, EINA_FALSE); 129 file = eina_file_open(path, EINA_FALSE);
130 ret->file = file; 130 ret->file = file;
131 ret->mime = efreet_mime_type_get(path);
131 lastindex = 1; 132 lastindex = 1;
132 133
133 ret->map = eina_file_map_all(file, EINA_FILE_POPULATE); 134 ret->map = eina_file_map_all(file, EINA_FILE_POPULATE);
diff --git a/src/lib/elementary/elm_code_file.h b/src/lib/elementary/elm_code_file.h
index e7f2cabb12..9bafe431ac 100644
--- a/src/lib/elementary/elm_code_file.h
+++ b/src/lib/elementary/elm_code_file.h
@@ -22,6 +22,7 @@ struct _Elm_Code_File
22 Eina_List *lines; 22 Eina_List *lines;
23 Eina_File *file; 23 Eina_File *file;
24 void *map; 24 void *map;
25 const char *mime;
25 26
26 Elm_Code_File_Line_Ending line_ending; 27 Elm_Code_File_Line_Ending line_ending;
27}; 28};
diff --git a/src/lib/elementary/elm_code_parse.c b/src/lib/elementary/elm_code_parse.c
index 04b45ce2cf..8f7243df2a 100644
--- a/src/lib/elementary/elm_code_parse.c
+++ b/src/lib/elementary/elm_code_parse.c
@@ -6,6 +6,7 @@
6 6
7#include "elm_code_private.h" 7#include "elm_code_private.h"
8 8
9EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_SYNTAX = NULL;
9EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF = NULL; 10EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF = NULL;
10EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO = NULL; 11EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO = NULL;
11 12
@@ -126,6 +127,34 @@ _elm_code_parser_diff_trim_leading(Elm_Code_Line *line, unsigned int count)
126 line->length -= count; 127 line->length -= count;
127} 128}
128 129
130#define _PARSE_C_SYMBOLS "{}()[]:;*&|!=<->,."
131#define _PARSE_C_KEYWORDS {"auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", \
132 "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", \
133 "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL}
134
135static void
136_elm_code_parser_syntax_parse_line(Elm_Code_Line *line, void *data EINA_UNUSED)
137{
138 Elm_Code_Syntax *syntax;
139
140 syntax = elm_code_syntax_for_mime_get(line->file->mime);
141 if (syntax)
142 elm_code_syntax_parse_line(syntax, line);
143}
144
145static void
146_elm_code_parser_syntax_parse_file(Elm_Code_File *file, void *data EINA_UNUSED)
147{
148 Elm_Code_Syntax *syntax;
149 INF("Parse syntax of file with mime \"%s\"", file->mime);
150
151 syntax = elm_code_syntax_for_mime_get(file->mime);
152 if (!syntax)
153 WRN("Unsupported mime in parser");
154 else
155 elm_code_syntax_parse_file(syntax, file);
156}
157
129static void 158static void
130_elm_code_parser_diff_parse_line(Elm_Code_Line *line, void *data EINA_UNUSED) 159_elm_code_parser_diff_parse_line(Elm_Code_Line *line, void *data EINA_UNUSED)
131{ 160{
@@ -200,6 +229,8 @@ _elm_code_parser_free(Elm_Code_Parser *parser)
200void 229void
201_elm_code_parse_setup() 230_elm_code_parse_setup()
202{ 231{
232 ELM_CODE_PARSER_STANDARD_SYNTAX = _elm_code_parser_new(_elm_code_parser_syntax_parse_line,
233 _elm_code_parser_syntax_parse_file);
203 ELM_CODE_PARSER_STANDARD_DIFF = _elm_code_parser_new(_elm_code_parser_diff_parse_line, 234 ELM_CODE_PARSER_STANDARD_DIFF = _elm_code_parser_new(_elm_code_parser_diff_parse_line,
204 _elm_code_parser_diff_parse_file); 235 _elm_code_parser_diff_parse_file);
205 ELM_CODE_PARSER_STANDARD_TODO = _elm_code_parser_new(_elm_code_parser_todo_parse_line, NULL); 236 ELM_CODE_PARSER_STANDARD_TODO = _elm_code_parser_new(_elm_code_parser_todo_parse_line, NULL);
diff --git a/src/lib/elementary/elm_code_parse.h b/src/lib/elementary/elm_code_parse.h
index d5a78cec83..4b53e0f2c9 100644
--- a/src/lib/elementary/elm_code_parse.h
+++ b/src/lib/elementary/elm_code_parse.h
@@ -12,6 +12,7 @@ extern "C" {
12 12
13typedef struct _Elm_Code_Parser Elm_Code_Parser; 13typedef struct _Elm_Code_Parser Elm_Code_Parser;
14 14
15extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_SYNTAX; /**< A provided parser to provide syntax highlighting */
15extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF; /**< A provided parser that will mark up diff text */ 16extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF; /**< A provided parser that will mark up diff text */
16extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO; /**< A provided parser that will highlight TODO and FIXME lines */ 17extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO; /**< A provided parser that will highlight TODO and FIXME lines */
17 18
diff --git a/src/lib/elementary/elm_code_private.h b/src/lib/elementary/elm_code_private.h
index aae7884ead..6cc9e3ae29 100644
--- a/src/lib/elementary/elm_code_private.h
+++ b/src/lib/elementary/elm_code_private.h
@@ -1,6 +1,8 @@
1#ifndef ELM_CODE_PRIVATE_H 1#ifndef ELM_CODE_PRIVATE_H
2# define ELM_CODE_PRIVATE_H 2# define ELM_CODE_PRIVATE_H
3 3
4#include "elm_priv.h"
5
4Eina_Bool _elm_code_text_char_is_whitespace(char c); 6Eina_Bool _elm_code_text_char_is_whitespace(char c);
5 7
6/* Private parser callbacks */ 8/* Private parser callbacks */
diff --git a/src/lib/elementary/elm_code_syntax.c b/src/lib/elementary/elm_code_syntax.c
new file mode 100644
index 0000000000..3a35f2e632
--- /dev/null
+++ b/src/lib/elementary/elm_code_syntax.c
@@ -0,0 +1,135 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Eina.h>
6#include "Elementary.h"
7
8#include "elm_code_private.h"
9
10typedef struct _Elm_Code_Syntax
11{
12 const char *symbols;
13 const char *keywords[];
14} Elm_Code_Syntax;
15
16static Elm_Code_Syntax _elm_code_syntax_c =
17{
18 "{}()[]:;*&|!=<->,.",
19 {"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", \
21 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL}
22};
23
24EAPI Elm_Code_Syntax *
25elm_code_syntax_for_mime_get(const char *mime)
26{
27 if (!strcmp("text/x-chdr", mime) || !strcmp("text/x-csrc", mime))
28 return &_elm_code_syntax_c;
29
30 return NULL;
31}
32
33static void
34_elm_code_syntax_parse_token(Elm_Code_Syntax *syntax, Elm_Code_Line *line, unsigned int pos, const char *token, unsigned int length)
35{
36 const char **keyword;
37 unsigned int i;
38
39 for (keyword = syntax->keywords; *keyword; keyword++)
40 if (strlen(*keyword) == length && !strncmp(token, *keyword, length))
41 {
42 elm_code_line_token_add(line, pos, pos + length - 1, 1, ELM_CODE_TOKEN_TYPE_KEYWORD);
43 return;
44 }
45
46 for (i = 0; i < length; i++)
47 {
48 if (!isdigit(token[i]))
49 break;
50 if (i == length - 1)
51 elm_code_line_token_add(line, pos, pos + length - 1, 1, ELM_CODE_TOKEN_TYPE_NUMBER);
52 }
53}
54
55EAPI void
56elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line)
57{
58 unsigned int i, count, length;
59 const char *content;
60 const char *sym, *ptr;
61
62 EINA_SAFETY_ON_NULL_RETURN(syntax);
63
64 content = elm_code_line_text_get(line, &length);
65 ptr = content;
66 count = 0;
67 for (i = 0; i < length; i++)
68 {
69 if (_elm_code_text_char_is_whitespace(content[i]))
70 {
71 if (count)
72 _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count);
73
74 ptr += count+1;
75 count = 0;
76 continue;
77 }
78
79 if (content[i] == '#')
80 {
81 elm_code_line_token_add(line, i, length - 1, 1, ELM_CODE_TOKEN_TYPE_PREPROCESSOR);
82 return;
83 }
84 else if (count == 1 && content[i-1] == '/' && content[i] == '/')
85 {
86 elm_code_line_token_add(line, i - 1, length - 1, 1, ELM_CODE_TOKEN_TYPE_COMMENT);
87 return;
88 }
89 else if (content[i] == '"')
90 {
91 unsigned int start = i, end;
92
93 for (i++; content[i] != '"' && i < length; i++) {}
94 end = i;
95
96 elm_code_line_token_add(line, start, end, 1, ELM_CODE_TOKEN_TYPE_STRING);
97 continue;
98 }
99 else if (content[i] == '\'')
100 {
101 unsigned int start = i, end;
102
103 for (i++; content[i] != '\'' && i < length; i++) {}
104 end = i;
105
106 elm_code_line_token_add(line, start, end, 1, ELM_CODE_TOKEN_TYPE_STRING);
107 continue;
108 }
109
110 for (sym = syntax->symbols; *sym; sym++)
111 if (content[i] == *sym)
112 {
113 if (count)
114 _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count);
115
116 elm_code_line_token_add(line, i, i, 1, ELM_CODE_TOKEN_TYPE_BRACE);
117
118 ptr = content + i+1;
119 count = -1;
120 break;
121 }
122
123 count++;
124 }
125
126 if (count)
127 _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count);
128}
129
130EAPI void
131elm_code_syntax_parse_file(Elm_Code_Syntax *syntax, Elm_Code_File *file EINA_UNUSED)
132{
133 EINA_SAFETY_ON_NULL_RETURN(syntax);
134}
135
diff --git a/src/lib/elementary/elm_code_syntax.h b/src/lib/elementary/elm_code_syntax.h
new file mode 100644
index 0000000000..268e11a63f
--- /dev/null
+++ b/src/lib/elementary/elm_code_syntax.h
@@ -0,0 +1,65 @@
1#ifndef ELM_CODE_SYNTAX_H_
2# define ELM_CODE_SYNTAX_H_
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8/**
9 * @file
10 * @brief These routines are used for handling the parsing of Elm Code content.
11 */
12
13typedef struct _Elm_Code_Syntax Elm_Code_Syntax;
14
15/**
16 * @brief Syntax highlighting helper functions.
17 * @defgroup Syntax Parsing and marking up syntax in files
18 *
19 * @{
20 *
21 * Syntax functions for adding syntax highlighting to elm code.
22 *
23 */
24
25/**
26 * Lookup a syntax definition from a mime type.
27 * If there is no syntax known NULL will be returned.
28 *
29 * @param mime The mime type to be looked up for a matching syntax definition
30 * @return A syntax definition, if one is found, or NULL
31 *
32 * @ingroup Syntax
33 */
34EAPI Elm_Code_Syntax *elm_code_syntax_for_mime_get(const char *mime);
35
36/**
37 * Parse a line and apply the syntax definition by inserting Elm_Code_Token into the line.
38 *
39 * @param syntax The syntax definition to use (from elm_code_syntax_for_mime_get)
40 * @param line The line that contains the content to parse and will receive the tokens
41 *
42 * @ingroup Syntax
43 */
44EAPI void elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line);
45
46/**
47 * Parse a file and apply the syntax definition one line at a time.
48 *
49 * @param syntax The syntax definition to use (from elm_code_syntax_for_mime_get)
50 * @param file The file to parse - each line in the file will be processed
51 *
52 * @ingroup Syntax
53 */
54EAPI void elm_code_syntax_parse_file(Elm_Code_Syntax *syntax, Elm_Code_File *file);
55
56
57/**
58 * @}
59 */
60
61#ifdef __cplusplus
62}
63#endif
64
65#endif /* ELM_CODE_SYNTAX_H_ */
diff --git a/src/lib/elementary/elm_code_text.c b/src/lib/elementary/elm_code_text.c
index d472894c91..bf25514f5f 100644
--- a/src/lib/elementary/elm_code_text.c
+++ b/src/lib/elementary/elm_code_text.c
@@ -172,7 +172,11 @@ elm_code_line_text_insert(Elm_Code_Line *line, unsigned int position, const char
172 line->length += length; 172 line->length += length;
173 173
174 file = line->file; 174 file = line->file;
175 elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); 175 if (file->parent)
176 {
177 _elm_code_parse_line(file->parent, line);
178 elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line);
179 }
176} 180}
177 181
178EAPI void 182EAPI void
@@ -207,7 +211,11 @@ elm_code_line_text_remove(Elm_Code_Line *line, unsigned int position, int length
207 line->length -= length; 211 line->length -= length;
208 212
209 file = line->file; 213 file = line->file;
210 elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); 214 if (file->parent)
215 {
216 _elm_code_parse_line(file->parent, line);
217 elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line);
218 }
211} 219}
212 220
213Eina_Bool 221Eina_Bool
diff --git a/src/lib/elementary/elm_code_widget.c b/src/lib/elementary/elm_code_widget.c
index 9e06e523f2..67a5d96c43 100644
--- a/src/lib/elementary/elm_code_widget.c
+++ b/src/lib/elementary/elm_code_widget.c
@@ -2076,6 +2076,30 @@ _elm_code_widget_show_whitespace_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *
2076} 2076}
2077 2077
2078EOLIAN static void 2078EOLIAN static void
2079_elm_code_widget_syntax_enabled_set(Eo *obj, Elm_Code_Widget_Data *pd EINA_UNUSED,
2080 Eina_Bool enabled)
2081{
2082 Elm_Code_Widget *widget = obj;
2083 Elm_Code *code;
2084
2085 code = elm_code_widget_code_get(widget);
2086 if (enabled)
2087 elm_code_parser_standard_add(code, ELM_CODE_PARSER_STANDARD_SYNTAX);
2088 else
2089 code->parsers = eina_list_remove(code->parsers, ELM_CODE_PARSER_STANDARD_SYNTAX);
2090}
2091
2092EOLIAN static Eina_Bool
2093_elm_code_widget_syntax_enabled_get(Eo *obj, Elm_Code_Widget_Data *pd EINA_UNUSED)
2094{
2095 Elm_Code_Widget *widget = obj;
2096 Elm_Code *code;
2097
2098 code = elm_code_widget_code_get(widget);
2099 return !!eina_list_data_find(code->parsers, ELM_CODE_PARSER_STANDARD_SYNTAX);
2100}
2101
2102EOLIAN static void
2079_elm_code_widget_tab_inserts_spaces_set(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd, 2103_elm_code_widget_tab_inserts_spaces_set(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd,
2080 Eina_Bool spaces) 2104 Eina_Bool spaces)
2081{ 2105{
diff --git a/src/lib/elementary/elm_code_widget.eo b/src/lib/elementary/elm_code_widget.eo
index a63f9197d7..f6bf6f48a4 100644
--- a/src/lib/elementary/elm_code_widget.eo
+++ b/src/lib/elementary/elm_code_widget.eo
@@ -140,7 +140,7 @@ class Elm.Code_Widget (Elm.Layout, Elm.Interface.Atspi.Text)
140 } 140 }
141 @property show_whitespace { 141 @property show_whitespace {
142 set { 142 set {
143 [[Set where white space should be shown.]] 143 [[Set whether white space should be shown.]]
144 } 144 }
145 get { 145 get {
146 [[Get whether or not white space will be visible.]] 146 [[Get whether or not white space will be visible.]]
@@ -149,6 +149,17 @@ class Elm.Code_Widget (Elm.Layout, Elm.Interface.Atspi.Text)
149 show_whitespace: bool; [[Whether or not we show whitespace characters]] 149 show_whitespace: bool; [[Whether or not we show whitespace characters]]
150 } 150 }
151 } 151 }
152 @property syntax_enabled {
153 set {
154 [[Set whether syntax highlighting should be use for this widget.]]
155 }
156 get {
157 [[Get this widget's enabled state for syntax highlighting.]]
158 }
159 values {
160 syntax_enabled: bool; [[Whether or not to enable syntax highlighting]]
161 }
162 }
152 @property tab_inserts_spaces { 163 @property tab_inserts_spaces {
153 set { 164 set {
154 [[Set whether space characters should be inserted instead of tabs.]] 165 [[Set whether space characters should be inserted instead of tabs.]]
diff --git a/src/tests/elementary/elm_code_test_syntax.c b/src/tests/elementary/elm_code_test_syntax.c
new file mode 100644
index 0000000000..0eeea6d0c6
--- /dev/null
+++ b/src/tests/elementary/elm_code_test_syntax.c
@@ -0,0 +1,107 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include "elm_suite.h"
6#include "Elementary.h"
7#include "elm_code_syntax.h"
8
9static void
10_append_line(Elm_Code_File *file, const char *line)
11{
12 int length;
13
14 length = strlen(line);
15 elm_code_file_line_append(file, line, length, NULL);
16}
17
18static void
19_assert_line_token_types(Elm_Code_File *file, unsigned int number,unsigned int count, Elm_Code_Token_Type types[])
20{
21 Elm_Code_Line *line;
22 unsigned int found, i;
23
24 line = elm_code_file_line_get(file, number);
25 if (line->tokens)
26 found = eina_list_count(line->tokens);
27 else
28 found = 0;
29 ck_assert_msg(found == count, "Bad token count %d on line %d - expected %d", found, number, count);
30
31 for (i = 0; i < found; i++)
32 {
33 Elm_Code_Token *token;
34
35 token = eina_list_nth(line->tokens, i);
36 ck_assert_msg(token->type == types[i], "Token mismatch (%d!=%d) on line %d", token->type, types[i], number);
37 }
38}
39
40START_TEST (elm_code_syntax_lookup)
41{
42 Elm_Code_Syntax *syntax;
43
44 syntax = elm_code_syntax_for_mime_get("text/x-csrc");
45 ck_assert(!!syntax);
46 syntax = elm_code_syntax_for_mime_get("text/x-chdr");
47 ck_assert(!!syntax);
48 syntax = elm_code_syntax_for_mime_get("text/unknown");
49 ck_assert(!syntax);
50}
51END_TEST
52
53START_TEST (elm_code_syntax_c)
54{
55 Elm_Code *code;
56 Elm_Code_File *file;
57 Elm_Code_Widget *widget;
58 Evas_Object *win;
59
60 elm_init(1, NULL);
61 code = elm_code_create();
62 file = elm_code_file_new(code);
63
64 win = elm_win_add(NULL, "syntax", ELM_WIN_BASIC);
65 widget = elm_code_widget_add(win, code);
66 elm_obj_code_widget_code_get(widget)->file->mime = "text/x-csrc";
67 elm_code_widget_syntax_enabled_set(widget, EINA_TRUE);
68
69 _append_line(file, "#include <stdio.h>");
70 _append_line(file, "int main(int argc, char **argv)");
71 _append_line(file, "{");
72 _append_line(file, " // display a welcome greeting");
73 _append_line(file, " if (argc > 0)");
74 _append_line(file, " printf(\"Hello, %s!\\n\", argv[0]);");
75 _append_line(file, " else");
76 _append_line(file, " printf(\"Hello, World!\\n\");");
77 _append_line(file, " return 0;");
78 _append_line(file, "}");
79
80 _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,
82 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});
84 _assert_line_token_types(file, 3, 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});
86 _assert_line_token_types(file, 5, 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});
88 _assert_line_token_types(file, 6, 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,
90 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});
92 _assert_line_token_types(file, 8, 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});
94 _assert_line_token_types(file, 9, 3, (Elm_Code_Token_Type[3]){ELM_CODE_TOKEN_TYPE_KEYWORD,
95 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});
97
98 elm_code_free(code);
99 elm_shutdown();
100}
101END_TEST
102
103void elm_code_test_syntax(TCase *tc)
104{
105 tcase_add_test(tc, elm_code_syntax_lookup);
106 tcase_add_test(tc, elm_code_syntax_c);
107}
diff --git a/src/tests/elementary/elm_suite.c b/src/tests/elementary/elm_suite.c
index 146b261b82..ed06e0aead 100644
--- a/src/tests/elementary/elm_suite.c
+++ b/src/tests/elementary/elm_suite.c
@@ -75,6 +75,7 @@ static const Efl_Test_Case etc[] = {
75 { "elm_code_file_load", elm_code_file_test_load }, 75 { "elm_code_file_load", elm_code_file_test_load },
76 { "elm_code_file_memory", elm_code_file_test_memory }, 76 { "elm_code_file_memory", elm_code_file_test_memory },
77 { "elm_code_parse", elm_code_test_parse }, 77 { "elm_code_parse", elm_code_test_parse },
78 { "elm_code_syntax", elm_code_test_syntax },
78 { "elm_code_text", elm_code_test_text }, 79 { "elm_code_text", elm_code_test_text },
79 { "elm_code_indent", elm_code_test_indent }, 80 { "elm_code_indent", elm_code_test_indent },
80 { "elm_code_basic", elm_code_test_basic }, 81 { "elm_code_basic", elm_code_test_basic },
diff --git a/src/tests/elementary/elm_suite.h b/src/tests/elementary/elm_suite.h
index e161331c0c..cfa46d95eb 100644
--- a/src/tests/elementary/elm_suite.h
+++ b/src/tests/elementary/elm_suite.h
@@ -75,6 +75,7 @@ void elm_code_file_test_memory(TCase *tc);
75void elm_code_test_basic(TCase *tc); 75void elm_code_test_basic(TCase *tc);
76void elm_code_test_line(TCase *tc); 76void elm_code_test_line(TCase *tc);
77void elm_code_test_parse(TCase *tc); 77void elm_code_test_parse(TCase *tc);
78void elm_code_test_syntax(TCase *tc);
78void elm_code_test_text(TCase *tc); 79void elm_code_test_text(TCase *tc);
79void elm_code_test_indent(TCase *tc); 80void elm_code_test_indent(TCase *tc);
80void elm_code_test_widget(TCase *tc); 81void elm_code_test_widget(TCase *tc);