From 5851a9d4a82b1fb5638d46f510fe9e8b6c7bdbb4 Mon Sep 17 00:00:00 2001 From: Andy Williams Date: Fri, 20 Jan 2017 22:09:16 +0000 Subject: [PATCH] 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 --- src/Makefile_Elementary.am | 5 +- src/bin/elementary/test.c | 2 + src/bin/elementary/test_code.c | 48 +++++++ src/lib/elementary/elm_code.h | 1 + src/lib/elementary/elm_code_file.c | 1 + src/lib/elementary/elm_code_file.h | 1 + src/lib/elementary/elm_code_parse.c | 31 +++++ src/lib/elementary/elm_code_parse.h | 1 + src/lib/elementary/elm_code_private.h | 2 + src/lib/elementary/elm_code_syntax.c | 135 ++++++++++++++++++++ src/lib/elementary/elm_code_syntax.h | 65 ++++++++++ src/lib/elementary/elm_code_text.c | 12 +- src/lib/elementary/elm_code_widget.c | 24 ++++ src/lib/elementary/elm_code_widget.eo | 13 +- src/tests/elementary/elm_code_test_syntax.c | 107 ++++++++++++++++ src/tests/elementary/elm_suite.c | 1 + src/tests/elementary/elm_suite.h | 1 + 17 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 src/lib/elementary/elm_code_syntax.c create mode 100644 src/lib/elementary/elm_code_syntax.h create mode 100644 src/tests/elementary/elm_code_test_syntax.c 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 = \ lib/elementary/elm_code_text.h \ lib/elementary/elm_code_indent.h \ lib/elementary/elm_code_file.h \ - lib/elementary/elm_code_parse.h + lib/elementary/elm_code_parse.h \ + lib/elementary/elm_code_syntax.h includesunstabledir = $(includedir)/elementary-@VMAJ@ nodist_includesunstable_HEADERS = \ @@ -557,6 +558,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/elm_code_indent.c \ lib/elementary/elm_code_file.c \ lib/elementary/elm_code_parse.c \ + lib/elementary/elm_code_syntax.c \ lib/elementary/elm_code_widget_selection.c \ lib/elementary/elm_code_widget.c \ lib/elementary/elm_code_diff_widget.c \ @@ -1321,6 +1323,7 @@ tests_elementary_elm_suite_SOURCES = \ tests/elementary/elm_code_test_basic.c \ tests/elementary/elm_code_test_line.c \ tests/elementary/elm_code_test_parse.c \ + tests/elementary/elm_code_test_syntax.c \ tests/elementary/elm_code_test_text.c \ tests/elementary/elm_code_test_indent.c \ 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); void test_code_welcome(void *data, Evas_Object *obj, void *event_info); void test_code_editor(void *data, Evas_Object *obj, void *event_info); +void test_code_syntax(void *data, Evas_Object *obj, void *event_info); void test_code_mirror(void *data, Evas_Object *obj, void *event_info); void test_code_log(void *data, Evas_Object *obj, void *event_info); void test_code_diff(void *data, Evas_Object *obj, void *event_info); @@ -732,6 +733,7 @@ add_tests: //------------------------------// ADD_TEST(NULL, "Advanced Entries", "Code Entry Markup", test_code_welcome); ADD_TEST(NULL, "Advanced Entries", "Code Editor", test_code_editor); + ADD_TEST(NULL, "Advanced Entries", "Code Syntax", test_code_syntax); ADD_TEST(NULL, "Advanced Entries", "Mirrored Editor", test_code_mirror); ADD_TEST(NULL, "Advanced Entries", "Logger", test_code_log); 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 @@ -108,6 +108,39 @@ _elm_code_test_editor_setup(Evas_Object *parent, Eina_Bool log) return widget; } +static Evas_Object * +_elm_code_test_syntax_setup(Evas_Object *parent) +{ + Elm_Code *code; + Elm_Code_Widget *widget; + + code = elm_code_create(); + widget = efl_add(ELM_CODE_WIDGET_CLASS, parent, elm_obj_code_widget_code_set(efl_added, code)); + elm_obj_code_widget_font_set(widget, NULL, 14); + elm_obj_code_widget_editable_set(widget, EINA_TRUE); + elm_obj_code_widget_syntax_enabled_set(widget, EINA_TRUE); + elm_obj_code_widget_code_get(widget)->file->mime = "text/x-csrc"; + elm_obj_code_widget_show_whitespace_set(widget, EINA_TRUE); + elm_obj_code_widget_line_numbers_set(widget, EINA_TRUE); + + _append_line(code->file, "#include "); + _append_line(code->file, "int main(int argc, char **argv)"); + _append_line(code->file, "{"); + _append_line(code->file, " // display a welcome greeting"); + _append_line(code->file, " if (argc > 0)"); + _append_line(code->file, " printf(\"Hello, %s!\\n\", argv[0]);"); + _append_line(code->file, " else"); + _append_line(code->file, " printf(\"Hello, World!\\n\");"); + _append_line(code->file, " return 0;"); + _append_line(code->file, "}"); + + evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(widget); + + return widget; +} + static Evas_Object * _elm_code_test_mirror_setup(Elm_Code *code, char *font_name, Evas_Object *parent) { @@ -201,6 +234,21 @@ test_code_editor(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve evas_object_show(win); } +void +test_code_syntax(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Evas_Object *win, *screen; + + win = _test_code_win_create("code-syntax", "Code Syntax"); + screen = elm_box_add(win); + evas_object_size_hint_weight_set(screen, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_pack_end(screen, _elm_code_test_syntax_setup(screen)); + elm_win_resize_object_add(win, screen); + evas_object_show(screen); + + evas_object_show(win); +} + void test_code_log(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { 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 @@ #include "elm_code_indent.h" #include "elm_code_file.h" #include "elm_code_parse.h" +#include "elm_code_syntax.h" #include "elm_code_widget.eo.h" #include "elm_code_widget_legacy.h" #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) ret = elm_code_file_new(code); file = eina_file_open(path, EINA_FALSE); ret->file = file; + ret->mime = efreet_mime_type_get(path); lastindex = 1; 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 Eina_List *lines; Eina_File *file; void *map; + const char *mime; Elm_Code_File_Line_Ending line_ending; }; 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 @@ #include "elm_code_private.h" +EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_SYNTAX = NULL; EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF = NULL; EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO = NULL; @@ -126,6 +127,34 @@ _elm_code_parser_diff_trim_leading(Elm_Code_Line *line, unsigned int count) line->length -= count; } +#define _PARSE_C_SYMBOLS "{}()[]:;*&|!=<->,." +#define _PARSE_C_KEYWORDS {"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} + +static void +_elm_code_parser_syntax_parse_line(Elm_Code_Line *line, void *data EINA_UNUSED) +{ + Elm_Code_Syntax *syntax; + + syntax = elm_code_syntax_for_mime_get(line->file->mime); + if (syntax) + elm_code_syntax_parse_line(syntax, line); +} + +static void +_elm_code_parser_syntax_parse_file(Elm_Code_File *file, void *data EINA_UNUSED) +{ + Elm_Code_Syntax *syntax; + INF("Parse syntax of file with mime \"%s\"", file->mime); + + syntax = elm_code_syntax_for_mime_get(file->mime); + if (!syntax) + WRN("Unsupported mime in parser"); + else + elm_code_syntax_parse_file(syntax, file); +} + static void _elm_code_parser_diff_parse_line(Elm_Code_Line *line, void *data EINA_UNUSED) { @@ -200,6 +229,8 @@ _elm_code_parser_free(Elm_Code_Parser *parser) void _elm_code_parse_setup() { + ELM_CODE_PARSER_STANDARD_SYNTAX = _elm_code_parser_new(_elm_code_parser_syntax_parse_line, + _elm_code_parser_syntax_parse_file); ELM_CODE_PARSER_STANDARD_DIFF = _elm_code_parser_new(_elm_code_parser_diff_parse_line, _elm_code_parser_diff_parse_file); 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" { typedef struct _Elm_Code_Parser Elm_Code_Parser; +extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_SYNTAX; /**< A provided parser to provide syntax highlighting */ extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_DIFF; /**< A provided parser that will mark up diff text */ extern EAPI Elm_Code_Parser *ELM_CODE_PARSER_STANDARD_TODO; /**< A provided parser that will highlight TODO and FIXME lines */ 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 @@ #ifndef ELM_CODE_PRIVATE_H # define ELM_CODE_PRIVATE_H +#include "elm_priv.h" + Eina_Bool _elm_code_text_char_is_whitespace(char c); /* 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 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include +#include "Elementary.h" + +#include "elm_code_private.h" + +typedef struct _Elm_Code_Syntax +{ + const char *symbols; + const char *keywords[]; +} Elm_Code_Syntax; + +static Elm_Code_Syntax _elm_code_syntax_c = +{ + "{}()[]:;*&|!=<->,.", + {"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} +}; + +EAPI Elm_Code_Syntax * +elm_code_syntax_for_mime_get(const char *mime) +{ + if (!strcmp("text/x-chdr", mime) || !strcmp("text/x-csrc", mime)) + return &_elm_code_syntax_c; + + return NULL; +} + +static void +_elm_code_syntax_parse_token(Elm_Code_Syntax *syntax, Elm_Code_Line *line, unsigned int pos, const char *token, unsigned int length) +{ + const char **keyword; + unsigned int i; + + for (keyword = syntax->keywords; *keyword; keyword++) + if (strlen(*keyword) == length && !strncmp(token, *keyword, length)) + { + elm_code_line_token_add(line, pos, pos + length - 1, 1, ELM_CODE_TOKEN_TYPE_KEYWORD); + return; + } + + for (i = 0; i < length; i++) + { + if (!isdigit(token[i])) + break; + if (i == length - 1) + elm_code_line_token_add(line, pos, pos + length - 1, 1, ELM_CODE_TOKEN_TYPE_NUMBER); + } +} + +EAPI void +elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line) +{ + unsigned int i, count, length; + const char *content; + const char *sym, *ptr; + + EINA_SAFETY_ON_NULL_RETURN(syntax); + + content = elm_code_line_text_get(line, &length); + ptr = content; + count = 0; + for (i = 0; i < length; i++) + { + if (_elm_code_text_char_is_whitespace(content[i])) + { + if (count) + _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count); + + ptr += count+1; + count = 0; + continue; + } + + if (content[i] == '#') + { + elm_code_line_token_add(line, i, length - 1, 1, ELM_CODE_TOKEN_TYPE_PREPROCESSOR); + return; + } + else if (count == 1 && content[i-1] == '/' && content[i] == '/') + { + elm_code_line_token_add(line, i - 1, length - 1, 1, ELM_CODE_TOKEN_TYPE_COMMENT); + return; + } + else if (content[i] == '"') + { + unsigned int start = i, end; + + for (i++; content[i] != '"' && i < length; i++) {} + end = i; + + elm_code_line_token_add(line, start, end, 1, ELM_CODE_TOKEN_TYPE_STRING); + continue; + } + else if (content[i] == '\'') + { + unsigned int start = i, end; + + for (i++; content[i] != '\'' && i < length; i++) {} + end = i; + + elm_code_line_token_add(line, start, end, 1, ELM_CODE_TOKEN_TYPE_STRING); + continue; + } + + for (sym = syntax->symbols; *sym; sym++) + if (content[i] == *sym) + { + if (count) + _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count); + + elm_code_line_token_add(line, i, i, 1, ELM_CODE_TOKEN_TYPE_BRACE); + + ptr = content + i+1; + count = -1; + break; + } + + count++; + } + + if (count) + _elm_code_syntax_parse_token(syntax, line, ptr-content, ptr, count); +} + +EAPI void +elm_code_syntax_parse_file(Elm_Code_Syntax *syntax, Elm_Code_File *file EINA_UNUSED) +{ + EINA_SAFETY_ON_NULL_RETURN(syntax); +} + 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 @@ +#ifndef ELM_CODE_SYNTAX_H_ +# define ELM_CODE_SYNTAX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * @brief These routines are used for handling the parsing of Elm Code content. + */ + +typedef struct _Elm_Code_Syntax Elm_Code_Syntax; + +/** + * @brief Syntax highlighting helper functions. + * @defgroup Syntax Parsing and marking up syntax in files + * + * @{ + * + * Syntax functions for adding syntax highlighting to elm code. + * + */ + +/** + * Lookup a syntax definition from a mime type. + * If there is no syntax known NULL will be returned. + * + * @param mime The mime type to be looked up for a matching syntax definition + * @return A syntax definition, if one is found, or NULL + * + * @ingroup Syntax + */ +EAPI Elm_Code_Syntax *elm_code_syntax_for_mime_get(const char *mime); + +/** + * Parse a line and apply the syntax definition by inserting Elm_Code_Token into the line. + * + * @param syntax The syntax definition to use (from elm_code_syntax_for_mime_get) + * @param line The line that contains the content to parse and will receive the tokens + * + * @ingroup Syntax + */ +EAPI void elm_code_syntax_parse_line(Elm_Code_Syntax *syntax, Elm_Code_Line *line); + +/** + * Parse a file and apply the syntax definition one line at a time. + * + * @param syntax The syntax definition to use (from elm_code_syntax_for_mime_get) + * @param file The file to parse - each line in the file will be processed + * + * @ingroup Syntax + */ +EAPI void elm_code_syntax_parse_file(Elm_Code_Syntax *syntax, Elm_Code_File *file); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#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 line->length += length; file = line->file; - elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); + if (file->parent) + { + _elm_code_parse_line(file->parent, line); + elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); + } } EAPI void @@ -207,7 +211,11 @@ elm_code_line_text_remove(Elm_Code_Line *line, unsigned int position, int length line->length -= length; file = line->file; - elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); + if (file->parent) + { + _elm_code_parse_line(file->parent, line); + elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); + } } Eina_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 @@ -2075,6 +2075,30 @@ _elm_code_widget_show_whitespace_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data * return pd->show_whitespace; } +EOLIAN static void +_elm_code_widget_syntax_enabled_set(Eo *obj, Elm_Code_Widget_Data *pd EINA_UNUSED, + Eina_Bool enabled) +{ + Elm_Code_Widget *widget = obj; + Elm_Code *code; + + code = elm_code_widget_code_get(widget); + if (enabled) + elm_code_parser_standard_add(code, ELM_CODE_PARSER_STANDARD_SYNTAX); + else + code->parsers = eina_list_remove(code->parsers, ELM_CODE_PARSER_STANDARD_SYNTAX); +} + +EOLIAN static Eina_Bool +_elm_code_widget_syntax_enabled_get(Eo *obj, Elm_Code_Widget_Data *pd EINA_UNUSED) +{ + Elm_Code_Widget *widget = obj; + Elm_Code *code; + + code = elm_code_widget_code_get(widget); + return !!eina_list_data_find(code->parsers, ELM_CODE_PARSER_STANDARD_SYNTAX); +} + EOLIAN static void _elm_code_widget_tab_inserts_spaces_set(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd, Eina_Bool spaces) 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) } @property show_whitespace { set { - [[Set where white space should be shown.]] + [[Set whether white space should be shown.]] } get { [[Get whether or not white space will be visible.]] @@ -149,6 +149,17 @@ class Elm.Code_Widget (Elm.Layout, Elm.Interface.Atspi.Text) show_whitespace: bool; [[Whether or not we show whitespace characters]] } } + @property syntax_enabled { + set { + [[Set whether syntax highlighting should be use for this widget.]] + } + get { + [[Get this widget's enabled state for syntax highlighting.]] + } + values { + syntax_enabled: bool; [[Whether or not to enable syntax highlighting]] + } + } @property tab_inserts_spaces { set { [[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 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include "elm_suite.h" +#include "Elementary.h" +#include "elm_code_syntax.h" + +static void +_append_line(Elm_Code_File *file, const char *line) +{ + int length; + + length = strlen(line); + elm_code_file_line_append(file, line, length, NULL); +} + +static void +_assert_line_token_types(Elm_Code_File *file, unsigned int number,unsigned int count, Elm_Code_Token_Type types[]) +{ + Elm_Code_Line *line; + unsigned int found, i; + + line = elm_code_file_line_get(file, number); + if (line->tokens) + found = eina_list_count(line->tokens); + else + found = 0; + ck_assert_msg(found == count, "Bad token count %d on line %d - expected %d", found, number, count); + + for (i = 0; i < found; i++) + { + Elm_Code_Token *token; + + token = eina_list_nth(line->tokens, i); + ck_assert_msg(token->type == types[i], "Token mismatch (%d!=%d) on line %d", token->type, types[i], number); + } +} + +START_TEST (elm_code_syntax_lookup) +{ + Elm_Code_Syntax *syntax; + + syntax = elm_code_syntax_for_mime_get("text/x-csrc"); + ck_assert(!!syntax); + syntax = elm_code_syntax_for_mime_get("text/x-chdr"); + ck_assert(!!syntax); + syntax = elm_code_syntax_for_mime_get("text/unknown"); + ck_assert(!syntax); +} +END_TEST + +START_TEST (elm_code_syntax_c) +{ + Elm_Code *code; + Elm_Code_File *file; + Elm_Code_Widget *widget; + Evas_Object *win; + + elm_init(1, NULL); + code = elm_code_create(); + file = elm_code_file_new(code); + + win = elm_win_add(NULL, "syntax", ELM_WIN_BASIC); + widget = elm_code_widget_add(win, code); + elm_obj_code_widget_code_get(widget)->file->mime = "text/x-csrc"; + elm_code_widget_syntax_enabled_set(widget, EINA_TRUE); + + _append_line(file, "#include "); + _append_line(file, "int main(int argc, char **argv)"); + _append_line(file, "{"); + _append_line(file, " // display a welcome greeting"); + _append_line(file, " if (argc > 0)"); + _append_line(file, " printf(\"Hello, %s!\\n\", argv[0]);"); + _append_line(file, " else"); + _append_line(file, " printf(\"Hello, World!\\n\");"); + _append_line(file, " return 0;"); + _append_line(file, "}"); + + _assert_line_token_types(file, 1, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_PREPROCESSOR}); + _assert_line_token_types(file, 2, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, + ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, + ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 3, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 4, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_COMMENT}); + _assert_line_token_types(file, 5, 5, (Elm_Code_Token_Type[5]){ELM_CODE_TOKEN_TYPE_KEYWORD, ELM_CODE_TOKEN_TYPE_BRACE, + ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 6, 8, (Elm_Code_Token_Type[8]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING, + ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE, + ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 7, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_KEYWORD}); + _assert_line_token_types(file, 8, 4, (Elm_Code_Token_Type[4]){ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_STRING, + ELM_CODE_TOKEN_TYPE_BRACE, ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 9, 3, (Elm_Code_Token_Type[3]){ELM_CODE_TOKEN_TYPE_KEYWORD, + ELM_CODE_TOKEN_TYPE_NUMBER, ELM_CODE_TOKEN_TYPE_BRACE}); + _assert_line_token_types(file, 10, 1, (Elm_Code_Token_Type[1]){ELM_CODE_TOKEN_TYPE_BRACE}); + + 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); +} 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[] = { { "elm_code_file_load", elm_code_file_test_load }, { "elm_code_file_memory", elm_code_file_test_memory }, { "elm_code_parse", elm_code_test_parse }, + { "elm_code_syntax", elm_code_test_syntax }, { "elm_code_text", elm_code_test_text }, { "elm_code_indent", elm_code_test_indent }, { "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); void elm_code_test_basic(TCase *tc); void elm_code_test_line(TCase *tc); void elm_code_test_parse(TCase *tc); +void elm_code_test_syntax(TCase *tc); void elm_code_test_text(TCase *tc); void elm_code_test_indent(TCase *tc); void elm_code_test_widget(TCase *tc);