mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-18 07:17:18 +01:00
Ported: Extract Syntax highlighting from TextEdit and add EditorSyntaxHighlighter
- Extacted all syntax highlighting code from text edit
- Removed enable syntax highlighting from text edit
- Added line_edited_from signal to text_edit
- Renamed get/set_syntax_highlighting to get/set_syntax_highlighter
- Added EditorSyntaxHighligher
- Paulb23
bc4cee4458
This commit is contained in:
parent
0edf8fe956
commit
c356806ebf
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include "script_language.h"
|
#include "script_language.h"
|
||||||
|
|
||||||
#include "core/core_string_names.h"
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/core_string_names.h"
|
||||||
|
|
||||||
ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES];
|
ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES];
|
||||||
int ScriptServer::_language_count = 0;
|
int ScriptServer::_language_count = 0;
|
||||||
@ -355,6 +355,56 @@ ScriptCodeCompletionCache::ScriptCodeCompletionCache() {
|
|||||||
singleton = this;
|
singleton = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptLanguage::get_core_type_words(List<String> *p_words) const {
|
||||||
|
static const char *_core_type_words[] = {
|
||||||
|
"bool",
|
||||||
|
"int",
|
||||||
|
"float",
|
||||||
|
"String",
|
||||||
|
"Rect2",
|
||||||
|
"Rect2i",
|
||||||
|
"Vector2",
|
||||||
|
"Vector2i",
|
||||||
|
"Vector3",
|
||||||
|
"Vector3i",
|
||||||
|
"Vector4",
|
||||||
|
"Vector4i",
|
||||||
|
"Plane",
|
||||||
|
"Quaternion",
|
||||||
|
"AABB",
|
||||||
|
"Basis",
|
||||||
|
"Transform",
|
||||||
|
"Transform2D",
|
||||||
|
"Projection",
|
||||||
|
"Color",
|
||||||
|
"NodePath",
|
||||||
|
"RID",
|
||||||
|
"Object",
|
||||||
|
"StringName",
|
||||||
|
"Dictionary",
|
||||||
|
"Array",
|
||||||
|
"PoolByteArray",
|
||||||
|
"PoolIntArray",
|
||||||
|
"PoolRealArray",
|
||||||
|
"PoolStringArray",
|
||||||
|
"PoolVector2Array",
|
||||||
|
"PoolVector2iArray",
|
||||||
|
"PoolVector3Array",
|
||||||
|
"PoolVector3iArray",
|
||||||
|
"PoolVector4Array",
|
||||||
|
"PoolVector4iArray",
|
||||||
|
"PoolColorArray",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const char **w = _core_type_words;
|
||||||
|
|
||||||
|
while (*w) {
|
||||||
|
p_words->push_back(*w);
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptLanguage::frame() {
|
void ScriptLanguage::frame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +213,11 @@ struct ScriptCodeCompletionOption {
|
|||||||
KIND_FILE_PATH,
|
KIND_FILE_PATH,
|
||||||
KIND_PLAIN_TEXT,
|
KIND_PLAIN_TEXT,
|
||||||
};
|
};
|
||||||
|
|
||||||
Kind kind;
|
Kind kind;
|
||||||
String display;
|
String display;
|
||||||
String insert_text;
|
String insert_text;
|
||||||
|
Color font_color;
|
||||||
RES icon;
|
RES icon;
|
||||||
Variant default_value;
|
Variant default_value;
|
||||||
|
|
||||||
@ -263,6 +265,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
virtual void get_reserved_words(List<String> *p_words) const = 0;
|
virtual void get_reserved_words(List<String> *p_words) const = 0;
|
||||||
|
virtual void get_core_type_words(List<String> *p_words) const;
|
||||||
virtual bool is_control_flow_keyword(String p_string) const = 0;
|
virtual bool is_control_flow_keyword(String p_string) const = 0;
|
||||||
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
|
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
|
||||||
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
|
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
|
||||||
|
@ -434,7 +434,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||||||
_load_default_text_editor_theme();
|
_load_default_text_editor_theme();
|
||||||
|
|
||||||
// Highlighting
|
// Highlighting
|
||||||
_initial_set("text_editor/highlighting/syntax_highlighting", true);
|
|
||||||
_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
|
_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
|
||||||
_initial_set("text_editor/highlighting/highlight_current_line", true);
|
_initial_set("text_editor/highlighting/highlight_current_line", true);
|
||||||
_initial_set("text_editor/highlighting/highlight_type_safe_lines", true);
|
_initial_set("text_editor/highlighting/highlight_type_safe_lines", true);
|
||||||
|
@ -15,6 +15,7 @@ sources = [
|
|||||||
"editor_goto_line_dialog.cpp",
|
"editor_goto_line_dialog.cpp",
|
||||||
"editor_find_replace_bar.cpp",
|
"editor_find_replace_bar.cpp",
|
||||||
"editor_script_editor_quick_open.cpp",
|
"editor_script_editor_quick_open.cpp",
|
||||||
|
"editor_syntax_highlighter.cpp",
|
||||||
|
|
||||||
"script_editor_plugin.cpp",
|
"script_editor_plugin.cpp",
|
||||||
"editor_script_editor.cpp",
|
"editor_script_editor.cpp",
|
||||||
|
@ -218,8 +218,16 @@ void EditorCodeTextEditor::_complete_request() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
|
for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
|
||||||
E->get().icon = _get_completion_icon(E->get());
|
ScriptCodeCompletionOption *e = &E->get();
|
||||||
|
e->icon = _get_completion_icon(*e);
|
||||||
|
e->font_color = completion_font_color;
|
||||||
|
if (e->insert_text.begins_with("\"") || e->insert_text.begins_with("\'")) {
|
||||||
|
e->font_color = completion_string_color;
|
||||||
|
} else if (e->insert_text.begins_with("#") || e->insert_text.begins_with("//")) {
|
||||||
|
e->font_color = completion_comment_color;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
text_editor->code_complete(entries, forced);
|
text_editor->code_complete(entries, forced);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +299,10 @@ bool EditorCodeTextEditor::_add_font_size(int p_delta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorCodeTextEditor::update_editor_settings() {
|
void EditorCodeTextEditor::update_editor_settings() {
|
||||||
text_editor->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
|
completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
|
||||||
|
completion_string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
||||||
|
completion_comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
||||||
|
|
||||||
text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
|
text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
|
||||||
text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
|
text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
|
||||||
text_editor->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
|
text_editor->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
|
||||||
@ -797,11 +808,8 @@ Variant EditorCodeTextEditor::get_edit_state() {
|
|||||||
state["breakpoints"] = text_editor->get_breakpoints_array();
|
state["breakpoints"] = text_editor->get_breakpoints_array();
|
||||||
state["bookmarks"] = text_editor->get_bookmarks_array();
|
state["bookmarks"] = text_editor->get_bookmarks_array();
|
||||||
|
|
||||||
state["syntax_highlighter"] = TTR("Standard");
|
Ref<EditorSyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighter();
|
||||||
Ref<SyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighting();
|
|
||||||
if (syntax_highlighter.is_valid()) {
|
|
||||||
state["syntax_highlighter"] = syntax_highlighter->_get_name();
|
state["syntax_highlighter"] = syntax_highlighter->_get_name();
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "scene/gui/dialogs.h"
|
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
|
#include "scene/gui/dialogs.h"
|
||||||
|
|
||||||
#include "core/containers/list.h"
|
#include "core/containers/list.h"
|
||||||
#include "core/math/math_defs.h"
|
#include "core/math/math_defs.h"
|
||||||
@ -97,6 +97,9 @@ class EditorCodeTextEditor : public VBoxContainer {
|
|||||||
void _zoom_changed();
|
void _zoom_changed();
|
||||||
void _reset_zoom();
|
void _reset_zoom();
|
||||||
|
|
||||||
|
Color completion_font_color;
|
||||||
|
Color completion_string_color;
|
||||||
|
Color completion_comment_color;
|
||||||
EditorCodeTextEditorCodeCompleteFunc code_complete_func;
|
EditorCodeTextEditorCodeCompleteFunc code_complete_func;
|
||||||
void *code_complete_ud;
|
void *code_complete_ud;
|
||||||
|
|
||||||
|
@ -2090,8 +2090,8 @@ bool EditorScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool
|
|||||||
|
|
||||||
if (p_resource->get_class_name() != StringName("VisualScript")) {
|
if (p_resource->get_class_name() != StringName("VisualScript")) {
|
||||||
bool highlighter_set = false;
|
bool highlighter_set = false;
|
||||||
for (int i = 0; i < syntax_highlighters_func_count; i++) {
|
for (int i = 0; i < syntax_highlighters.size(); i++) {
|
||||||
SyntaxHighlighter *highlighter = syntax_highlighters_funcs[i]();
|
Ref<EditorSyntaxHighlighter> highlighter = syntax_highlighters[i]->_create();
|
||||||
se->add_syntax_highlighter(highlighter);
|
se->add_syntax_highlighter(highlighter);
|
||||||
|
|
||||||
if (script != nullptr && !highlighter_set) {
|
if (script != nullptr && !highlighter_set) {
|
||||||
@ -2999,12 +2999,18 @@ void EditorScriptEditor::_open_script_request(const String &p_path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EditorScriptEditor::syntax_highlighters_func_count = 0;
|
void EditorScriptEditor::register_syntax_highlighter(const Ref<EditorSyntaxHighlighter> &p_syntax_highlighter) {
|
||||||
CreateSyntaxHighlighterFunc EditorScriptEditor::syntax_highlighters_funcs[EditorScriptEditor::SYNTAX_HIGHLIGHTER_FUNC_MAX];
|
ERR_FAIL_COND(p_syntax_highlighter.is_null());
|
||||||
|
|
||||||
void EditorScriptEditor::register_create_syntax_highlighter_function(CreateSyntaxHighlighterFunc p_func) {
|
if (syntax_highlighters.find(p_syntax_highlighter) == -1) {
|
||||||
ERR_FAIL_COND(syntax_highlighters_func_count == SYNTAX_HIGHLIGHTER_FUNC_MAX);
|
syntax_highlighters.push_back(p_syntax_highlighter);
|
||||||
syntax_highlighters_funcs[syntax_highlighters_func_count++] = p_func;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScriptEditor::unregister_syntax_highlighter(const Ref<EditorSyntaxHighlighter> &p_syntax_highlighter) {
|
||||||
|
ERR_FAIL_COND(p_syntax_highlighter.is_null());
|
||||||
|
|
||||||
|
syntax_highlighters.erase(p_syntax_highlighter);
|
||||||
}
|
}
|
||||||
|
|
||||||
int EditorScriptEditor::script_editor_func_count = 0;
|
int EditorScriptEditor::script_editor_func_count = 0;
|
||||||
|
@ -38,21 +38,22 @@
|
|||||||
|
|
||||||
#include "scene/resources/text_file.h"
|
#include "scene/resources/text_file.h"
|
||||||
|
|
||||||
#include "core/object/script_language.h"
|
|
||||||
#include "core/variant/array.h"
|
|
||||||
#include "core/error/error_list.h"
|
|
||||||
#include "core/containers/list.h"
|
#include "core/containers/list.h"
|
||||||
|
#include "core/containers/rb_set.h"
|
||||||
|
#include "core/containers/vector.h"
|
||||||
|
#include "core/error/error_list.h"
|
||||||
#include "core/math/vector2.h"
|
#include "core/math/vector2.h"
|
||||||
#include "core/object/object.h"
|
#include "core/object/object.h"
|
||||||
#include "core/object/reference.h"
|
#include "core/object/reference.h"
|
||||||
#include "core/object/resource.h"
|
#include "core/object/resource.h"
|
||||||
#include "core/containers/rb_set.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/typedefs.h"
|
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
|
#include "core/typedefs.h"
|
||||||
|
#include "core/variant/array.h"
|
||||||
#include "core/variant/variant.h"
|
#include "core/variant/variant.h"
|
||||||
#include "core/containers/vector.h"
|
|
||||||
|
|
||||||
#include "editor_script_editor_base.h"
|
#include "editor_script_editor_base.h"
|
||||||
|
#include "editor_syntax_highlighter.h"
|
||||||
|
|
||||||
class Button;
|
class Button;
|
||||||
class ConfigFile;
|
class ConfigFile;
|
||||||
@ -81,7 +82,6 @@ class VSplitContainer;
|
|||||||
class EditorScriptEditorQuickOpen;
|
class EditorScriptEditorQuickOpen;
|
||||||
class EditorScriptEditorDebugger;
|
class EditorScriptEditorDebugger;
|
||||||
|
|
||||||
typedef SyntaxHighlighter *(*CreateSyntaxHighlighterFunc)();
|
|
||||||
typedef EditorScriptEditorBase *(*CreateEditorScriptEditorFunc)(const RES &p_resource);
|
typedef EditorScriptEditorBase *(*CreateEditorScriptEditorFunc)(const RES &p_resource);
|
||||||
|
|
||||||
class EditorScriptCodeCompletionCache;
|
class EditorScriptCodeCompletionCache;
|
||||||
@ -208,8 +208,7 @@ class EditorScriptEditor : public PanelContainer {
|
|||||||
static int script_editor_func_count;
|
static int script_editor_func_count;
|
||||||
static CreateEditorScriptEditorFunc script_editor_funcs[SCRIPT_EDITOR_FUNC_MAX];
|
static CreateEditorScriptEditorFunc script_editor_funcs[SCRIPT_EDITOR_FUNC_MAX];
|
||||||
|
|
||||||
static int syntax_highlighters_func_count;
|
Vector<Ref<EditorSyntaxHighlighter>> syntax_highlighters;
|
||||||
static CreateSyntaxHighlighterFunc syntax_highlighters_funcs[SYNTAX_HIGHLIGHTER_FUNC_MAX];
|
|
||||||
|
|
||||||
struct ScriptHistory {
|
struct ScriptHistory {
|
||||||
Control *control;
|
Control *control;
|
||||||
@ -417,7 +416,9 @@ public:
|
|||||||
EditorScriptEditorDebugger *get_debugger() { return debugger; }
|
EditorScriptEditorDebugger *get_debugger() { return debugger; }
|
||||||
void set_live_auto_reload_running_scripts(bool p_enabled);
|
void set_live_auto_reload_running_scripts(bool p_enabled);
|
||||||
|
|
||||||
static void register_create_syntax_highlighter_function(CreateSyntaxHighlighterFunc p_func);
|
void register_syntax_highlighter(const Ref<EditorSyntaxHighlighter> &p_syntax_highlighter);
|
||||||
|
void unregister_syntax_highlighter(const Ref<EditorSyntaxHighlighter> &p_syntax_highlighter);
|
||||||
|
|
||||||
static void register_create_script_editor_function(CreateEditorScriptEditorFunc p_func);
|
static void register_create_script_editor_function(CreateEditorScriptEditorFunc p_func);
|
||||||
|
|
||||||
EditorScriptEditor(EditorNode *p_editor);
|
EditorScriptEditor(EditorNode *p_editor);
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include "editor_script_editor_base.h"
|
#include "editor_script_editor_base.h"
|
||||||
|
|
||||||
|
#include "editor_syntax_highlighter.h"
|
||||||
|
|
||||||
void EditorScriptEditorBase::_bind_methods() {
|
void EditorScriptEditorBase::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("name_changed"));
|
ADD_SIGNAL(MethodInfo("name_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("edited_script_changed"));
|
ADD_SIGNAL(MethodInfo("edited_script_changed"));
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
|
|
||||||
class SyntaxHighlighter;
|
class EditorSyntaxHighlighter;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
class EditorScriptEditorBase : public VBoxContainer {
|
class EditorScriptEditorBase : public VBoxContainer {
|
||||||
@ -43,8 +43,8 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void add_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) = 0;
|
virtual void add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) = 0;
|
||||||
virtual void set_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) = 0;
|
virtual void set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) = 0;
|
||||||
|
|
||||||
virtual void apply_code() = 0;
|
virtual void apply_code() = 0;
|
||||||
virtual RES get_edited_resource() const = 0;
|
virtual RES get_edited_resource() const = 0;
|
||||||
|
@ -76,6 +76,8 @@
|
|||||||
#include "editor_goto_line_dialog.h"
|
#include "editor_goto_line_dialog.h"
|
||||||
#include "editor_script_editor.h"
|
#include "editor_script_editor.h"
|
||||||
|
|
||||||
|
#include "editor_syntax_highlighter.h"
|
||||||
|
|
||||||
Vector<String> EditorScriptTextEditor::get_functions() {
|
Vector<String> EditorScriptTextEditor::get_functions() {
|
||||||
String errortxt;
|
String errortxt;
|
||||||
int line = -1, col;
|
int line = -1, col;
|
||||||
@ -100,7 +102,7 @@ void EditorScriptTextEditor::apply_code() {
|
|||||||
}
|
}
|
||||||
script->set_source_code(code_editor->get_text_edit()->get_text());
|
script->set_source_code(code_editor->get_text_edit()->get_text());
|
||||||
script->update_exports();
|
script->update_exports();
|
||||||
_update_member_keywords();
|
code_editor->get_text_edit()->get_syntax_highlighter()->update_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
RES EditorScriptTextEditor::get_edited_resource() const {
|
RES EditorScriptTextEditor::get_edited_resource() const {
|
||||||
@ -134,43 +136,10 @@ void EditorScriptTextEditor::enable_editor() {
|
|||||||
_validate_script();
|
_validate_script();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScriptTextEditor::_update_member_keywords() {
|
|
||||||
member_keywords.clear();
|
|
||||||
code_editor->get_text_edit()->clear_member_keywords();
|
|
||||||
Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
|
||||||
|
|
||||||
StringName instance_base = script->get_instance_base_type();
|
|
||||||
|
|
||||||
if (instance_base == StringName()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<PropertyInfo> plist;
|
|
||||||
ClassDB::get_property_list(instance_base, &plist);
|
|
||||||
|
|
||||||
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
|
|
||||||
String name = E->get().name;
|
|
||||||
if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (name.find("/") != -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
code_editor->get_text_edit()->add_member_keyword(name, member_variable_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> clist;
|
|
||||||
ClassDB::get_integer_constant_list(instance_base, &clist);
|
|
||||||
|
|
||||||
for (List<String>::Element *E = clist.front(); E; E = E->next()) {
|
|
||||||
code_editor->get_text_edit()->add_member_keyword(E->get(), member_variable_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorScriptTextEditor::_load_theme_settings() {
|
void EditorScriptTextEditor::_load_theme_settings() {
|
||||||
TextEdit *text_edit = code_editor->get_text_edit();
|
TextEdit *text_edit = code_editor->get_text_edit();
|
||||||
|
|
||||||
text_edit->clear_colors();
|
text_edit->clear_keywords();
|
||||||
|
|
||||||
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
||||||
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
||||||
@ -189,9 +158,6 @@ void EditorScriptTextEditor::_load_theme_settings() {
|
|||||||
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
||||||
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
||||||
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
||||||
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
|
|
||||||
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
|
|
||||||
Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
|
||||||
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
||||||
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
||||||
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
||||||
@ -199,14 +165,6 @@ void EditorScriptTextEditor::_load_theme_settings() {
|
|||||||
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
||||||
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
||||||
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
||||||
Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
|
||||||
Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
|
||||||
Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
|
|
||||||
Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
|
||||||
Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
|
|
||||||
Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
|
||||||
Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
|
||||||
Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
|
||||||
|
|
||||||
text_edit->add_theme_color_override("background_color", background_color);
|
text_edit->add_theme_color_override("background_color", background_color);
|
||||||
text_edit->add_theme_color_override("completion_background_color", completion_background_color);
|
text_edit->add_theme_color_override("completion_background_color", completion_background_color);
|
||||||
@ -225,9 +183,6 @@ void EditorScriptTextEditor::_load_theme_settings() {
|
|||||||
text_edit->add_theme_color_override("current_line_color", current_line_color);
|
text_edit->add_theme_color_override("current_line_color", current_line_color);
|
||||||
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
||||||
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
||||||
text_edit->add_theme_color_override("number_color", number_color);
|
|
||||||
text_edit->add_theme_color_override("function_color", function_color);
|
|
||||||
text_edit->add_theme_color_override("member_variable_color", member_variable_color);
|
|
||||||
text_edit->add_theme_color_override("bookmark_color", bookmark_color);
|
text_edit->add_theme_color_override("bookmark_color", bookmark_color);
|
||||||
text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
|
text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
|
||||||
text_edit->add_theme_color_override("executing_line_color", executing_line_color);
|
text_edit->add_theme_color_override("executing_line_color", executing_line_color);
|
||||||
@ -235,19 +190,9 @@ void EditorScriptTextEditor::_load_theme_settings() {
|
|||||||
text_edit->add_theme_color_override("code_folding_color", code_folding_color);
|
text_edit->add_theme_color_override("code_folding_color", code_folding_color);
|
||||||
text_edit->add_theme_color_override("search_result_color", search_result_color);
|
text_edit->add_theme_color_override("search_result_color", search_result_color);
|
||||||
text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
|
text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
|
||||||
text_edit->add_theme_color_override("symbol_color", symbol_color);
|
|
||||||
|
|
||||||
text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
|
text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
|
||||||
|
|
||||||
colors_cache.symbol_color = symbol_color;
|
|
||||||
colors_cache.keyword_color = keyword_color;
|
|
||||||
colors_cache.control_flow_keyword_color = control_flow_keyword_color;
|
|
||||||
colors_cache.basetype_color = basetype_color;
|
|
||||||
colors_cache.type_color = type_color;
|
|
||||||
colors_cache.usertype_color = usertype_color;
|
|
||||||
colors_cache.comment_color = comment_color;
|
|
||||||
colors_cache.string_color = string_color;
|
|
||||||
|
|
||||||
theme_loaded = true;
|
theme_loaded = true;
|
||||||
if (!script.is_null()) {
|
if (!script.is_null()) {
|
||||||
_set_theme_for_script();
|
_set_theme_for_script();
|
||||||
@ -260,46 +205,11 @@ void EditorScriptTextEditor::_set_theme_for_script() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextEdit *text_edit = code_editor->get_text_edit();
|
TextEdit *text_edit = code_editor->get_text_edit();
|
||||||
|
text_edit->get_syntax_highlighter()->update_cache();
|
||||||
|
|
||||||
List<String> keywords;
|
/* add keywords for auto completion */
|
||||||
script->get_language()->get_reserved_words(&keywords);
|
|
||||||
|
|
||||||
for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
|
// engine types
|
||||||
if (script->get_language()->is_control_flow_keyword(E->get())) {
|
|
||||||
// Use a different color for control flow keywords to make them easier to distinguish.
|
|
||||||
text_edit->add_keyword_color(E->get(), colors_cache.control_flow_keyword_color);
|
|
||||||
} else {
|
|
||||||
text_edit->add_keyword_color(E->get(), colors_cache.keyword_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//colorize core types
|
|
||||||
const Color basetype_color = colors_cache.basetype_color;
|
|
||||||
text_edit->add_keyword_color("String", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Vector2", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Rect2", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Transform2D", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Vector3", basetype_color);
|
|
||||||
text_edit->add_keyword_color("AABB", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Basis", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Plane", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Transform", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Quaternion", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Color", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Object", basetype_color);
|
|
||||||
text_edit->add_keyword_color("NodePath", basetype_color);
|
|
||||||
text_edit->add_keyword_color("RID", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Dictionary", basetype_color);
|
|
||||||
text_edit->add_keyword_color("Array", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolByteArray", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolIntArray", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolRealArray", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolStringArray", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolVector2Array", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolVector3Array", basetype_color);
|
|
||||||
text_edit->add_keyword_color("PoolColorArray", basetype_color);
|
|
||||||
|
|
||||||
//colorize engine types
|
|
||||||
List<StringName> types;
|
List<StringName> types;
|
||||||
ClassDB::get_class_list(&types);
|
ClassDB::get_class_list(&types);
|
||||||
|
|
||||||
@ -309,16 +219,15 @@ void EditorScriptTextEditor::_set_theme_for_script() {
|
|||||||
n = n.substr(1, n.length());
|
n = n.substr(1, n.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
text_edit->add_keyword_color(n, colors_cache.type_color);
|
text_edit->add_keyword(E->get());
|
||||||
}
|
}
|
||||||
_update_member_keywords();
|
|
||||||
|
|
||||||
//colorize user types
|
//colorize user types
|
||||||
List<StringName> global_classes;
|
List<StringName> global_classes;
|
||||||
ScriptServer::get_global_class_list(&global_classes);
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
|
||||||
for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
|
for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
|
||||||
text_edit->add_keyword_color(E->get(), colors_cache.usertype_color);
|
text_edit->add_keyword(E->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//colorize singleton autoloads (as types, just as engine singletons are)
|
//colorize singleton autoloads (as types, just as engine singletons are)
|
||||||
@ -331,31 +240,9 @@ void EditorScriptTextEditor::_set_theme_for_script() {
|
|||||||
}
|
}
|
||||||
String path = ProjectSettings::get_singleton()->get(s);
|
String path = ProjectSettings::get_singleton()->get(s);
|
||||||
if (path.begins_with("*")) {
|
if (path.begins_with("*")) {
|
||||||
text_edit->add_keyword_color(s.get_slice("/", 1), colors_cache.usertype_color);
|
text_edit->add_keyword(s.get_slice("/", 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//colorize comments
|
|
||||||
List<String> comments;
|
|
||||||
script->get_language()->get_comment_delimiters(&comments);
|
|
||||||
|
|
||||||
for (List<String>::Element *E = comments.front(); E; E = E->next()) {
|
|
||||||
String comment = E->get();
|
|
||||||
String beg = comment.get_slice(" ", 0);
|
|
||||||
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
|
|
||||||
|
|
||||||
text_edit->add_color_region(beg, end, colors_cache.comment_color, end == "");
|
|
||||||
}
|
|
||||||
|
|
||||||
//colorize strings
|
|
||||||
List<String> strings;
|
|
||||||
script->get_language()->get_string_delimiters(&strings);
|
|
||||||
for (List<String>::Element *E = strings.front(); E; E = E->next()) {
|
|
||||||
String string = E->get();
|
|
||||||
String beg = string.get_slice(" ", 0);
|
|
||||||
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
|
|
||||||
text_edit->add_color_region(beg, end, colors_cache.string_color, end == "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScriptTextEditor::_show_warnings_panel(bool p_show) {
|
void EditorScriptTextEditor::_show_warnings_panel(bool p_show) {
|
||||||
@ -543,7 +430,7 @@ void EditorScriptTextEditor::_validate_script() {
|
|||||||
if (!script->is_tool()) {
|
if (!script->is_tool()) {
|
||||||
script->set_source_code(text);
|
script->set_source_code(text);
|
||||||
script->update_exports();
|
script->update_exports();
|
||||||
_update_member_keywords();
|
te->get_syntax_highlighter()->update_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
functions.clear();
|
functions.clear();
|
||||||
@ -1346,23 +1233,20 @@ void EditorScriptTextEditor::_edit_option_toggle_inline_comment() {
|
|||||||
code_editor->toggle_inline_comment(delimiter);
|
code_editor->toggle_inline_comment(delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScriptTextEditor::add_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) {
|
void EditorScriptTextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
|
||||||
highlighters[p_highlighter->_get_name()] = p_highlighter;
|
highlighters[p_highlighter->_get_name()] = p_highlighter;
|
||||||
highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
|
highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScriptTextEditor::set_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) {
|
void EditorScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
|
||||||
TextEdit *te = code_editor->get_text_edit();
|
TextEdit *te = code_editor->get_text_edit();
|
||||||
te->set_syntax_highlighting(p_highlighter);
|
p_highlighter->_set_edited_resource(script);
|
||||||
if (p_highlighter.is_valid()) {
|
te->set_syntax_highlighter(p_highlighter);
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
|
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
|
||||||
} else {
|
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(TTR("Standard")), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScriptTextEditor::_change_syntax_highlighter(int p_idx) {
|
void EditorScriptTextEditor::_change_syntax_highlighter(int p_idx) {
|
||||||
RBMap<String, Ref<SyntaxHighlighter> >::Element *el = highlighters.front();
|
RBMap<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
|
||||||
while (el != nullptr) {
|
while (el != nullptr) {
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
|
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
|
||||||
el = el->next();
|
el = el->next();
|
||||||
@ -1903,10 +1787,17 @@ EditorScriptTextEditor::EditorScriptTextEditor() {
|
|||||||
convert_case = memnew(PopupMenu);
|
convert_case = memnew(PopupMenu);
|
||||||
convert_case->set_name("convert_case");
|
convert_case->set_name("convert_case");
|
||||||
|
|
||||||
highlighters[TTR("Standard")] = Ref<SyntaxHighlighter>();
|
|
||||||
highlighter_menu = memnew(PopupMenu);
|
highlighter_menu = memnew(PopupMenu);
|
||||||
highlighter_menu->set_name("highlighter_menu");
|
highlighter_menu->set_name("highlighter_menu");
|
||||||
highlighter_menu->add_radio_check_item(TTR("Standard"));
|
|
||||||
|
Ref<EditorPlainTextSyntaxHighlighter> plain_highlighter;
|
||||||
|
plain_highlighter.instance();
|
||||||
|
add_syntax_highlighter(plain_highlighter);
|
||||||
|
|
||||||
|
Ref<EditorStandardSyntaxHighlighter> highlighter;
|
||||||
|
highlighter.instance();
|
||||||
|
add_syntax_highlighter(highlighter);
|
||||||
|
set_syntax_highlighter(highlighter);
|
||||||
|
|
||||||
search_menu = memnew(MenuButton);
|
search_menu = memnew(MenuButton);
|
||||||
search_menu->set_text(TTR("Search"));
|
search_menu->set_text(TTR("Search"));
|
||||||
|
@ -66,6 +66,7 @@ class Tree;
|
|||||||
struct ScriptCodeCompletionOption;
|
struct ScriptCodeCompletionOption;
|
||||||
class EditorScriptEditorQuickOpen;
|
class EditorScriptEditorQuickOpen;
|
||||||
class EditorConnectionInfoDialog;
|
class EditorConnectionInfoDialog;
|
||||||
|
class EditorSyntaxHighlighter;
|
||||||
|
|
||||||
class EditorScriptTextEditor : public EditorScriptEditorBase {
|
class EditorScriptTextEditor : public EditorScriptEditorBase {
|
||||||
GDCLASS(EditorScriptTextEditor, EditorScriptEditorBase);
|
GDCLASS(EditorScriptTextEditor, EditorScriptEditorBase);
|
||||||
@ -103,19 +104,6 @@ class EditorScriptTextEditor : public EditorScriptEditorBase {
|
|||||||
Vector2 color_position;
|
Vector2 color_position;
|
||||||
String color_args;
|
String color_args;
|
||||||
|
|
||||||
void _update_member_keywords();
|
|
||||||
|
|
||||||
struct ColorsCache {
|
|
||||||
Color symbol_color;
|
|
||||||
Color keyword_color;
|
|
||||||
Color control_flow_keyword_color;
|
|
||||||
Color basetype_color;
|
|
||||||
Color type_color;
|
|
||||||
Color usertype_color;
|
|
||||||
Color comment_color;
|
|
||||||
Color string_color;
|
|
||||||
} colors_cache;
|
|
||||||
|
|
||||||
bool theme_loaded;
|
bool theme_loaded;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -186,7 +174,7 @@ protected:
|
|||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
RBMap<String, Ref<SyntaxHighlighter>> highlighters;
|
RBMap<String, Ref<EditorSyntaxHighlighter>> highlighters;
|
||||||
void _change_syntax_highlighter(int p_idx);
|
void _change_syntax_highlighter(int p_idx);
|
||||||
|
|
||||||
void _edit_option(int p_op);
|
void _edit_option(int p_op);
|
||||||
@ -212,8 +200,8 @@ protected:
|
|||||||
public:
|
public:
|
||||||
void _update_connected_methods();
|
void _update_connected_methods();
|
||||||
|
|
||||||
virtual void add_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter);
|
virtual void add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter);
|
||||||
virtual void set_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter);
|
virtual void set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter);
|
||||||
void update_toggle_scripts_button();
|
void update_toggle_scripts_button();
|
||||||
|
|
||||||
virtual void apply_code();
|
virtual void apply_code();
|
||||||
|
229
editor_modules/editor_code_editor/editor_syntax_highlighter.cpp
Normal file
229
editor_modules/editor_code_editor/editor_syntax_highlighter.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*************************************************************************/
|
||||||
|
/* script_editor_plugin.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "editor_syntax_highlighter.h"
|
||||||
|
|
||||||
|
#include "editor/editor_settings.h"
|
||||||
|
#include "core/config/project_settings.h"
|
||||||
|
|
||||||
|
#include "editor_script_editor.h"
|
||||||
|
/*** SYNTAX HIGHLIGHTER ****/
|
||||||
|
|
||||||
|
String EditorSyntaxHighlighter::_get_name() const {
|
||||||
|
ScriptInstance *si = get_script_instance();
|
||||||
|
if (si && si->has_method("_get_name")) {
|
||||||
|
return si->call("_get_name");
|
||||||
|
}
|
||||||
|
return "Unnamed";
|
||||||
|
}
|
||||||
|
|
||||||
|
Array EditorSyntaxHighlighter::_get_supported_languages() const {
|
||||||
|
ScriptInstance *si = get_script_instance();
|
||||||
|
if (si && si->has_method("_get_supported_languages")) {
|
||||||
|
return si->call("_get_supported_languages");
|
||||||
|
}
|
||||||
|
return Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<EditorSyntaxHighlighter> EditorSyntaxHighlighter::_create() const {
|
||||||
|
Ref<EditorSyntaxHighlighter> syntax_highlighter;
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
if (get_script_instance()) {
|
||||||
|
syntax_highlighter->set_script(get_script_instance()->get_script().get_ref_ptr());
|
||||||
|
}
|
||||||
|
return syntax_highlighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorSyntaxHighlighter::EditorSyntaxHighlighter() {
|
||||||
|
}
|
||||||
|
EditorSyntaxHighlighter::~EditorSyntaxHighlighter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorSyntaxHighlighter::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("_get_edited_resource"), &EditorSyntaxHighlighter::_get_edited_resource);
|
||||||
|
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name"));
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_supported_languages"));
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_supported_extentions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
void EditorStandardSyntaxHighlighter::_update_cache() {
|
||||||
|
highlighter->set_text_edit(text_edit);
|
||||||
|
highlighter->clear_keyword_colors();
|
||||||
|
highlighter->clear_member_keyword_colors();
|
||||||
|
highlighter->clear_color_regions();
|
||||||
|
|
||||||
|
highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
|
||||||
|
highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color"));
|
||||||
|
highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
|
||||||
|
highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color"));
|
||||||
|
|
||||||
|
/* Engine types. */
|
||||||
|
const Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
|
||||||
|
List<StringName> types;
|
||||||
|
ClassDB::get_class_list(&types);
|
||||||
|
for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
|
||||||
|
String n = E->get();
|
||||||
|
if (n.begins_with("_")) {
|
||||||
|
n = n.substr(1, n.length());
|
||||||
|
}
|
||||||
|
highlighter->add_keyword_color(n, type_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* User types. */
|
||||||
|
const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
||||||
|
List<StringName> global_classes;
|
||||||
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
|
||||||
|
highlighter->add_keyword_color(E->get(), usertype_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Autoloads. */
|
||||||
|
List<PropertyInfo> props;
|
||||||
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
const PropertyInfo &pi = E->get();
|
||||||
|
|
||||||
|
if (!pi.name.begins_with("autoload/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = pi.name.get_slice("/", 1);
|
||||||
|
String path = ProjectSettings::get_singleton()->get(pi.name);
|
||||||
|
|
||||||
|
if (name.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_singleton = path.begins_with("*");
|
||||||
|
|
||||||
|
if (is_singleton) {
|
||||||
|
highlighter->add_keyword_color(name, usertype_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ref<Script> script = _get_edited_resource();
|
||||||
|
if (script.is_valid()) {
|
||||||
|
/* Core types. */
|
||||||
|
const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
||||||
|
List<String> core_types;
|
||||||
|
script->get_language()->get_core_type_words(&core_types);
|
||||||
|
for (List<String>::Element *E = core_types.front(); E; E = E->next()) {
|
||||||
|
highlighter->add_keyword_color(E->get(), basetype_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserved words. */
|
||||||
|
const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
||||||
|
List<String> keywords;
|
||||||
|
script->get_language()->get_reserved_words(&keywords);
|
||||||
|
for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
|
||||||
|
highlighter->add_keyword_color(E->get(), keyword_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Member types. */
|
||||||
|
const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
||||||
|
StringName instance_base = script->get_instance_base_type();
|
||||||
|
if (instance_base != StringName()) {
|
||||||
|
List<PropertyInfo> plist;
|
||||||
|
ClassDB::get_property_list(instance_base, &plist);
|
||||||
|
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
|
||||||
|
String name = E->get().name;
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (name.find("/") != -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
highlighter->add_member_keyword_color(name, member_variable_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> clist;
|
||||||
|
ClassDB::get_integer_constant_list(instance_base, &clist);
|
||||||
|
for (List<String>::Element *E = clist.front(); E; E = E->next()) {
|
||||||
|
highlighter->add_member_keyword_color(E->get(), member_variable_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comments */
|
||||||
|
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
||||||
|
List<String> comments;
|
||||||
|
script->get_language()->get_comment_delimiters(&comments);
|
||||||
|
for (List<String>::Element *E = comments.front(); E; E = E->next()) {
|
||||||
|
String comment = E->get();
|
||||||
|
String beg = comment.get_slice(" ", 0);
|
||||||
|
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
|
||||||
|
highlighter->add_color_region(beg, end, comment_color, end == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strings */
|
||||||
|
const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
||||||
|
List<String> strings;
|
||||||
|
script->get_language()->get_string_delimiters(&strings);
|
||||||
|
for (List<String>::Element *E = strings.front(); E; E = E->next()) {
|
||||||
|
String string = E->get();
|
||||||
|
String beg = string.get_slice(" ", 0);
|
||||||
|
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
|
||||||
|
highlighter->add_color_region(beg, end, string_color, end == "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<EditorSyntaxHighlighter> EditorStandardSyntaxHighlighter::_create() const {
|
||||||
|
Ref<EditorStandardSyntaxHighlighter> syntax_highlighter;
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
return syntax_highlighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorStandardSyntaxHighlighter::EditorStandardSyntaxHighlighter() {
|
||||||
|
highlighter.instance();
|
||||||
|
}
|
||||||
|
EditorStandardSyntaxHighlighter::~EditorStandardSyntaxHighlighter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorStandardSyntaxHighlighter::_bind_methods() {
|
||||||
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
Ref<EditorSyntaxHighlighter> EditorPlainTextSyntaxHighlighter::_create() const {
|
||||||
|
Ref<EditorPlainTextSyntaxHighlighter> syntax_highlighter;
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
return syntax_highlighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorPlainTextSyntaxHighlighter::EditorPlainTextSyntaxHighlighter() {
|
||||||
|
}
|
||||||
|
EditorPlainTextSyntaxHighlighter::~EditorPlainTextSyntaxHighlighter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorPlainTextSyntaxHighlighter::_bind_methods() {
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef EDITOR_SYNTAX_HIGHLIGHTER_H
|
||||||
|
#define EDITOR_SYNTAX_HIGHLIGHTER_H
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/* script_editor_plugin.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "editor/editor_plugin.h"
|
||||||
|
|
||||||
|
#include "scene/resources/syntax_highlighter.h"
|
||||||
|
|
||||||
|
class EditorSyntaxHighlighter : public SyntaxHighlighter {
|
||||||
|
GDCLASS(EditorSyntaxHighlighter, SyntaxHighlighter)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual String _get_name() const;
|
||||||
|
virtual Array _get_supported_languages() const;
|
||||||
|
|
||||||
|
void _set_edited_resource(const RES &p_res) { edited_resourse = p_res; }
|
||||||
|
REF _get_edited_resource() { return edited_resourse; }
|
||||||
|
|
||||||
|
virtual Ref<EditorSyntaxHighlighter> _create() const;
|
||||||
|
|
||||||
|
EditorSyntaxHighlighter();
|
||||||
|
~EditorSyntaxHighlighter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
REF edited_resourse;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorStandardSyntaxHighlighter : public EditorSyntaxHighlighter {
|
||||||
|
GDCLASS(EditorStandardSyntaxHighlighter, EditorSyntaxHighlighter)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void _update_cache();
|
||||||
|
virtual Dictionary _get_line_syntax_highlighting(int p_line) override { return highlighter->get_line_syntax_highlighting(p_line); }
|
||||||
|
|
||||||
|
virtual String _get_name() const { return TTR("Standard"); }
|
||||||
|
|
||||||
|
virtual Ref<EditorSyntaxHighlighter> _create() const;
|
||||||
|
|
||||||
|
EditorStandardSyntaxHighlighter();
|
||||||
|
~EditorStandardSyntaxHighlighter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<CodeHighlighter> highlighter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorPlainTextSyntaxHighlighter : public EditorSyntaxHighlighter {
|
||||||
|
GDCLASS(EditorPlainTextSyntaxHighlighter, EditorSyntaxHighlighter)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual String _get_name() const { return TTR("Plain Text"); }
|
||||||
|
|
||||||
|
virtual Ref<EditorSyntaxHighlighter> _create() const;
|
||||||
|
|
||||||
|
EditorPlainTextSyntaxHighlighter();
|
||||||
|
~EditorPlainTextSyntaxHighlighter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCRIPT_EDITOR_PLUGIN_H
|
@ -30,17 +30,17 @@
|
|||||||
|
|
||||||
#include "editor_text_editor.h"
|
#include "editor_text_editor.h"
|
||||||
|
|
||||||
#include "core/os/keyboard.h"
|
|
||||||
#include "editor/editor_node.h"
|
|
||||||
#include "core/variant/array.h"
|
|
||||||
#include "core/object/class_db.h"
|
|
||||||
#include "core/variant/dictionary.h"
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
|
#include "core/input/input_event.h"
|
||||||
#include "core/math/transform_2d.h"
|
#include "core/math/transform_2d.h"
|
||||||
#include "core/math/vector2.h"
|
#include "core/math/vector2.h"
|
||||||
#include "core/input/input_event.h"
|
#include "core/object/class_db.h"
|
||||||
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/memory.h"
|
#include "core/os/memory.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
#include "core/variant/array.h"
|
||||||
|
#include "core/variant/dictionary.h"
|
||||||
|
#include "editor/editor_node.h"
|
||||||
#include "editor/editor_settings.h"
|
#include "editor/editor_settings.h"
|
||||||
#include "scene/gui/box_container.h"
|
#include "scene/gui/box_container.h"
|
||||||
#include "scene/gui/control.h"
|
#include "scene/gui/control.h"
|
||||||
@ -50,39 +50,24 @@
|
|||||||
#include "scene/resources/text_file.h"
|
#include "scene/resources/text_file.h"
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
|
|
||||||
#include "editor_script_editor.h"
|
|
||||||
#include "editor_goto_line_dialog.h"
|
|
||||||
#include "editor_find_replace_bar.h"
|
#include "editor_find_replace_bar.h"
|
||||||
|
#include "editor_goto_line_dialog.h"
|
||||||
|
#include "editor_script_editor.h"
|
||||||
|
#include "editor_syntax_highlighter.h"
|
||||||
|
|
||||||
void EditorTextEditor::add_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) {
|
void EditorTextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
|
||||||
highlighters[p_highlighter->_get_name()] = p_highlighter;
|
highlighters[p_highlighter->_get_name()] = p_highlighter;
|
||||||
highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
|
highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorTextEditor::set_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter) {
|
void EditorTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
|
||||||
TextEdit *te = code_editor->get_text_edit();
|
TextEdit *te = code_editor->get_text_edit();
|
||||||
te->set_syntax_highlighting(p_highlighter);
|
te->set_syntax_highlighter(p_highlighter);
|
||||||
if (p_highlighter.is_valid()) {
|
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
|
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
|
||||||
} else {
|
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(TTR("Standard")), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// little work around. GDScript highlighter goes through text_edit for colours,
|
|
||||||
// so to remove all colours we need to set and unset them here.
|
|
||||||
if (p_highlighter == nullptr) { // standard
|
|
||||||
TextEdit *text_edit = code_editor->get_text_edit();
|
|
||||||
text_edit->add_theme_color_override("number_color", colors_cache.font_color);
|
|
||||||
text_edit->add_theme_color_override("function_color", colors_cache.font_color);
|
|
||||||
text_edit->add_theme_color_override("number_color", colors_cache.font_color);
|
|
||||||
text_edit->add_theme_color_override("member_variable_color", colors_cache.font_color);
|
|
||||||
} else {
|
|
||||||
_load_theme_settings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorTextEditor::_change_syntax_highlighter(int p_idx) {
|
void EditorTextEditor::_change_syntax_highlighter(int p_idx) {
|
||||||
RBMap<String, Ref<SyntaxHighlighter> >::Element *el = highlighters.front();
|
RBMap<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
|
||||||
while (el != nullptr) {
|
while (el != nullptr) {
|
||||||
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
|
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
|
||||||
el = el->next();
|
el = el->next();
|
||||||
@ -92,7 +77,7 @@ void EditorTextEditor::_change_syntax_highlighter(int p_idx) {
|
|||||||
|
|
||||||
void EditorTextEditor::_load_theme_settings() {
|
void EditorTextEditor::_load_theme_settings() {
|
||||||
TextEdit *text_edit = code_editor->get_text_edit();
|
TextEdit *text_edit = code_editor->get_text_edit();
|
||||||
text_edit->clear_colors();
|
text_edit->get_syntax_highlighter()->update_cache();
|
||||||
|
|
||||||
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
||||||
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
||||||
@ -110,9 +95,6 @@ void EditorTextEditor::_load_theme_settings() {
|
|||||||
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
||||||
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
||||||
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
||||||
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
|
|
||||||
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
|
|
||||||
Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
|
||||||
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
||||||
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
||||||
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
||||||
@ -120,13 +102,6 @@ void EditorTextEditor::_load_theme_settings() {
|
|||||||
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
||||||
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
||||||
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
||||||
Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
|
||||||
Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
|
||||||
Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
|
|
||||||
Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
|
||||||
Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
|
|
||||||
Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
|
||||||
Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
|
||||||
|
|
||||||
text_edit->add_theme_color_override("background_color", background_color);
|
text_edit->add_theme_color_override("background_color", background_color);
|
||||||
text_edit->add_theme_color_override("completion_background_color", completion_background_color);
|
text_edit->add_theme_color_override("completion_background_color", completion_background_color);
|
||||||
@ -144,9 +119,6 @@ void EditorTextEditor::_load_theme_settings() {
|
|||||||
text_edit->add_theme_color_override("current_line_color", current_line_color);
|
text_edit->add_theme_color_override("current_line_color", current_line_color);
|
||||||
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
||||||
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
||||||
text_edit->add_theme_color_override("number_color", number_color);
|
|
||||||
text_edit->add_theme_color_override("function_color", function_color);
|
|
||||||
text_edit->add_theme_color_override("member_variable_color", member_variable_color);
|
|
||||||
text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
|
text_edit->add_theme_color_override("breakpoint_color", breakpoint_color);
|
||||||
text_edit->add_theme_color_override("executing_line_color", executing_line_color);
|
text_edit->add_theme_color_override("executing_line_color", executing_line_color);
|
||||||
text_edit->add_theme_color_override("mark_color", mark_color);
|
text_edit->add_theme_color_override("mark_color", mark_color);
|
||||||
@ -154,18 +126,8 @@ void EditorTextEditor::_load_theme_settings() {
|
|||||||
text_edit->add_theme_color_override("code_folding_color", code_folding_color);
|
text_edit->add_theme_color_override("code_folding_color", code_folding_color);
|
||||||
text_edit->add_theme_color_override("search_result_color", search_result_color);
|
text_edit->add_theme_color_override("search_result_color", search_result_color);
|
||||||
text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
|
text_edit->add_theme_color_override("search_result_border_color", search_result_border_color);
|
||||||
text_edit->add_theme_color_override("symbol_color", symbol_color);
|
|
||||||
|
|
||||||
text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
|
text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6));
|
||||||
|
|
||||||
colors_cache.font_color = text_color;
|
|
||||||
colors_cache.symbol_color = symbol_color;
|
|
||||||
colors_cache.keyword_color = keyword_color;
|
|
||||||
colors_cache.control_flow_keyword_color = control_flow_keyword_color;
|
|
||||||
colors_cache.basetype_color = basetype_color;
|
|
||||||
colors_cache.type_color = type_color;
|
|
||||||
colors_cache.comment_color = comment_color;
|
|
||||||
colors_cache.string_color = string_color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String EditorTextEditor::get_name() {
|
String EditorTextEditor::get_name() {
|
||||||
@ -690,14 +652,21 @@ EditorTextEditor::EditorTextEditor() {
|
|||||||
convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize")), EDIT_CAPITALIZE);
|
convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize")), EDIT_CAPITALIZE);
|
||||||
convert_case->connect("id_pressed", this, "_edit_option");
|
convert_case->connect("id_pressed", this, "_edit_option");
|
||||||
|
|
||||||
highlighters[TTR("Standard")] = Ref<SyntaxHighlighter>();
|
|
||||||
highlighter_menu = memnew(PopupMenu);
|
highlighter_menu = memnew(PopupMenu);
|
||||||
highlighter_menu->set_name("highlighter_menu");
|
highlighter_menu->set_name("highlighter_menu");
|
||||||
edit_menu->get_popup()->add_child(highlighter_menu);
|
edit_menu->get_popup()->add_child(highlighter_menu);
|
||||||
edit_menu->get_popup()->add_submenu_item(TTR("Syntax Highlighter"), "highlighter_menu");
|
edit_menu->get_popup()->add_submenu_item(TTR("Syntax Highlighter"), "highlighter_menu");
|
||||||
highlighter_menu->add_radio_check_item(TTR("Standard"));
|
|
||||||
highlighter_menu->connect("id_pressed", this, "_change_syntax_highlighter");
|
highlighter_menu->connect("id_pressed", this, "_change_syntax_highlighter");
|
||||||
|
|
||||||
|
Ref<EditorPlainTextSyntaxHighlighter> plain_highlighter;
|
||||||
|
plain_highlighter.instance();
|
||||||
|
add_syntax_highlighter(plain_highlighter);
|
||||||
|
|
||||||
|
Ref<EditorStandardSyntaxHighlighter> highlighter;
|
||||||
|
highlighter.instance();
|
||||||
|
add_syntax_highlighter(highlighter);
|
||||||
|
set_syntax_highlighter(plain_highlighter);
|
||||||
|
|
||||||
MenuButton *goto_menu = memnew(MenuButton);
|
MenuButton *goto_menu = memnew(MenuButton);
|
||||||
edit_hb->add_child(goto_menu);
|
edit_hb->add_child(goto_menu);
|
||||||
goto_menu->set_text(TTR("Go To"));
|
goto_menu->set_text(TTR("Go To"));
|
||||||
|
@ -54,7 +54,7 @@ class SyntaxHighlighter;
|
|||||||
class TextFile;
|
class TextFile;
|
||||||
class Texture;
|
class Texture;
|
||||||
struct Vector2;
|
struct Vector2;
|
||||||
|
class EditorSyntaxHighlighter;
|
||||||
class EditorTextEditor : public EditorScriptEditorBase {
|
class EditorTextEditor : public EditorScriptEditorBase {
|
||||||
GDCLASS(EditorTextEditor, EditorScriptEditorBase);
|
GDCLASS(EditorTextEditor, EditorScriptEditorBase);
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ protected:
|
|||||||
void _text_edit_gui_input(const Ref<InputEvent> &ev);
|
void _text_edit_gui_input(const Ref<InputEvent> &ev);
|
||||||
void _prepare_edit_menu();
|
void _prepare_edit_menu();
|
||||||
|
|
||||||
RBMap<String, Ref<SyntaxHighlighter> > highlighters;
|
RBMap<String, Ref<EditorSyntaxHighlighter> > highlighters;
|
||||||
void _change_syntax_highlighter(int p_idx);
|
void _change_syntax_highlighter(int p_idx);
|
||||||
void _load_theme_settings();
|
void _load_theme_settings();
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ protected:
|
|||||||
void _bookmark_item_pressed(int p_idx);
|
void _bookmark_item_pressed(int p_idx);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void add_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter);
|
virtual void add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter);
|
||||||
virtual void set_syntax_highlighter(Ref<SyntaxHighlighter> p_highlighter);
|
virtual void set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter);
|
||||||
|
|
||||||
virtual String get_name();
|
virtual String get_name();
|
||||||
virtual Ref<Texture> get_icon();
|
virtual Ref<Texture> get_icon();
|
||||||
|
@ -16,6 +16,8 @@ void register_editor_code_editor_types(ModuleRegistrationLevel p_level) {
|
|||||||
|
|
||||||
ClassDB::register_virtual_class<EditorScriptEditorBase>();
|
ClassDB::register_virtual_class<EditorScriptEditorBase>();
|
||||||
|
|
||||||
|
ClassDB::register_class<EditorSyntaxHighlighter>();
|
||||||
|
|
||||||
//ClassDB::register_class<TextEditor>();
|
//ClassDB::register_class<TextEditor>();
|
||||||
//ClassDB::register_class<EditorScriptTextEditor>();
|
//ClassDB::register_class<EditorScriptTextEditor>();
|
||||||
//ClassDB::register_class<EditorCodeTextEditor>();
|
//ClassDB::register_class<EditorCodeTextEditor>();
|
||||||
|
@ -30,24 +30,24 @@
|
|||||||
|
|
||||||
#include "shader_editor_plugin.h"
|
#include "shader_editor_plugin.h"
|
||||||
|
|
||||||
#include "core/variant/array.h"
|
#include "core/containers/rb_map.h"
|
||||||
#include "core/object/class_db.h"
|
#include "core/containers/vector.h"
|
||||||
#include "core/math/color.h"
|
|
||||||
#include "core/error/error_list.h"
|
#include "core/error/error_list.h"
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
|
#include "core/input/input_event.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/io/resource_saver.h"
|
#include "core/io/resource_saver.h"
|
||||||
#include "core/containers/rb_map.h"
|
#include "core/math/color.h"
|
||||||
#include "core/math/transform_2d.h"
|
#include "core/math/transform_2d.h"
|
||||||
|
#include "core/object/class_db.h"
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
#include "core/input/input_event.h"
|
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/main_loop.h"
|
#include "core/os/main_loop.h"
|
||||||
#include "core/os/memory.h"
|
#include "core/os/memory.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/string/string_name.h"
|
#include "core/string/string_name.h"
|
||||||
|
#include "core/variant/array.h"
|
||||||
#include "core/variant/variant.h"
|
#include "core/variant/variant.h"
|
||||||
#include "core/containers/vector.h"
|
|
||||||
#include "core/version_generated.gen.h"
|
#include "core/version_generated.gen.h"
|
||||||
#include "editor/editor_node.h"
|
#include "editor/editor_node.h"
|
||||||
#include "editor/editor_scale.h"
|
#include "editor/editor_scale.h"
|
||||||
@ -61,12 +61,13 @@
|
|||||||
#include "scene/gui/popup_menu.h"
|
#include "scene/gui/popup_menu.h"
|
||||||
#include "scene/gui/text_edit.h"
|
#include "scene/gui/text_edit.h"
|
||||||
#include "scene/gui/tool_button.h"
|
#include "scene/gui/tool_button.h"
|
||||||
|
#include "scene/resources/syntax_highlighter.h"
|
||||||
#include "servers/rendering/shader_language.h"
|
#include "servers/rendering/shader_language.h"
|
||||||
#include "servers/rendering/shader_types.h"
|
#include "servers/rendering/shader_types.h"
|
||||||
#include "servers/rendering_server.h"
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
#include "editor_code_editor/editor_goto_line_dialog.h"
|
|
||||||
#include "editor_code_editor/editor_find_replace_bar.h"
|
#include "editor_code_editor/editor_find_replace_bar.h"
|
||||||
|
#include "editor_code_editor/editor_goto_line_dialog.h"
|
||||||
|
|
||||||
struct ScriptCodeCompletionOption;
|
struct ScriptCodeCompletionOption;
|
||||||
|
|
||||||
@ -113,8 +114,6 @@ void ShaderTextEditor::reload_text() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ShaderTextEditor::_load_theme_settings() {
|
void ShaderTextEditor::_load_theme_settings() {
|
||||||
get_text_edit()->clear_colors();
|
|
||||||
|
|
||||||
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
|
||||||
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
|
||||||
Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
|
Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
|
||||||
@ -131,9 +130,6 @@ void ShaderTextEditor::_load_theme_settings() {
|
|||||||
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
Color current_line_color = EDITOR_GET("text_editor/highlighting/current_line_color");
|
||||||
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
Color line_length_guideline_color = EDITOR_GET("text_editor/highlighting/line_length_guideline_color");
|
||||||
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
Color word_highlighted_color = EDITOR_GET("text_editor/highlighting/word_highlighted_color");
|
||||||
Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
|
|
||||||
Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
|
|
||||||
Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
|
||||||
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
Color mark_color = EDITOR_GET("text_editor/highlighting/mark_color");
|
||||||
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
Color bookmark_color = EDITOR_GET("text_editor/highlighting/bookmark_color");
|
||||||
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
Color breakpoint_color = EDITOR_GET("text_editor/highlighting/breakpoint_color");
|
||||||
@ -141,10 +137,6 @@ void ShaderTextEditor::_load_theme_settings() {
|
|||||||
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
Color code_folding_color = EDITOR_GET("text_editor/highlighting/code_folding_color");
|
||||||
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
|
||||||
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
|
||||||
Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
|
||||||
Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
|
||||||
Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
|
|
||||||
Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
|
||||||
|
|
||||||
get_text_edit()->add_theme_color_override("background_color", background_color);
|
get_text_edit()->add_theme_color_override("background_color", background_color);
|
||||||
get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color);
|
get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color);
|
||||||
@ -162,9 +154,6 @@ void ShaderTextEditor::_load_theme_settings() {
|
|||||||
get_text_edit()->add_theme_color_override("current_line_color", current_line_color);
|
get_text_edit()->add_theme_color_override("current_line_color", current_line_color);
|
||||||
get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
|
||||||
get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
|
||||||
get_text_edit()->add_theme_color_override("number_color", number_color);
|
|
||||||
get_text_edit()->add_theme_color_override("function_color", function_color);
|
|
||||||
get_text_edit()->add_theme_color_override("member_variable_color", member_variable_color);
|
|
||||||
get_text_edit()->add_theme_color_override("mark_color", mark_color);
|
get_text_edit()->add_theme_color_override("mark_color", mark_color);
|
||||||
get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color);
|
get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color);
|
||||||
get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color);
|
get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color);
|
||||||
@ -172,17 +161,19 @@ void ShaderTextEditor::_load_theme_settings() {
|
|||||||
get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color);
|
get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color);
|
||||||
get_text_edit()->add_theme_color_override("search_result_color", search_result_color);
|
get_text_edit()->add_theme_color_override("search_result_color", search_result_color);
|
||||||
get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color);
|
get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color);
|
||||||
get_text_edit()->add_theme_color_override("symbol_color", symbol_color);
|
|
||||||
|
syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
|
||||||
|
syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
|
||||||
|
syntax_highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color"));
|
||||||
|
syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color"));
|
||||||
|
|
||||||
|
const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
||||||
|
|
||||||
List<String> keywords;
|
List<String> keywords;
|
||||||
ShaderLanguage::get_keyword_list(&keywords);
|
ShaderLanguage::get_keyword_list(&keywords);
|
||||||
|
|
||||||
for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
|
for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
|
||||||
if (ShaderLanguage::is_control_flow_keyword(E->get())) {
|
syntax_highlighter->add_keyword_color(E->get(), keyword_color);
|
||||||
get_text_edit()->add_keyword_color(E->get(), control_flow_keyword_color);
|
|
||||||
} else {
|
|
||||||
get_text_edit()->add_keyword_color(E->get(), keyword_color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Colorize built-ins like `COLOR` differently to make them easier
|
// Colorize built-ins like `COLOR` differently to make them easier
|
||||||
@ -204,12 +195,14 @@ void ShaderTextEditor::_load_theme_settings() {
|
|||||||
const Color user_type_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
const Color user_type_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
||||||
|
|
||||||
for (List<String>::Element *E = built_ins.front(); E; E = E->next()) {
|
for (List<String>::Element *E = built_ins.front(); E; E = E->next()) {
|
||||||
get_text_edit()->add_keyword_color(E->get(), user_type_color);
|
syntax_highlighter->add_keyword_color(E->get(), user_type_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Colorize comments.
|
// Colorize comments.
|
||||||
get_text_edit()->add_color_region("/*", "*/", comment_color, false);
|
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
||||||
get_text_edit()->add_color_region("//", "", comment_color, false);
|
syntax_highlighter->clear_color_regions();
|
||||||
|
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
|
||||||
|
syntax_highlighter->add_color_region("//", "", comment_color, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderTextEditor::_check_shader_mode() {
|
void ShaderTextEditor::_check_shader_mode() {
|
||||||
@ -276,6 +269,8 @@ void ShaderTextEditor::_bind_methods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShaderTextEditor::ShaderTextEditor() {
|
ShaderTextEditor::ShaderTextEditor() {
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
get_text_edit()->set_syntax_highlighter(syntax_highlighter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** SCRIPT EDITOR ******/
|
/*** SCRIPT EDITOR ******/
|
||||||
@ -396,7 +391,6 @@ void ShaderEditor::_editor_settings_changed() {
|
|||||||
shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
|
shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
|
||||||
shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces"));
|
shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces"));
|
||||||
shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
|
shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
|
||||||
shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
|
|
||||||
shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
|
shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
|
||||||
shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
|
shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
|
||||||
shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->is_caret_blink_active());
|
shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->is_caret_blink_active());
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "editor_code_editor/editor_code_text_editor.h"
|
|
||||||
#include "editor/editor_plugin.h"
|
#include "editor/editor_plugin.h"
|
||||||
|
#include "editor_code_editor/editor_code_text_editor.h"
|
||||||
#include "scene/gui/margin_container.h"
|
#include "scene/gui/margin_container.h"
|
||||||
|
|
||||||
#include "scene/resources/shader.h"
|
#include "scene/resources/shader.h"
|
||||||
@ -49,10 +49,12 @@ class InputEvent;
|
|||||||
class MenuButton;
|
class MenuButton;
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
struct ScriptCodeCompletionOption;
|
struct ScriptCodeCompletionOption;
|
||||||
|
class CodeHighlighter;
|
||||||
|
|
||||||
class ShaderTextEditor : public EditorCodeTextEditor {
|
class ShaderTextEditor : public EditorCodeTextEditor {
|
||||||
GDCLASS(ShaderTextEditor, EditorCodeTextEditor);
|
GDCLASS(ShaderTextEditor, EditorCodeTextEditor);
|
||||||
|
|
||||||
|
Ref<CodeHighlighter> syntax_highlighter;
|
||||||
Ref<Shader> shader;
|
Ref<Shader> shader;
|
||||||
|
|
||||||
void _check_shader_mode();
|
void _check_shader_mode();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "scene/gui/line_edit.h"
|
#include "scene/gui/line_edit.h"
|
||||||
#include "scene/gui/text_edit.h"
|
#include "scene/gui/text_edit.h"
|
||||||
#include "scene/gui/texture_rect.h"
|
#include "scene/gui/texture_rect.h"
|
||||||
|
#include "scene/resources/syntax_highlighter.h"
|
||||||
|
|
||||||
#include "editor_code_editor/editor_code_text_editor.h"
|
#include "editor_code_editor/editor_code_text_editor.h"
|
||||||
#include "editor_code_editor/editor_find_replace_bar.h"
|
#include "editor_code_editor/editor_find_replace_bar.h"
|
||||||
@ -75,51 +76,76 @@ void TextEditorVanillaEditor::draw_minimap(const bool value) {
|
|||||||
|
|
||||||
void TextEditorVanillaEditor::color_region(const String &fileextension) {
|
void TextEditorVanillaEditor::color_region(const String &fileextension) {
|
||||||
if (fileextension == "bbs") {
|
if (fileextension == "bbs") {
|
||||||
text_editor->add_color_region("[b]", "[/b]", Color::color8(153, 153, 255, 255), false);
|
Ref<CodeHighlighter> highlighter;
|
||||||
text_editor->add_color_region("[i]", "[/i]", Color::color8(153, 255, 153, 255), false);
|
highlighter.instance();
|
||||||
text_editor->add_color_region("[s]", "[/s]", Color::color8(255, 153, 153, 255), false);
|
|
||||||
text_editor->add_color_region("[u]", "[/u]", Color::color8(255, 255, 102, 255), false);
|
highlighter->add_color_region("[b]", "[/b]", Color::color8(153, 153, 255, 255), false);
|
||||||
text_editor->add_color_region("[url", "[/url]", Color::color8(153, 204, 255, 255), false);
|
highlighter->add_color_region("[i]", "[/i]", Color::color8(153, 255, 153, 255), false);
|
||||||
text_editor->add_color_region("[code]", "[/code]", Color::color8(192, 192, 192, 255), false);
|
highlighter->add_color_region("[s]", "[/s]", Color::color8(255, 153, 153, 255), false);
|
||||||
text_editor->add_color_region("[img]", "[/img]", Color::color8(255, 204, 153, 255), false);
|
highlighter->add_color_region("[u]", "[/u]", Color::color8(255, 255, 102, 255), false);
|
||||||
text_editor->add_color_region("[center]", "[/center]", Color::color8(175, 238, 238, 255), false);
|
highlighter->add_color_region("[url", "[/url]", Color::color8(153, 204, 255, 255), false);
|
||||||
text_editor->add_color_region("[right]", "[/right]", Color::color8(135, 206, 235, 255), false);
|
highlighter->add_color_region("[code]", "[/code]", Color::color8(192, 192, 192, 255), false);
|
||||||
|
highlighter->add_color_region("[img]", "[/img]", Color::color8(255, 204, 153, 255), false);
|
||||||
|
highlighter->add_color_region("[center]", "[/center]", Color::color8(175, 238, 238, 255), false);
|
||||||
|
highlighter->add_color_region("[right]", "[/right]", Color::color8(135, 206, 235, 255), false);
|
||||||
|
|
||||||
|
text_editor->set_syntax_highlighter(highlighter);
|
||||||
} else if (fileextension == "html") {
|
} else if (fileextension == "html") {
|
||||||
text_editor->add_color_region("<b>", "</b>", Color::color8(153, 153, 255, 255), false);
|
Ref<CodeHighlighter> highlighter;
|
||||||
text_editor->add_color_region("<i>", "</i>", Color::color8(153, 255, 153, 255), false);
|
highlighter.instance();
|
||||||
text_editor->add_color_region("<del>", "</del>", Color::color8(255, 153, 153, 255), false);
|
|
||||||
text_editor->add_color_region("<ins>", "</ins>", Color::color8(255, 255, 102, 255), false);
|
highlighter->add_color_region("<b>", "</b>", Color::color8(153, 153, 255, 255), false);
|
||||||
text_editor->add_color_region("<a", "</a>", Color::color8(153, 204, 255, 255), false);
|
highlighter->add_color_region("<i>", "</i>", Color::color8(153, 255, 153, 255), false);
|
||||||
text_editor->add_color_region("<img", "/>", Color::color8(255, 204, 153, 255), true);
|
highlighter->add_color_region("<del>", "</del>", Color::color8(255, 153, 153, 255), false);
|
||||||
text_editor->add_color_region("<pre>", "</pre>", Color::color8(192, 192, 192, 255), false);
|
highlighter->add_color_region("<ins>", "</ins>", Color::color8(255, 255, 102, 255), false);
|
||||||
text_editor->add_color_region("<center>", "</center>", Color::color8(175, 238, 238, 255), false);
|
highlighter->add_color_region("<a", "</a>", Color::color8(153, 204, 255, 255), false);
|
||||||
text_editor->add_color_region("<right>", "</right>", Color::color8(135, 206, 235, 255), false);
|
highlighter->add_color_region("<img", "/>", Color::color8(255, 204, 153, 255), true);
|
||||||
|
highlighter->add_color_region("<pre>", "</pre>", Color::color8(192, 192, 192, 255), false);
|
||||||
|
highlighter->add_color_region("<center>", "</center>", Color::color8(175, 238, 238, 255), false);
|
||||||
|
highlighter->add_color_region("<right>", "</right>", Color::color8(135, 206, 235, 255), false);
|
||||||
|
|
||||||
|
text_editor->set_syntax_highlighter(highlighter);
|
||||||
} else if (fileextension == "md") {
|
} else if (fileextension == "md") {
|
||||||
text_editor->add_color_region("***", "***", Color::color8(126, 186, 181, 255), false);
|
Ref<CodeHighlighter> highlighter;
|
||||||
text_editor->add_color_region("**", "**", Color::color8(153, 153, 255, 255), false);
|
highlighter.instance();
|
||||||
text_editor->add_color_region("*", "*", Color::color8(153, 255, 153, 255), false);
|
|
||||||
text_editor->add_color_region("+ ", "", Color::color8(255, 178, 102, 255), false);
|
highlighter->add_color_region("***", "***", Color::color8(126, 186, 181, 255), false);
|
||||||
text_editor->add_color_region("- ", "", Color::color8(255, 178, 102, 255), false);
|
highlighter->add_color_region("**", "**", Color::color8(153, 153, 255, 255), false);
|
||||||
text_editor->add_color_region("~~", "~~", Color::color8(255, 153, 153, 255), false);
|
highlighter->add_color_region("*", "*", Color::color8(153, 255, 153, 255), false);
|
||||||
text_editor->add_color_region("__", "__", Color::color8(255, 255, 102, 255), false);
|
highlighter->add_color_region("+ ", "", Color::color8(255, 178, 102, 255), false);
|
||||||
text_editor->add_color_region("[", ")", Color::color8(153, 204, 255, 255), false);
|
highlighter->add_color_region("- ", "", Color::color8(255, 178, 102, 255), false);
|
||||||
text_editor->add_color_region("`", "`", Color::color8(192, 192, 192, 255), false);
|
highlighter->add_color_region("~~", "~~", Color::color8(255, 153, 153, 255), false);
|
||||||
text_editor->add_color_region("\"*.", "\"", Color::color8(255, 255, 255, 255), true);
|
highlighter->add_color_region("__", "__", Color::color8(255, 255, 102, 255), false);
|
||||||
text_editor->add_color_region("# ", "", Color::color8(105, 105, 105, 255), true);
|
highlighter->add_color_region("[", ")", Color::color8(153, 204, 255, 255), false);
|
||||||
text_editor->add_color_region("## ", "", Color::color8(128, 128, 128, 255), true);
|
highlighter->add_color_region("`", "`", Color::color8(192, 192, 192, 255), false);
|
||||||
text_editor->add_color_region("### ", "", Color::color8(169, 169, 169, 255), true);
|
highlighter->add_color_region("\"*.", "\"", Color::color8(255, 255, 255, 255), true);
|
||||||
text_editor->add_color_region("#### ", "", Color::color8(192, 192, 192, 255), true);
|
highlighter->add_color_region("# ", "", Color::color8(105, 105, 105, 255), true);
|
||||||
text_editor->add_color_region("##### ", "", Color::color8(211, 211, 211, 255), true);
|
highlighter->add_color_region("## ", "", Color::color8(128, 128, 128, 255), true);
|
||||||
text_editor->add_color_region("###### ", "", Color::color8(255, 255, 255, 255), true);
|
highlighter->add_color_region("### ", "", Color::color8(169, 169, 169, 255), true);
|
||||||
text_editor->add_color_region("> ", "", Color::color8(172, 138, 79, 255), true);
|
highlighter->add_color_region("#### ", "", Color::color8(192, 192, 192, 255), true);
|
||||||
|
highlighter->add_color_region("##### ", "", Color::color8(211, 211, 211, 255), true);
|
||||||
|
highlighter->add_color_region("###### ", "", Color::color8(255, 255, 255, 255), true);
|
||||||
|
highlighter->add_color_region("> ", "", Color::color8(172, 138, 79, 255), true);
|
||||||
|
|
||||||
|
text_editor->set_syntax_highlighter(highlighter);
|
||||||
} else if (fileextension == "cfg") {
|
} else if (fileextension == "cfg") {
|
||||||
text_editor->add_color_region("[", "]", Color::color8(153, 204, 255, 255), false);
|
Ref<CodeHighlighter> highlighter;
|
||||||
text_editor->add_color_region("\"", "\"", Color::color8(255, 255, 102, 255), false);
|
highlighter.instance();
|
||||||
text_editor->add_color_region(";", "", Color::color8(128, 128, 128, 255), true);
|
|
||||||
|
highlighter->add_color_region("[", "]", Color::color8(153, 204, 255, 255), false);
|
||||||
|
highlighter->add_color_region("\"", "\"", Color::color8(255, 255, 102, 255), false);
|
||||||
|
highlighter->add_color_region(";", "", Color::color8(128, 128, 128, 255), true);
|
||||||
|
|
||||||
|
text_editor->set_syntax_highlighter(highlighter);
|
||||||
} else if (fileextension == "ini") {
|
} else if (fileextension == "ini") {
|
||||||
text_editor->add_color_region("[", "]", Color::color8(153, 204, 255, 255), false);
|
Ref<CodeHighlighter> highlighter;
|
||||||
text_editor->add_color_region("\"", "\"", Color::color8(255, 255, 102, 255), false);
|
highlighter.instance();
|
||||||
text_editor->add_color_region(";", "", Color::color8(128, 128, 128, 255), true);
|
|
||||||
|
highlighter->add_color_region("[", "]", Color::color8(153, 204, 255, 255), false);
|
||||||
|
highlighter->add_color_region("\"", "\"", Color::color8(255, 255, 102, 255), false);
|
||||||
|
highlighter->add_color_region(";", "", Color::color8(128, 128, 128, 255), true);
|
||||||
|
|
||||||
|
text_editor->set_syntax_highlighter(highlighter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +221,6 @@ TextEditorVanillaEditor::TextEditorVanillaEditor() {
|
|||||||
text_editor = memnew(TextEdit);
|
text_editor = memnew(TextEdit);
|
||||||
add_child(text_editor);
|
add_child(text_editor);
|
||||||
text_editor->set_highlight_current_line(true);
|
text_editor->set_highlight_current_line(true);
|
||||||
text_editor->set_syntax_coloring(true);
|
|
||||||
text_editor->set_show_line_numbers(true);
|
text_editor->set_show_line_numbers(true);
|
||||||
text_editor->set_breakpoint_gutter_enabled(true);
|
text_editor->set_breakpoint_gutter_enabled(true);
|
||||||
text_editor->set_highlight_all_occurrences(true);
|
text_editor->set_highlight_all_occurrences(true);
|
||||||
|
@ -29,25 +29,15 @@
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "cscript_highlighter.h"
|
#include "cscript_highlighter.h"
|
||||||
|
#include "../cscript.h"
|
||||||
#include "../cscript_tokenizer.h"
|
#include "../cscript_tokenizer.h"
|
||||||
#include "editor/editor_settings.h"
|
#include "editor/editor_settings.h"
|
||||||
|
#include "core/config/project_settings.h"
|
||||||
inline bool _is_symbol(CharType c) {
|
|
||||||
return is_symbol(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_text_char(CharType c) {
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_char(CharType c) {
|
static bool _is_char(CharType c) {
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _is_number(CharType c) {
|
|
||||||
return (c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_hex_symbol(CharType c) {
|
static bool _is_hex_symbol(CharType c) {
|
||||||
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||||
}
|
}
|
||||||
@ -81,36 +71,136 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
Color keyword_color;
|
Color keyword_color;
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
int in_region = text_edit->_is_line_in_region(p_line);
|
color_region_cache[p_line] = -1;
|
||||||
int deregion = 0;
|
int in_region = -1;
|
||||||
|
if (p_line != 0) {
|
||||||
|
if (!color_region_cache.has(p_line - 1)) {
|
||||||
|
get_line_syntax_highlighting(p_line - 1);
|
||||||
|
}
|
||||||
|
in_region = color_region_cache[p_line - 1];
|
||||||
|
}
|
||||||
|
|
||||||
const RBMap<int, TextEdit::Text::ColorRegionInfo> cri_map = text_edit->_get_line_color_region_info(p_line);
|
|
||||||
const String &str = text_edit->get_line(p_line);
|
const String &str = text_edit->get_line(p_line);
|
||||||
|
const int line_length = str.length();
|
||||||
Color prev_color;
|
Color prev_color;
|
||||||
for (int j = 0; j < str.length(); j++) {
|
for (int j = 0; j < str.length(); j++) {
|
||||||
Dictionary highlighter_info;
|
Dictionary highlighter_info;
|
||||||
|
|
||||||
if (deregion > 0) {
|
color = font_color;
|
||||||
deregion--;
|
bool is_char = !is_symbol(str[j]);
|
||||||
if (deregion == 0) {
|
bool is_a_symbol = is_symbol(str[j]);
|
||||||
in_region = -1;
|
bool is_number = (str[j] >= '0' && str[j] <= '9');
|
||||||
|
|
||||||
|
/* color regions */
|
||||||
|
if (is_a_symbol || in_region != -1) {
|
||||||
|
int from = j;
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deregion != 0) {
|
if (from != line_length) {
|
||||||
if (color != prev_color) {
|
/* check if we are in entering a region */
|
||||||
prev_color = color;
|
if (in_region == -1) {
|
||||||
highlighter_info["color"] = color;
|
for (int c = 0; c < color_regions.size(); c++) {
|
||||||
color_map[j] = highlighter_info;
|
/* check there is enough room */
|
||||||
}
|
int chars_left = line_length - from;
|
||||||
|
int start_key_length = color_regions[c].start_key.length();
|
||||||
|
int end_key_length = color_regions[c].end_key.length();
|
||||||
|
if (chars_left < start_key_length) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = font_color;
|
/* search the line */
|
||||||
|
bool match = true;
|
||||||
|
const CharType *start_key = color_regions[c].start_key.get_data();
|
||||||
|
for (int k = 0; k < start_key_length; k++) {
|
||||||
|
if (start_key[k] != str[from + k]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
in_region = c;
|
||||||
|
from += start_key_length;
|
||||||
|
|
||||||
bool is_char = _is_text_char(str[j]);
|
/* check if it's the whole line */
|
||||||
bool is_symbol = _is_symbol(str[j]);
|
if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) {
|
||||||
bool is_number = _is_number(str[j]);
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[c].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
j = line_length;
|
||||||
|
if (!color_regions[c].line_only) {
|
||||||
|
color_region_cache[p_line] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == line_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are in one find the end key */
|
||||||
|
if (in_region != -1) {
|
||||||
|
/* check there is enough room */
|
||||||
|
int chars_left = line_length - from;
|
||||||
|
int end_key_length = color_regions[in_region].end_key.length();
|
||||||
|
if (chars_left < end_key_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the line */
|
||||||
|
int region_end_index = -1;
|
||||||
|
const CharType *end_key = color_regions[in_region].start_key.get_data();
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (!is_a_symbol) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < end_key_length; k++) {
|
||||||
|
if (end_key[k] == str[from + k]) {
|
||||||
|
region_end_index = from;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (region_end_index != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[in_region].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
previous_type = REGION;
|
||||||
|
previous_text = "";
|
||||||
|
previous_column = j;
|
||||||
|
j = from;
|
||||||
|
if (region_end_index == -1) {
|
||||||
|
color_region_cache[p_line] = in_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_region = -1;
|
||||||
|
prev_is_char = false;
|
||||||
|
prev_is_number = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// allow ABCDEF in hex notation
|
// allow ABCDEF in hex notation
|
||||||
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
||||||
@ -132,7 +222,7 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
|
// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
|
||||||
if ((str[j] == '.' || str[j] == 'x' || str[j] == 'b' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
if ((str[j] == '.' || str[j] == 'x' || str[j] == 'b' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
||||||
is_number = true;
|
is_number = true;
|
||||||
is_symbol = false;
|
is_a_symbol = false;
|
||||||
is_char = false;
|
is_char = false;
|
||||||
|
|
||||||
if (str[j] == 'x' && str[j - 1] == '0') {
|
if (str[j] == 'x' && str[j - 1] == '0') {
|
||||||
@ -150,64 +240,46 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
is_number = false;
|
is_number = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && str[j] != '.' && in_word) {
|
if (is_a_symbol && str[j] != '.' && in_word) {
|
||||||
in_word = false;
|
in_word = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && cri_map.has(j)) {
|
|
||||||
const TextEdit::Text::ColorRegionInfo &cri = cri_map[j];
|
|
||||||
|
|
||||||
if (in_region == -1) {
|
|
||||||
if (!cri.end) {
|
|
||||||
in_region = cri.region;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TextEdit::ColorRegion cr = text_edit->_get_color_region(cri.region);
|
|
||||||
if (in_region == cri.region && !cr.line_only) { //ignore otherwise
|
|
||||||
if (cri.end || cr.eq) {
|
|
||||||
deregion = cr.eq ? cr.begin_key.length() : cr.end_key.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_char) {
|
if (!is_char) {
|
||||||
in_keyword = false;
|
in_keyword = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_region == -1 && !in_keyword && is_char && !prev_is_char) {
|
if (!in_keyword && is_char && !prev_is_char) {
|
||||||
int to = j;
|
int to = j;
|
||||||
while (to < str.length() && _is_text_char(str[to])) {
|
|
||||||
|
while (to < str.length() && !is_symbol(str[to])) {
|
||||||
to++;
|
to++;
|
||||||
}
|
}
|
||||||
|
|
||||||
String word = str.substr(j, to - j);
|
String word = str.substr(j, to - j);
|
||||||
Color col = Color();
|
Color col = Color();
|
||||||
if (text_edit->has_keyword_color(word)) {
|
if (keywords.has(word)) {
|
||||||
col = text_edit->get_keyword_color(word);
|
col = keywords[word];
|
||||||
} else if (text_edit->has_member_color(word)) {
|
} else if (member_keywords.has(word)) {
|
||||||
col = text_edit->get_member_color(word);
|
col = member_keywords[word];
|
||||||
}
|
|
||||||
|
|
||||||
if (col != Color()) {
|
|
||||||
for (int k = j - 1; k >= 0; k--) {
|
for (int k = j - 1; k >= 0; k--) {
|
||||||
if (str[k] == '.') {
|
if (str[k] == '.') {
|
||||||
col = Color(); // keyword & member indexing not allowed
|
col = Color(); //member indexing not allowed
|
||||||
break;
|
break;
|
||||||
} else if (str[k] > 32) {
|
} else if (str[k] > 32) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (col != Color()) {
|
if (col != Color()) {
|
||||||
in_keyword = true;
|
in_keyword = true;
|
||||||
keyword_color = col;
|
keyword_color = col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_function_name && in_word && !in_keyword) {
|
if (!in_function_name && in_word && !in_keyword) {
|
||||||
int k = j;
|
int k = j;
|
||||||
while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
while (k < str.length() && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +297,7 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
|
|
||||||
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
||||||
int k = j;
|
int k = j;
|
||||||
while (k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
while (k > 0 && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
k--;
|
k--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +306,7 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && in_region == -1) {
|
if (is_a_symbol) {
|
||||||
if (in_function_name) {
|
if (in_function_name) {
|
||||||
in_function_args = true;
|
in_function_args = true;
|
||||||
}
|
}
|
||||||
@ -271,14 +343,11 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
|
|
||||||
if (!in_node_path && in_region == -1 && str[j] == '$') {
|
if (!in_node_path && in_region == -1 && str[j] == '$') {
|
||||||
in_node_path = true;
|
in_node_path = true;
|
||||||
} else if (in_region != -1 || (is_symbol && str[j] != '/')) {
|
} else if (in_region != -1 || (is_a_symbol && str[j] != '/')) {
|
||||||
in_node_path = false;
|
in_node_path = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_region >= 0) {
|
if (in_node_path) {
|
||||||
next_type = REGION;
|
|
||||||
color = text_edit->_get_color_region(in_region).color;
|
|
||||||
} else if (in_node_path) {
|
|
||||||
next_type = NODE_PATH;
|
next_type = NODE_PATH;
|
||||||
color = node_path_color;
|
color = node_path_color;
|
||||||
} else if (in_keyword) {
|
} else if (in_keyword) {
|
||||||
@ -295,7 +364,7 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
} else {
|
} else {
|
||||||
color = function_color;
|
color = function_color;
|
||||||
}
|
}
|
||||||
} else if (is_symbol) {
|
} else if (is_a_symbol) {
|
||||||
next_type = SYMBOL;
|
next_type = SYMBOL;
|
||||||
color = symbol_color;
|
color = symbol_color;
|
||||||
} else if (is_number) {
|
} else if (is_number) {
|
||||||
@ -343,6 +412,7 @@ Dictionary CScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) {
|
|||||||
return color_map;
|
return color_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String CScriptSyntaxHighlighter::_get_name() const {
|
String CScriptSyntaxHighlighter::_get_name() const {
|
||||||
return "CScript";
|
return "CScript";
|
||||||
}
|
}
|
||||||
@ -354,11 +424,128 @@ Array CScriptSyntaxHighlighter::_get_supported_languages() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CScriptSyntaxHighlighter::_update_cache() {
|
void CScriptSyntaxHighlighter::_update_cache() {
|
||||||
|
keywords.clear();
|
||||||
|
member_keywords.clear();
|
||||||
|
color_regions.clear();
|
||||||
|
color_region_cache.clear();
|
||||||
|
|
||||||
font_color = text_edit->get_theme_color("font_color");
|
font_color = text_edit->get_theme_color("font_color");
|
||||||
symbol_color = text_edit->get_theme_color("symbol_color");
|
symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
||||||
function_color = text_edit->get_theme_color("function_color");
|
function_color = EDITOR_GET("text_editor/highlighting/function_color");
|
||||||
number_color = text_edit->get_theme_color("number_color");
|
number_color = EDITOR_GET("text_editor/highlighting/number_color");
|
||||||
member_color = text_edit->get_theme_color("member_variable_color");
|
member_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
||||||
|
|
||||||
|
/* Engine types. */
|
||||||
|
const Color types_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
|
||||||
|
List<StringName> types;
|
||||||
|
ClassDB::get_class_list(&types);
|
||||||
|
for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
|
||||||
|
String n = E->get();
|
||||||
|
if (n.begins_with("_")) {
|
||||||
|
n = n.substr(1, n.length());
|
||||||
|
}
|
||||||
|
keywords[n] = types_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* User types. */
|
||||||
|
const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
||||||
|
List<StringName> global_classes;
|
||||||
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
|
||||||
|
keywords[String(E->get())] = usertype_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Autoloads. */
|
||||||
|
|
||||||
|
List<PropertyInfo> props;
|
||||||
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
const PropertyInfo &pi = E->get();
|
||||||
|
|
||||||
|
if (!pi.name.begins_with("autoload/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = pi.name.get_slice("/", 1);
|
||||||
|
String path = ProjectSettings::get_singleton()->get(pi.name);
|
||||||
|
|
||||||
|
if (name.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_singleton = path.begins_with("*");
|
||||||
|
|
||||||
|
if (is_singleton) {
|
||||||
|
keywords[name] = usertype_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CScriptLanguage *cscript = CScriptLanguage::get_singleton();
|
||||||
|
|
||||||
|
/* Core types. */
|
||||||
|
const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
||||||
|
List<String> core_types;
|
||||||
|
cscript->get_core_type_words(&core_types);
|
||||||
|
for (List<String>::Element *E = core_types.front(); E; E = E->next()) {
|
||||||
|
keywords[E->get()] = basetype_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserved words. */
|
||||||
|
const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
||||||
|
List<String> keyword_list;
|
||||||
|
cscript->get_reserved_words(&keyword_list);
|
||||||
|
for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
|
||||||
|
keywords[E->get()] = keyword_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comments */
|
||||||
|
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
||||||
|
List<String> comments;
|
||||||
|
cscript->get_comment_delimiters(&comments);
|
||||||
|
for (List<String>::Element *E = comments.front(); E; E = E->next()) {
|
||||||
|
String comment = E->get();
|
||||||
|
String beg = comment.get_slice(" ", 0);
|
||||||
|
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
|
||||||
|
add_color_region(beg, end, comment_color, end == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strings */
|
||||||
|
const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
||||||
|
List<String> strings;
|
||||||
|
cscript->get_string_delimiters(&strings);
|
||||||
|
for (List<String>::Element *E = strings.front(); E; E = E->next()) {
|
||||||
|
String string = E->get();
|
||||||
|
String beg = string.get_slice(" ", 0);
|
||||||
|
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
|
||||||
|
add_color_region(beg, end, string_color, end == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ref<Script> script = _get_edited_resource();
|
||||||
|
if (script.is_valid()) {
|
||||||
|
/* Member types. */
|
||||||
|
const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
||||||
|
StringName instance_base = script->get_instance_base_type();
|
||||||
|
if (instance_base != StringName()) {
|
||||||
|
List<PropertyInfo> plist;
|
||||||
|
ClassDB::get_property_list(instance_base, &plist);
|
||||||
|
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
|
||||||
|
String name = E->get().name;
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (name.find("/") != -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
member_keywords[name] = member_variable_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> clist;
|
||||||
|
ClassDB::get_integer_constant_list(instance_base, &clist);
|
||||||
|
for (List<String>::Element *E = clist.front(); E; E = E->next()) {
|
||||||
|
member_keywords[E->get()] = member_variable_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
|
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
|
||||||
const bool default_theme = text_edit_color_theme == "Default";
|
const bool default_theme = text_edit_color_theme == "Default";
|
||||||
@ -389,6 +576,31 @@ void CScriptSyntaxHighlighter::_update_cache() {
|
|||||||
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxHighlighter *CScriptSyntaxHighlighter::create() {
|
void CScriptSyntaxHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
|
||||||
return memnew(CScriptSyntaxHighlighter);
|
for (int i = 0; i < p_start_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "color regions must start with a symbol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_end_key.length() > 0) {
|
||||||
|
for (int i = 0; i < p_end_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_end_key[i]), "color regions must end with a symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "color region with start key '" + p_start_key + "' already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRegion color_region;
|
||||||
|
color_region.color = p_color;
|
||||||
|
color_region.start_key = p_start_key;
|
||||||
|
color_region.end_key = p_end_key;
|
||||||
|
color_region.line_only = p_line_only;
|
||||||
|
color_regions.push_back(color_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<EditorSyntaxHighlighter> CScriptSyntaxHighlighter::_create() const {
|
||||||
|
Ref<CScriptSyntaxHighlighter> syntax_highlighter;
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
return syntax_highlighter;
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,25 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "editor_modules/editor_code_editor/editor_syntax_highlighter.h"
|
||||||
#include "scene/gui/text_edit.h"
|
#include "scene/gui/text_edit.h"
|
||||||
|
|
||||||
class CScriptSyntaxHighlighter : public SyntaxHighlighter {
|
class CScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
|
||||||
|
GDCLASS(CScriptSyntaxHighlighter, EditorSyntaxHighlighter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ColorRegion {
|
||||||
|
Color color;
|
||||||
|
String start_key;
|
||||||
|
String end_key;
|
||||||
|
bool line_only;
|
||||||
|
};
|
||||||
|
Vector<ColorRegion> color_regions;
|
||||||
|
RBMap<int, int> color_region_cache;
|
||||||
|
|
||||||
|
Dictionary keywords;
|
||||||
|
Dictionary member_keywords;
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
NONE,
|
NONE,
|
||||||
REGION,
|
REGION,
|
||||||
@ -58,8 +73,10 @@ private:
|
|||||||
Color node_path_color;
|
Color node_path_color;
|
||||||
Color type_color;
|
Color type_color;
|
||||||
|
|
||||||
|
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SyntaxHighlighter *create();
|
virtual Ref<EditorSyntaxHighlighter> _create() const;
|
||||||
|
|
||||||
virtual void _update_cache();
|
virtual void _update_cache();
|
||||||
virtual Dictionary _get_line_syntax_highlighting(int p_line);
|
virtual Dictionary _get_line_syntax_highlighting(int p_line);
|
||||||
|
@ -138,6 +138,12 @@ static void _editor_init() {
|
|||||||
Ref<EditorExportCScript> gd_export;
|
Ref<EditorExportCScript> gd_export;
|
||||||
gd_export.instance();
|
gd_export.instance();
|
||||||
EditorExport::get_singleton()->add_export_plugin(gd_export);
|
EditorExport::get_singleton()->add_export_plugin(gd_export);
|
||||||
|
|
||||||
|
#ifdef MODULE_EDITOR_CODE_EDITOR_ENABLED
|
||||||
|
Ref<CScriptSyntaxHighlighter> cscript_syntax_highlighter;
|
||||||
|
cscript_syntax_highlighter.instance();
|
||||||
|
EditorScriptEditor::get_singleton()->register_syntax_highlighter(cscript_syntax_highlighter);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
@ -160,9 +166,6 @@ void register_cscript_types(ModuleRegistrationLevel p_level) {
|
|||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (p_level == MODULE_REGISTRATION_LEVEL_EDITOR) {
|
if (p_level == MODULE_REGISTRATION_LEVEL_EDITOR) {
|
||||||
#ifdef MODULE_EDITOR_CODE_EDITOR_ENABLED
|
|
||||||
EditorScriptEditor::register_create_syntax_highlighter_function(CScriptSyntaxHighlighter::create);
|
|
||||||
#endif
|
|
||||||
EditorNode::add_init_callback(_editor_init);
|
EditorNode::add_init_callback(_editor_init);
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
@ -29,25 +29,15 @@
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "gdscript_highlighter.h"
|
#include "gdscript_highlighter.h"
|
||||||
|
#include "../gdscript.h"
|
||||||
#include "../gdscript_tokenizer.h"
|
#include "../gdscript_tokenizer.h"
|
||||||
|
#include "core/config/project_settings.h"
|
||||||
#include "editor/editor_settings.h"
|
#include "editor/editor_settings.h"
|
||||||
|
|
||||||
inline bool _is_symbol(CharType c) {
|
|
||||||
return is_symbol(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_text_char(CharType c) {
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_char(CharType c) {
|
static bool _is_char(CharType c) {
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _is_number(CharType c) {
|
|
||||||
return (c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_hex_symbol(CharType c) {
|
static bool _is_hex_symbol(CharType c) {
|
||||||
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||||
}
|
}
|
||||||
@ -81,36 +71,136 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
Color keyword_color;
|
Color keyword_color;
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
int in_region = text_edit->_is_line_in_region(p_line);
|
color_region_cache[p_line] = -1;
|
||||||
int deregion = 0;
|
int in_region = -1;
|
||||||
|
if (p_line != 0) {
|
||||||
|
if (!color_region_cache.has(p_line - 1)) {
|
||||||
|
get_line_syntax_highlighting(p_line - 1);
|
||||||
|
}
|
||||||
|
in_region = color_region_cache[p_line - 1];
|
||||||
|
}
|
||||||
|
|
||||||
const RBMap<int, TextEdit::Text::ColorRegionInfo> cri_map = text_edit->_get_line_color_region_info(p_line);
|
|
||||||
const String &str = text_edit->get_line(p_line);
|
const String &str = text_edit->get_line(p_line);
|
||||||
|
const int line_length = str.length();
|
||||||
Color prev_color;
|
Color prev_color;
|
||||||
for (int j = 0; j < str.length(); j++) {
|
for (int j = 0; j < str.length(); j++) {
|
||||||
Dictionary highlighter_info;
|
Dictionary highlighter_info;
|
||||||
|
|
||||||
if (deregion > 0) {
|
color = font_color;
|
||||||
deregion--;
|
bool is_char = !is_symbol(str[j]);
|
||||||
if (deregion == 0) {
|
bool is_a_symbol = is_symbol(str[j]);
|
||||||
in_region = -1;
|
bool is_number = (str[j] >= '0' && str[j] <= '9');
|
||||||
|
|
||||||
|
/* color regions */
|
||||||
|
if (is_a_symbol || in_region != -1) {
|
||||||
|
int from = j;
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deregion != 0) {
|
if (from != line_length) {
|
||||||
if (color != prev_color) {
|
/* check if we are in entering a region */
|
||||||
prev_color = color;
|
if (in_region == -1) {
|
||||||
highlighter_info["color"] = color;
|
for (int c = 0; c < color_regions.size(); c++) {
|
||||||
color_map[j] = highlighter_info;
|
/* check there is enough room */
|
||||||
}
|
int chars_left = line_length - from;
|
||||||
|
int start_key_length = color_regions[c].start_key.length();
|
||||||
|
int end_key_length = color_regions[c].end_key.length();
|
||||||
|
if (chars_left < start_key_length) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = font_color;
|
/* search the line */
|
||||||
|
bool match = true;
|
||||||
|
const CharType *start_key = color_regions[c].start_key.get_data();
|
||||||
|
for (int k = 0; k < start_key_length; k++) {
|
||||||
|
if (start_key[k] != str[from + k]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
in_region = c;
|
||||||
|
from += start_key_length;
|
||||||
|
|
||||||
bool is_char = _is_text_char(str[j]);
|
/* check if it's the whole line */
|
||||||
bool is_symbol = _is_symbol(str[j]);
|
if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) {
|
||||||
bool is_number = _is_number(str[j]);
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[c].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
j = line_length;
|
||||||
|
if (!color_regions[c].line_only) {
|
||||||
|
color_region_cache[p_line] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == line_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are in one find the end key */
|
||||||
|
if (in_region != -1) {
|
||||||
|
/* check there is enough room */
|
||||||
|
int chars_left = line_length - from;
|
||||||
|
int end_key_length = color_regions[in_region].end_key.length();
|
||||||
|
if (chars_left < end_key_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the line */
|
||||||
|
int region_end_index = -1;
|
||||||
|
const CharType *end_key = color_regions[in_region].start_key.get_data();
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (!is_a_symbol) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < end_key_length; k++) {
|
||||||
|
if (end_key[k] == str[from + k]) {
|
||||||
|
region_end_index = from;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (region_end_index != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[in_region].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
previous_type = REGION;
|
||||||
|
previous_text = "";
|
||||||
|
previous_column = j;
|
||||||
|
j = from;
|
||||||
|
if (region_end_index == -1) {
|
||||||
|
color_region_cache[p_line] = in_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_region = -1;
|
||||||
|
prev_is_char = false;
|
||||||
|
prev_is_number = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// allow ABCDEF in hex notation
|
// allow ABCDEF in hex notation
|
||||||
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
||||||
@ -132,7 +222,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
|
// check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation
|
||||||
if ((str[j] == '.' || str[j] == 'x' || str[j] == 'b' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
if ((str[j] == '.' || str[j] == 'x' || str[j] == 'b' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
||||||
is_number = true;
|
is_number = true;
|
||||||
is_symbol = false;
|
is_a_symbol = false;
|
||||||
is_char = false;
|
is_char = false;
|
||||||
|
|
||||||
if (str[j] == 'x' && str[j - 1] == '0') {
|
if (str[j] == 'x' && str[j - 1] == '0') {
|
||||||
@ -150,64 +240,46 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
is_number = false;
|
is_number = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && str[j] != '.' && in_word) {
|
if (is_a_symbol && str[j] != '.' && in_word) {
|
||||||
in_word = false;
|
in_word = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && cri_map.has(j)) {
|
|
||||||
const TextEdit::Text::ColorRegionInfo &cri = cri_map[j];
|
|
||||||
|
|
||||||
if (in_region == -1) {
|
|
||||||
if (!cri.end) {
|
|
||||||
in_region = cri.region;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TextEdit::ColorRegion cr = text_edit->_get_color_region(cri.region);
|
|
||||||
if (in_region == cri.region && !cr.line_only) { //ignore otherwise
|
|
||||||
if (cri.end || cr.eq) {
|
|
||||||
deregion = cr.eq ? cr.begin_key.length() : cr.end_key.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_char) {
|
if (!is_char) {
|
||||||
in_keyword = false;
|
in_keyword = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_region == -1 && !in_keyword && is_char && !prev_is_char) {
|
if (!in_keyword && is_char && !prev_is_char) {
|
||||||
int to = j;
|
int to = j;
|
||||||
while (to < str.length() && _is_text_char(str[to])) {
|
|
||||||
|
while (to < str.length() && !is_symbol(str[to])) {
|
||||||
to++;
|
to++;
|
||||||
}
|
}
|
||||||
|
|
||||||
String word = str.substr(j, to - j);
|
String word = str.substr(j, to - j);
|
||||||
Color col = Color();
|
Color col = Color();
|
||||||
if (text_edit->has_keyword_color(word)) {
|
if (keywords.has(word)) {
|
||||||
col = text_edit->get_keyword_color(word);
|
col = keywords[word];
|
||||||
} else if (text_edit->has_member_color(word)) {
|
} else if (member_keywords.has(word)) {
|
||||||
col = text_edit->get_member_color(word);
|
col = member_keywords[word];
|
||||||
}
|
|
||||||
|
|
||||||
if (col != Color()) {
|
|
||||||
for (int k = j - 1; k >= 0; k--) {
|
for (int k = j - 1; k >= 0; k--) {
|
||||||
if (str[k] == '.') {
|
if (str[k] == '.') {
|
||||||
col = Color(); // keyword & member indexing not allowed
|
col = Color(); //member indexing not allowed
|
||||||
break;
|
break;
|
||||||
} else if (str[k] > 32) {
|
} else if (str[k] > 32) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (col != Color()) {
|
if (col != Color()) {
|
||||||
in_keyword = true;
|
in_keyword = true;
|
||||||
keyword_color = col;
|
keyword_color = col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_function_name && in_word && !in_keyword) {
|
if (!in_function_name && in_word && !in_keyword) {
|
||||||
int k = j;
|
int k = j;
|
||||||
while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
while (k < str.length() && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +297,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
|
|
||||||
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
||||||
int k = j;
|
int k = j;
|
||||||
while (k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
while (k > 0 && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
k--;
|
k--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +306,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_symbol && in_region == -1) {
|
if (is_a_symbol) {
|
||||||
if (in_function_name) {
|
if (in_function_name) {
|
||||||
in_function_args = true;
|
in_function_args = true;
|
||||||
}
|
}
|
||||||
@ -271,14 +343,11 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
|
|
||||||
if (!in_node_path && in_region == -1 && str[j] == '$') {
|
if (!in_node_path && in_region == -1 && str[j] == '$') {
|
||||||
in_node_path = true;
|
in_node_path = true;
|
||||||
} else if (in_region != -1 || (is_symbol && str[j] != '/')) {
|
} else if (in_region != -1 || (is_a_symbol && str[j] != '/')) {
|
||||||
in_node_path = false;
|
in_node_path = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_region >= 0) {
|
if (in_node_path) {
|
||||||
next_type = REGION;
|
|
||||||
color = text_edit->_get_color_region(in_region).color;
|
|
||||||
} else if (in_node_path) {
|
|
||||||
next_type = NODE_PATH;
|
next_type = NODE_PATH;
|
||||||
color = node_path_color;
|
color = node_path_color;
|
||||||
} else if (in_keyword) {
|
} else if (in_keyword) {
|
||||||
@ -295,7 +364,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
|
|||||||
} else {
|
} else {
|
||||||
color = function_color;
|
color = function_color;
|
||||||
}
|
}
|
||||||
} else if (is_symbol) {
|
} else if (is_a_symbol) {
|
||||||
next_type = SYMBOL;
|
next_type = SYMBOL;
|
||||||
color = symbol_color;
|
color = symbol_color;
|
||||||
} else if (is_number) {
|
} else if (is_number) {
|
||||||
@ -354,11 +423,128 @@ Array GDScriptSyntaxHighlighter::_get_supported_languages() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GDScriptSyntaxHighlighter::_update_cache() {
|
void GDScriptSyntaxHighlighter::_update_cache() {
|
||||||
|
keywords.clear();
|
||||||
|
member_keywords.clear();
|
||||||
|
color_regions.clear();
|
||||||
|
color_region_cache.clear();
|
||||||
|
|
||||||
font_color = text_edit->get_theme_color("font_color");
|
font_color = text_edit->get_theme_color("font_color");
|
||||||
symbol_color = text_edit->get_theme_color("symbol_color");
|
symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
||||||
function_color = text_edit->get_theme_color("function_color");
|
function_color = EDITOR_GET("text_editor/highlighting/function_color");
|
||||||
number_color = text_edit->get_theme_color("number_color");
|
number_color = EDITOR_GET("text_editor/highlighting/number_color");
|
||||||
member_color = text_edit->get_theme_color("member_variable_color");
|
member_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
||||||
|
|
||||||
|
/* Engine types. */
|
||||||
|
const Color types_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
|
||||||
|
List<StringName> types;
|
||||||
|
ClassDB::get_class_list(&types);
|
||||||
|
for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
|
||||||
|
String n = E->get();
|
||||||
|
if (n.begins_with("_")) {
|
||||||
|
n = n.substr(1, n.length());
|
||||||
|
}
|
||||||
|
keywords[n] = types_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* User types. */
|
||||||
|
const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
|
||||||
|
List<StringName> global_classes;
|
||||||
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
|
||||||
|
keywords[String(E->get())] = usertype_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Autoloads. */
|
||||||
|
|
||||||
|
List<PropertyInfo> props;
|
||||||
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
||||||
|
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
const PropertyInfo &pi = E->get();
|
||||||
|
|
||||||
|
if (!pi.name.begins_with("autoload/")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = pi.name.get_slice("/", 1);
|
||||||
|
String path = ProjectSettings::get_singleton()->get(pi.name);
|
||||||
|
|
||||||
|
if (name.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_singleton = path.begins_with("*");
|
||||||
|
|
||||||
|
if (is_singleton) {
|
||||||
|
keywords[name] = usertype_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GDScriptLanguage *gdscript = GDScriptLanguage::get_singleton();
|
||||||
|
|
||||||
|
/* Core types. */
|
||||||
|
const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
||||||
|
List<String> core_types;
|
||||||
|
gdscript->get_core_type_words(&core_types);
|
||||||
|
for (List<String>::Element *E = core_types.front(); E; E = E->next()) {
|
||||||
|
keywords[E->get()] = basetype_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserved words. */
|
||||||
|
const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
||||||
|
List<String> keyword_list;
|
||||||
|
gdscript->get_reserved_words(&keyword_list);
|
||||||
|
for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
|
||||||
|
keywords[E->get()] = keyword_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comments */
|
||||||
|
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
||||||
|
List<String> comments;
|
||||||
|
gdscript->get_comment_delimiters(&comments);
|
||||||
|
for (List<String>::Element *E = comments.front(); E; E = E->next()) {
|
||||||
|
String comment = E->get();
|
||||||
|
String beg = comment.get_slice(" ", 0);
|
||||||
|
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
|
||||||
|
add_color_region(beg, end, comment_color, end == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strings */
|
||||||
|
const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
|
||||||
|
List<String> strings;
|
||||||
|
gdscript->get_string_delimiters(&strings);
|
||||||
|
for (List<String>::Element *E = strings.front(); E; E = E->next()) {
|
||||||
|
String string = E->get();
|
||||||
|
String beg = string.get_slice(" ", 0);
|
||||||
|
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
|
||||||
|
add_color_region(beg, end, string_color, end == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ref<Script> script = _get_edited_resource();
|
||||||
|
if (script.is_valid()) {
|
||||||
|
/* Member types. */
|
||||||
|
const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
|
||||||
|
StringName instance_base = script->get_instance_base_type();
|
||||||
|
if (instance_base != StringName()) {
|
||||||
|
List<PropertyInfo> plist;
|
||||||
|
ClassDB::get_property_list(instance_base, &plist);
|
||||||
|
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
|
||||||
|
String name = E->get().name;
|
||||||
|
if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (name.find("/") != -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
member_keywords[name] = member_variable_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> clist;
|
||||||
|
ClassDB::get_integer_constant_list(instance_base, &clist);
|
||||||
|
for (List<String>::Element *E = clist.front(); E; E = E->next()) {
|
||||||
|
member_keywords[E->get()] = member_variable_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
|
const String text_edit_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
|
||||||
const bool default_theme = text_edit_color_theme == "Default";
|
const bool default_theme = text_edit_color_theme == "Default";
|
||||||
@ -389,6 +575,31 @@ void GDScriptSyntaxHighlighter::_update_cache() {
|
|||||||
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxHighlighter *GDScriptSyntaxHighlighter::create() {
|
void GDScriptSyntaxHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
|
||||||
return memnew(GDScriptSyntaxHighlighter);
|
for (int i = 0; i < p_start_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "color regions must start with a symbol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_end_key.length() > 0) {
|
||||||
|
for (int i = 0; i < p_end_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_end_key[i]), "color regions must end with a symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "color region with start key '" + p_start_key + "' already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRegion color_region;
|
||||||
|
color_region.color = p_color;
|
||||||
|
color_region.start_key = p_start_key;
|
||||||
|
color_region.end_key = p_end_key;
|
||||||
|
color_region.line_only = p_line_only;
|
||||||
|
color_regions.push_back(color_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<EditorSyntaxHighlighter> GDScriptSyntaxHighlighter::_create() const {
|
||||||
|
Ref<GDScriptSyntaxHighlighter> syntax_highlighter;
|
||||||
|
syntax_highlighter.instance();
|
||||||
|
return syntax_highlighter;
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,25 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "editor_modules/editor_code_editor/editor_syntax_highlighter.h"
|
||||||
#include "scene/gui/text_edit.h"
|
#include "scene/gui/text_edit.h"
|
||||||
|
|
||||||
class GDScriptSyntaxHighlighter : public SyntaxHighlighter {
|
class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
|
||||||
|
GDCLASS(GDScriptSyntaxHighlighter, EditorSyntaxHighlighter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ColorRegion {
|
||||||
|
Color color;
|
||||||
|
String start_key;
|
||||||
|
String end_key;
|
||||||
|
bool line_only;
|
||||||
|
};
|
||||||
|
Vector<ColorRegion> color_regions;
|
||||||
|
RBMap<int, int> color_region_cache;
|
||||||
|
|
||||||
|
Dictionary keywords;
|
||||||
|
Dictionary member_keywords;
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
NONE,
|
NONE,
|
||||||
REGION,
|
REGION,
|
||||||
@ -58,8 +73,10 @@ private:
|
|||||||
Color node_path_color;
|
Color node_path_color;
|
||||||
Color type_color;
|
Color type_color;
|
||||||
|
|
||||||
|
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SyntaxHighlighter *create();
|
virtual Ref<EditorSyntaxHighlighter> _create() const;
|
||||||
|
|
||||||
virtual void _update_cache();
|
virtual void _update_cache();
|
||||||
virtual Dictionary _get_line_syntax_highlighting(int p_line);
|
virtual Dictionary _get_line_syntax_highlighting(int p_line);
|
||||||
|
@ -30,13 +30,13 @@
|
|||||||
|
|
||||||
#include "gdscript.h"
|
#include "gdscript.h"
|
||||||
|
|
||||||
#include "core/core_string_names.h"
|
|
||||||
#include "core/config/engine.h"
|
#include "core/config/engine.h"
|
||||||
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/core_string_names.h"
|
||||||
#include "core/global_constants.h"
|
#include "core/global_constants.h"
|
||||||
#include "core/io/file_access_encrypted.h"
|
#include "core/io/file_access_encrypted.h"
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/config/project_settings.h"
|
|
||||||
#include "gdscript_compiler.h"
|
#include "gdscript_compiler.h"
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
|
@ -138,6 +138,12 @@ static void _editor_init() {
|
|||||||
Ref<EditorExportGDScript> gd_export;
|
Ref<EditorExportGDScript> gd_export;
|
||||||
gd_export.instance();
|
gd_export.instance();
|
||||||
EditorExport::get_singleton()->add_export_plugin(gd_export);
|
EditorExport::get_singleton()->add_export_plugin(gd_export);
|
||||||
|
|
||||||
|
#ifdef MODULE_EDITOR_CODE_EDITOR_ENABLED
|
||||||
|
Ref<GDScriptSyntaxHighlighter> gdscript_syntax_highlighter;
|
||||||
|
gdscript_syntax_highlighter.instance();
|
||||||
|
EditorScriptEditor::get_singleton()->register_syntax_highlighter(gdscript_syntax_highlighter);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
@ -161,9 +167,6 @@ void register_gdscript_types(ModuleRegistrationLevel p_level) {
|
|||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (p_level == MODULE_REGISTRATION_LEVEL_EDITOR) {
|
if (p_level == MODULE_REGISTRATION_LEVEL_EDITOR) {
|
||||||
#ifdef MODULE_EDITOR_CODE_EDITOR_ENABLED
|
|
||||||
EditorScriptEditor::register_create_syntax_highlighter_function(GDScriptSyntaxHighlighter::create);
|
|
||||||
#endif
|
|
||||||
EditorNode::add_init_callback(_editor_init);
|
EditorNode::add_init_callback(_editor_init);
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
@ -265,7 +265,6 @@ WebNodeEditor::WebNodeEditor() {
|
|||||||
_results_label->set_v_size_flags(SIZE_EXPAND_FILL);
|
_results_label->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||||
_results_label->set_readonly(true);
|
_results_label->set_readonly(true);
|
||||||
_results_label->set_highlight_current_line(true);
|
_results_label->set_highlight_current_line(true);
|
||||||
_results_label->set_syntax_coloring(true);
|
|
||||||
_results_label->set_show_line_length_guidelines(true);
|
_results_label->set_show_line_length_guidelines(true);
|
||||||
_results_label->set_draw_fold_gutter(true);
|
_results_label->set_draw_fold_gutter(true);
|
||||||
_results_label->set_highlight_all_occurrences(true);
|
_results_label->set_highlight_all_occurrences(true);
|
||||||
@ -273,16 +272,21 @@ WebNodeEditor::WebNodeEditor() {
|
|||||||
_results_label->set_right_click_moves_caret(false);
|
_results_label->set_right_click_moves_caret(false);
|
||||||
_html_previewer->add_child(_results_label);
|
_html_previewer->add_child(_results_label);
|
||||||
|
|
||||||
|
Ref<CodeHighlighter> code_highlighter;
|
||||||
|
code_highlighter.instance();
|
||||||
|
|
||||||
//todo add all
|
//todo add all
|
||||||
_results_label->add_color_region("<b>", "</b>", Color::color8(153, 153, 255, 255), false);
|
code_highlighter->add_color_region("<b>", "</b>", Color::color8(153, 153, 255, 255), false);
|
||||||
_results_label->add_color_region("<i>", "</i>", Color::color8(153, 255, 153, 255), false);
|
code_highlighter->add_color_region("<i>", "</i>", Color::color8(153, 255, 153, 255), false);
|
||||||
_results_label->add_color_region("<del>", "</del>", Color::color8(255, 153, 153, 255), false);
|
code_highlighter->add_color_region("<del>", "</del>", Color::color8(255, 153, 153, 255), false);
|
||||||
_results_label->add_color_region("<ins>", "</ins>", Color::color8(255, 255, 102, 255), false);
|
code_highlighter->add_color_region("<ins>", "</ins>", Color::color8(255, 255, 102, 255), false);
|
||||||
_results_label->add_color_region("<a", "</a>", Color::color8(153, 204, 255, 255), false);
|
code_highlighter->add_color_region("<a", "</a>", Color::color8(153, 204, 255, 255), false);
|
||||||
_results_label->add_color_region("<img", "/>", Color::color8(255, 204, 153, 255), true);
|
code_highlighter->add_color_region("<img", "/>", Color::color8(255, 204, 153, 255), true);
|
||||||
_results_label->add_color_region("<pre>", "</pre>", Color::color8(192, 192, 192, 255), false);
|
code_highlighter->add_color_region("<pre>", "</pre>", Color::color8(192, 192, 192, 255), false);
|
||||||
_results_label->add_color_region("<center>", "</center>", Color::color8(175, 238, 238, 255), false);
|
code_highlighter->add_color_region("<center>", "</center>", Color::color8(175, 238, 238, 255), false);
|
||||||
_results_label->add_color_region("<right>", "</right>", Color::color8(135, 206, 235, 255), false);
|
code_highlighter->add_color_region("<right>", "</right>", Color::color8(135, 206, 235, 255), false);
|
||||||
|
|
||||||
|
_results_label->set_syntax_highlighter(code_highlighter);
|
||||||
|
|
||||||
_main_button_group.instance();
|
_main_button_group.instance();
|
||||||
|
|
||||||
|
@ -65,14 +65,6 @@ static bool _is_char(CharType c) {
|
|||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _is_number(CharType c) {
|
|
||||||
return (c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_hex_symbol(CharType c) {
|
|
||||||
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _is_pair_right_symbol(CharType c) {
|
static bool _is_pair_right_symbol(CharType c) {
|
||||||
return c == '"' ||
|
return c == '"' ||
|
||||||
c == '\'' ||
|
c == '\'' ||
|
||||||
@ -141,94 +133,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
text.write[p_line].width_cache = w;
|
text.write[p_line].width_cache = w;
|
||||||
|
|
||||||
text.write[p_line].wrap_amount_cache = -1;
|
text.write[p_line].wrap_amount_cache = -1;
|
||||||
|
|
||||||
// Update regions.
|
|
||||||
|
|
||||||
text.write[p_line].region_info.clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (!_is_symbol(str[i])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (str[i] == '\\') {
|
|
||||||
i++; // Skip quoted anything.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int left = len - i;
|
|
||||||
|
|
||||||
for (int j = 0; j < color_regions->size(); j++) {
|
|
||||||
const ColorRegion &cr = color_regions->operator[](j);
|
|
||||||
|
|
||||||
/* BEGIN */
|
|
||||||
|
|
||||||
int lr = cr.begin_key.length();
|
|
||||||
const CharType *kc;
|
|
||||||
bool match;
|
|
||||||
|
|
||||||
if (lr != 0 && lr <= left) {
|
|
||||||
kc = cr.begin_key.get_data();
|
|
||||||
|
|
||||||
match = true;
|
|
||||||
|
|
||||||
for (int k = 0; k < lr; k++) {
|
|
||||||
if (kc[k] != str[i + k]) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
ColorRegionInfo cri;
|
|
||||||
cri.end = false;
|
|
||||||
cri.region = j;
|
|
||||||
text.write[p_line].region_info[i] = cri;
|
|
||||||
i += lr - 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* END */
|
|
||||||
|
|
||||||
lr = cr.end_key.length();
|
|
||||||
if (lr != 0 && lr <= left) {
|
|
||||||
kc = cr.end_key.get_data();
|
|
||||||
|
|
||||||
match = true;
|
|
||||||
|
|
||||||
for (int k = 0; k < lr; k++) {
|
|
||||||
if (kc[k] != str[i + k]) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
ColorRegionInfo cri;
|
|
||||||
cri.end = true;
|
|
||||||
cri.region = j;
|
|
||||||
text.write[p_line].region_info[i] = cri;
|
|
||||||
i += lr - 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const RBMap<int, TextEdit::Text::ColorRegionInfo> &TextEdit::Text::get_color_region_info(int p_line) const {
|
|
||||||
static RBMap<int, ColorRegionInfo> cri;
|
|
||||||
ERR_FAIL_INDEX_V(p_line, text.size(), cri);
|
|
||||||
|
|
||||||
if (text[p_line].width_cache == -1) {
|
|
||||||
_update_line_cache(p_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text[p_line].region_info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextEdit::Text::get_line_width(int p_line) const {
|
int TextEdit::Text::get_line_width(int p_line) const {
|
||||||
@ -637,7 +542,6 @@ void TextEdit::_notification(int p_what) {
|
|||||||
case NOTIFICATION_THEME_CHANGED: {
|
case NOTIFICATION_THEME_CHANGED: {
|
||||||
_update_caches();
|
_update_caches();
|
||||||
_update_wrap_at();
|
_update_wrap_at();
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
} break;
|
} break;
|
||||||
case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
|
case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
|
||||||
window_has_focus = true;
|
window_has_focus = true;
|
||||||
@ -676,6 +580,14 @@ void TextEdit::_notification(int p_what) {
|
|||||||
adjust_viewport_to_cursor();
|
adjust_viewport_to_cursor();
|
||||||
first_draw = false;
|
first_draw = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prevent the resource getting lost between the editor and game. */
|
||||||
|
if (Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
if (syntax_highlighter.is_valid() && syntax_highlighter->get_text_edit() != this) {
|
||||||
|
syntax_highlighter->set_text_edit(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Size2 size = get_size();
|
Size2 size = get_size();
|
||||||
if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
|
if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
|
||||||
draw_caret = false;
|
draw_caret = false;
|
||||||
@ -747,11 +659,9 @@ void TextEdit::_notification(int p_what) {
|
|||||||
|
|
||||||
Color color = readonly ? cache.font_color_readonly : cache.font_color;
|
Color color = readonly ? cache.font_color_readonly : cache.font_color;
|
||||||
|
|
||||||
if (syntax_coloring) {
|
|
||||||
if (cache.background_color.a > 0.01) {
|
if (cache.background_color.a > 0.01) {
|
||||||
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
|
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (line_length_guidelines) {
|
if (line_length_guidelines) {
|
||||||
const int hard_x = xmargin_beg + (int)cache.font->get_char_size('0').width * line_length_guideline_hard_col - cursor.x_ofs;
|
const int hard_x = xmargin_beg + (int)cache.font->get_char_size('0').width * line_length_guideline_hard_col - cursor.x_ofs;
|
||||||
@ -985,10 +895,7 @@ void TextEdit::_notification(int p_what) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary color_map;
|
Dictionary color_map = _get_line_syntax_highlighting(minimap_line);
|
||||||
if (syntax_coloring) {
|
|
||||||
color_map = _get_line_syntax_highlighting(minimap_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color current_color = cache.font_color;
|
Color current_color = cache.font_color;
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
@ -1026,15 +933,14 @@ void TextEdit::_notification(int p_what) {
|
|||||||
int characters = 0;
|
int characters = 0;
|
||||||
int tabs = 0;
|
int tabs = 0;
|
||||||
for (int j = 0; j < str.length(); j++) {
|
for (int j = 0; j < str.length(); j++) {
|
||||||
if (syntax_coloring) {
|
|
||||||
if (color_map.has(last_wrap_column + j)) {
|
if (color_map.has(last_wrap_column + j)) {
|
||||||
current_color = color_map[last_wrap_column + j].get("color");
|
current_color = color_map[last_wrap_column + j].get("color");
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
current_color.a = cache.font_color_readonly.a;
|
current_color.a = cache.font_color_readonly.a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color = current_color;
|
color = current_color;
|
||||||
}
|
|
||||||
|
|
||||||
if (j == 0) {
|
if (j == 0) {
|
||||||
previous_color = color;
|
previous_color = color;
|
||||||
@ -1125,10 +1031,8 @@ void TextEdit::_notification(int p_what) {
|
|||||||
const String &fullstr = text[line];
|
const String &fullstr = text[line];
|
||||||
LineDrawingCache cache_entry;
|
LineDrawingCache cache_entry;
|
||||||
|
|
||||||
Dictionary color_map;
|
Dictionary color_map = _get_line_syntax_highlighting(line);
|
||||||
if (syntax_coloring) {
|
|
||||||
color_map = _get_line_syntax_highlighting(line);
|
|
||||||
}
|
|
||||||
// Ensure we at least use the font color.
|
// Ensure we at least use the font color.
|
||||||
Color current_color = readonly ? cache.font_color_readonly : cache.font_color;
|
Color current_color = readonly ? cache.font_color_readonly : cache.font_color;
|
||||||
|
|
||||||
@ -1340,7 +1244,6 @@ void TextEdit::_notification(int p_what) {
|
|||||||
// Loop through characters in one line.
|
// Loop through characters in one line.
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (; j < str.length(); j++) {
|
for (; j < str.length(); j++) {
|
||||||
if (syntax_coloring) {
|
|
||||||
if (color_map.has(last_wrap_column + j)) {
|
if (color_map.has(last_wrap_column + j)) {
|
||||||
current_color = color_map[last_wrap_column + j].get("color");
|
current_color = color_map[last_wrap_column + j].get("color");
|
||||||
if (readonly && current_color.a > cache.font_color_readonly.a) {
|
if (readonly && current_color.a > cache.font_color_readonly.a) {
|
||||||
@ -1348,7 +1251,6 @@ void TextEdit::_notification(int p_what) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
color = current_color;
|
color = current_color;
|
||||||
}
|
|
||||||
|
|
||||||
int char_w;
|
int char_w;
|
||||||
|
|
||||||
@ -1536,7 +1438,7 @@ void TextEdit::_notification(int p_what) {
|
|||||||
if (!clipped) {
|
if (!clipped) {
|
||||||
if (cursor.column == last_wrap_column + j && cursor.line == line && cursor_wrap_index == line_wrap_index && block_caret && draw_caret && !insert_mode) {
|
if (cursor.column == last_wrap_column + j && cursor.line == line && cursor_wrap_index == line_wrap_index && block_caret && draw_caret && !insert_mode) {
|
||||||
color = cache.caret_background_color;
|
color = cache.caret_background_color;
|
||||||
} else if (!syntax_coloring && block_caret) {
|
} else if (block_caret) {
|
||||||
color = readonly ? cache.font_color_readonly : cache.font_color;
|
color = readonly ? cache.font_color_readonly : cache.font_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1733,12 +1635,6 @@ void TextEdit::_notification(int p_what) {
|
|||||||
for (int i = 0; i < row_count; i++) {
|
for (int i = 0; i < row_count; i++) {
|
||||||
int l = line_from + i;
|
int l = line_from + i;
|
||||||
ERR_CONTINUE(l < 0 || l >= completion_options_size);
|
ERR_CONTINUE(l < 0 || l >= completion_options_size);
|
||||||
Color text_color = cache.completion_font_color;
|
|
||||||
for (int j = 0; j < color_regions.size(); j++) {
|
|
||||||
if (completion_options[l].insert_text.begins_with(color_regions[j].begin_key)) {
|
|
||||||
text_color = color_regions[j].color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int yofs = (get_row_height() - cache.font->get_height()) / 2;
|
int yofs = (get_row_height() - cache.font->get_height()) / 2;
|
||||||
Point2 title_pos(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent() + yofs);
|
Point2 title_pos(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent() + yofs);
|
||||||
|
|
||||||
@ -1759,7 +1655,7 @@ void TextEdit::_notification(int p_what) {
|
|||||||
draw_rect(Rect2(Point2(completion_rect.position.x + completion_rect.size.width - icon_area_size.x, icon_area.position.y), icon_area_size), (Color)completion_options[l].default_value);
|
draw_rect(Rect2(Point2(completion_rect.position.x + completion_rect.size.width - icon_area_size.x, icon_area.position.y), icon_area_size), (Color)completion_options[l].default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_string(cache.font, title_pos, completion_options[l].display, text_color, completion_rect.size.width - (icon_area_size.x + icon_hsep));
|
draw_string(cache.font, title_pos, completion_options[l].display, completion_options[l].font_color, completion_rect.size.width - (icon_area_size.x + icon_hsep));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scroll_rectangle_width) {
|
if (scroll_rectangle_width) {
|
||||||
@ -3096,7 +2992,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||||||
// Indent once again if previous line will end with ':','{','[','(' and the line is not a comment
|
// Indent once again if previous line will end with ':','{','[','(' and the line is not a comment
|
||||||
// (i.e. colon/brace precedes current cursor position).
|
// (i.e. colon/brace precedes current cursor position).
|
||||||
if (cursor.column > 0) {
|
if (cursor.column > 0) {
|
||||||
const RBMap<int, Text::ColorRegionInfo> &cri_map = text.get_color_region_info(cursor.line);
|
|
||||||
bool indent_char_found = false;
|
bool indent_char_found = false;
|
||||||
bool should_indent = false;
|
bool should_indent = false;
|
||||||
char indent_char = ':';
|
char indent_char = ':';
|
||||||
@ -3115,7 +3010,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indent_char_found && cri_map.has(i) && (color_regions[cri_map[i].region].begin_key == "#" || color_regions[cri_map[i].region].begin_key == "//")) {
|
if (indent_char_found && is_line_comment(i)) {
|
||||||
should_indent = true;
|
should_indent = true;
|
||||||
break;
|
break;
|
||||||
} else if (indent_char_found && !_is_whitespace(c)) {
|
} else if (indent_char_found && !_is_whitespace(c)) {
|
||||||
@ -4209,7 +4104,8 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
|
|||||||
}
|
}
|
||||||
text_changed_dirty = true;
|
text_changed_dirty = true;
|
||||||
}
|
}
|
||||||
_line_edited_from(p_line);
|
|
||||||
|
emit_signal("line_edited_from", p_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
String TextEdit::_base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const {
|
String TextEdit::_base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const {
|
||||||
@ -4272,7 +4168,8 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li
|
|||||||
}
|
}
|
||||||
text_changed_dirty = true;
|
text_changed_dirty = true;
|
||||||
}
|
}
|
||||||
_line_edited_from(p_from_line);
|
|
||||||
|
emit_signal("line_edited_from", p_from_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_char) {
|
void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_char) {
|
||||||
@ -4392,22 +4289,6 @@ void TextEdit::_insert_text_at_cursor(const String &p_text) {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::_line_edited_from(int p_line) {
|
|
||||||
int cache_size = color_region_cache.size();
|
|
||||||
for (int i = p_line; i < cache_size; i++) {
|
|
||||||
color_region_cache.erase(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syntax_highlighting_cache.size() > 0) {
|
|
||||||
cache_size = syntax_highlighting_cache.back()->key();
|
|
||||||
for (int i = p_line - 1; i <= cache_size; i++) {
|
|
||||||
if (syntax_highlighting_cache.has(i)) {
|
|
||||||
syntax_highlighting_cache.erase(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int TextEdit::get_char_count() {
|
int TextEdit::get_char_count() {
|
||||||
int totalsize = 0;
|
int totalsize = 0;
|
||||||
|
|
||||||
@ -5395,11 +5276,7 @@ void TextEdit::_update_caches() {
|
|||||||
cache.font_color = get_theme_color("font_color");
|
cache.font_color = get_theme_color("font_color");
|
||||||
cache.font_color_selected = get_theme_color("font_color_selected");
|
cache.font_color_selected = get_theme_color("font_color_selected");
|
||||||
cache.font_color_readonly = get_theme_color("font_color_readonly");
|
cache.font_color_readonly = get_theme_color("font_color_readonly");
|
||||||
cache.keyword_color = get_theme_color("keyword_color");
|
|
||||||
cache.control_flow_keyword_color = get_theme_color("control_flow_keyword_color");
|
cache.control_flow_keyword_color = get_theme_color("control_flow_keyword_color");
|
||||||
cache.function_color = get_theme_color("function_color");
|
|
||||||
cache.member_variable_color = get_theme_color("member_variable_color");
|
|
||||||
cache.number_color = get_theme_color("number_color");
|
|
||||||
cache.selection_color = get_theme_color("selection_color");
|
cache.selection_color = get_theme_color("selection_color");
|
||||||
cache.mark_color = get_theme_color("mark_color");
|
cache.mark_color = get_theme_color("mark_color");
|
||||||
cache.current_line_color = get_theme_color("current_line_color");
|
cache.current_line_color = get_theme_color("current_line_color");
|
||||||
@ -5412,7 +5289,6 @@ void TextEdit::_update_caches() {
|
|||||||
cache.word_highlighted_color = get_theme_color("word_highlighted_color");
|
cache.word_highlighted_color = get_theme_color("word_highlighted_color");
|
||||||
cache.search_result_color = get_theme_color("search_result_color");
|
cache.search_result_color = get_theme_color("search_result_color");
|
||||||
cache.search_result_border_color = get_theme_color("search_result_border_color");
|
cache.search_result_border_color = get_theme_color("search_result_border_color");
|
||||||
cache.symbol_color = get_theme_color("symbol_color");
|
|
||||||
cache.background_color = get_theme_color("background_color");
|
cache.background_color = get_theme_color("background_color");
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
cache.line_spacing = get_theme_constant("line_spacing") * EDSCALE;
|
cache.line_spacing = get_theme_constant("line_spacing") * EDSCALE;
|
||||||
@ -5429,140 +5305,28 @@ void TextEdit::_update_caches() {
|
|||||||
text.set_font(cache.font);
|
text.set_font(cache.font);
|
||||||
|
|
||||||
if (syntax_highlighter.is_valid()) {
|
if (syntax_highlighter.is_valid()) {
|
||||||
syntax_highlighter->update_cache();
|
syntax_highlighter->set_text_edit(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighting() {
|
Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighter() {
|
||||||
return syntax_highlighter;
|
return syntax_highlighter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::set_syntax_highlighting(Ref<SyntaxHighlighter> p_syntax_highlighter) {
|
void TextEdit::set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter) {
|
||||||
syntax_highlighter = p_syntax_highlighter;
|
syntax_highlighter = p_syntax_highlighter;
|
||||||
if (syntax_highlighter.is_valid()) {
|
if (syntax_highlighter.is_valid()) {
|
||||||
syntax_highlighter->set_text_edit(this);
|
syntax_highlighter->set_text_edit(this);
|
||||||
syntax_highlighter->update_cache();
|
|
||||||
}
|
}
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextEdit::_is_line_in_region(int p_line) {
|
void TextEdit::add_keyword(const String &p_keyword) {
|
||||||
// Do we have in cache?
|
keywords.insert(p_keyword);
|
||||||
if (color_region_cache.has(p_line)) {
|
|
||||||
return color_region_cache[p_line];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not find the closest line we have.
|
void TextEdit::clear_keywords() {
|
||||||
int previous_line = p_line - 1;
|
|
||||||
for (; previous_line > -1; previous_line--) {
|
|
||||||
if (color_region_cache.has(p_line)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate up to line we need and update the cache along the way.
|
|
||||||
int in_region = color_region_cache[previous_line];
|
|
||||||
if (previous_line == -1) {
|
|
||||||
in_region = -1;
|
|
||||||
}
|
|
||||||
for (int i = previous_line; i < p_line; i++) {
|
|
||||||
const RBMap<int, Text::ColorRegionInfo> &cri_map = _get_line_color_region_info(i);
|
|
||||||
for (const RBMap<int, Text::ColorRegionInfo>::Element *E = cri_map.front(); E; E = E->next()) {
|
|
||||||
const Text::ColorRegionInfo &cri = E->get();
|
|
||||||
if (in_region == -1) {
|
|
||||||
if (!cri.end) {
|
|
||||||
in_region = cri.region;
|
|
||||||
}
|
|
||||||
} else if (in_region == cri.region && !_get_color_region(cri.region).line_only) {
|
|
||||||
if (cri.end || _get_color_region(cri.region).eq) {
|
|
||||||
in_region = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_region >= 0 && _get_color_region(in_region).line_only) {
|
|
||||||
in_region = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
color_region_cache[i + 1] = in_region;
|
|
||||||
}
|
|
||||||
return in_region;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEdit::ColorRegion TextEdit::_get_color_region(int p_region) const {
|
|
||||||
if (p_region < 0 || p_region >= color_regions.size()) {
|
|
||||||
return ColorRegion();
|
|
||||||
}
|
|
||||||
return color_regions[p_region];
|
|
||||||
}
|
|
||||||
|
|
||||||
RBMap<int, TextEdit::Text::ColorRegionInfo> TextEdit::_get_line_color_region_info(int p_line) const {
|
|
||||||
if (p_line < 0 || p_line > text.size() - 1) {
|
|
||||||
return RBMap<int, Text::ColorRegionInfo>();
|
|
||||||
}
|
|
||||||
return text.get_color_region_info(p_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::clear_colors() {
|
|
||||||
keywords.clear();
|
keywords.clear();
|
||||||
member_keywords.clear();
|
|
||||||
color_regions.clear();
|
|
||||||
color_region_cache.clear();
|
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
text.clear_width_cache();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::add_keyword_color(const String &p_keyword, const Color &p_color) {
|
|
||||||
keywords[p_keyword] = p_color;
|
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextEdit::has_keyword_color(String p_keyword) const {
|
|
||||||
return keywords.has(p_keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color TextEdit::get_keyword_color(String p_keyword) const {
|
|
||||||
ERR_FAIL_COND_V(!keywords.has(p_keyword), Color());
|
|
||||||
return keywords[p_keyword];
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::add_color_region(const String &p_begin_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
|
|
||||||
color_regions.push_back(ColorRegion(p_begin_key, p_end_key, p_color, p_line_only));
|
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
text.clear_width_cache();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::add_member_keyword(const String &p_keyword, const Color &p_color) {
|
|
||||||
member_keywords[p_keyword] = p_color;
|
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextEdit::has_member_color(String p_member) const {
|
|
||||||
return member_keywords.has(p_member);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color TextEdit::get_member_color(String p_member) const {
|
|
||||||
return member_keywords[p_member];
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::clear_member_keywords() {
|
|
||||||
member_keywords.clear();
|
|
||||||
syntax_highlighting_cache.clear();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextEdit::set_syntax_coloring(bool p_enabled) {
|
|
||||||
syntax_coloring = p_enabled;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextEdit::is_syntax_coloring_enabled() const {
|
|
||||||
return syntax_coloring;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEdit::set_auto_indent(bool p_auto_indent) {
|
void TextEdit::set_auto_indent(bool p_auto_indent) {
|
||||||
@ -6233,18 +5997,19 @@ bool TextEdit::is_line_comment(int p_line) const {
|
|||||||
// Checks to see if this line is the start of a comment.
|
// Checks to see if this line is the start of a comment.
|
||||||
ERR_FAIL_INDEX_V(p_line, text.size(), false);
|
ERR_FAIL_INDEX_V(p_line, text.size(), false);
|
||||||
|
|
||||||
const RBMap<int, Text::ColorRegionInfo> &cri_map = text.get_color_region_info(p_line);
|
|
||||||
|
|
||||||
int line_length = text[p_line].size();
|
int line_length = text[p_line].size();
|
||||||
for (int i = 0; i < line_length - 1; i++) {
|
for (int i = 0; i < line_length - 1; i++) {
|
||||||
if (_is_symbol(text[p_line][i]) && cri_map.has(i)) {
|
if (_is_whitespace(text[p_line][i])) {
|
||||||
const Text::ColorRegionInfo &cri = cri_map[i];
|
|
||||||
return color_regions[cri.region].begin_key == "#" || color_regions[cri.region].begin_key == "//";
|
|
||||||
} else if (_is_whitespace(text[p_line][i])) {
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (_is_symbol(text[p_line][i])) {
|
||||||
|
if (text[p_line][i] == '\\') {
|
||||||
|
i++; // Skip quoted anything.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return text[p_line][i] == '#' || (i + 1 < line_length && text[p_line][i] == '/' && text[p_line][i + 1] == '/');
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -7524,11 +7289,8 @@ void TextEdit::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color);
|
ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color);
|
||||||
ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color);
|
ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_syntax_coloring", "enable"), &TextEdit::set_syntax_coloring);
|
ClassDB::bind_method(D_METHOD("set_syntax_highlighter", "syntax_highlighter"), &TextEdit::set_syntax_highlighter);
|
||||||
ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"), &TextEdit::is_syntax_coloring_enabled);
|
ClassDB::bind_method(D_METHOD("get_syntax_highlighter"), &TextEdit::get_syntax_highlighter);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_syntax_highlighting", "syntax_highlighter"), &TextEdit::set_syntax_highlighting);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_syntax_highlighting"), &TextEdit::get_syntax_highlighting);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
|
ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line);
|
||||||
ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
|
ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled);
|
||||||
@ -7542,11 +7304,6 @@ void TextEdit::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &TextEdit::set_h_scroll);
|
ClassDB::bind_method(D_METHOD("set_h_scroll", "value"), &TextEdit::set_h_scroll);
|
||||||
ClassDB::bind_method(D_METHOD("get_h_scroll"), &TextEdit::get_h_scroll);
|
ClassDB::bind_method(D_METHOD("get_h_scroll"), &TextEdit::get_h_scroll);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color);
|
|
||||||
ClassDB::bind_method(D_METHOD("has_keyword_color", "keyword"), &TextEdit::has_keyword_color);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_keyword_color", "keyword"), &TextEdit::get_keyword_color);
|
|
||||||
ClassDB::bind_method(D_METHOD("add_color_region", "begin_key", "end_key", "color", "line_only"), &TextEdit::add_color_region, DEFVAL(false));
|
|
||||||
ClassDB::bind_method(D_METHOD("clear_colors"), &TextEdit::clear_colors);
|
|
||||||
ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
|
ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
|
||||||
ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
|
ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
|
||||||
|
|
||||||
@ -7561,8 +7318,6 @@ void TextEdit::_bind_methods() {
|
|||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "syntax_highlighter", PROPERTY_HINT_RESOURCE_TYPE, "SyntaxHighlighter"), "set_syntax_highlighting", "get_syntax_highlighting");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces");
|
||||||
@ -7584,6 +7339,8 @@ void TextEdit::_bind_methods() {
|
|||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "scroll_vertical"), "set_v_scroll", "get_v_scroll");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal"), "set_h_scroll", "get_h_scroll");
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "syntax_highlighter", PROPERTY_HINT_RESOURCE_TYPE, "SyntaxHighlighter", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_syntax_highlighter", "get_syntax_highlighter");
|
||||||
|
|
||||||
ADD_GROUP("Minimap", "minimap_");
|
ADD_GROUP("Minimap", "minimap_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "draw_minimap", "is_drawing_minimap");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "draw_minimap", "is_drawing_minimap");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width"), "set_minimap_width", "get_minimap_width");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "minimap_width"), "set_minimap_width", "get_minimap_width");
|
||||||
@ -7596,6 +7353,7 @@ void TextEdit::_bind_methods() {
|
|||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("cursor_changed"));
|
ADD_SIGNAL(MethodInfo("cursor_changed"));
|
||||||
ADD_SIGNAL(MethodInfo("text_changed"));
|
ADD_SIGNAL(MethodInfo("text_changed"));
|
||||||
|
ADD_SIGNAL(MethodInfo("line_edited_from", PropertyInfo(Variant::INT, "line")));
|
||||||
ADD_SIGNAL(MethodInfo("request_completion"));
|
ADD_SIGNAL(MethodInfo("request_completion"));
|
||||||
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "row")));
|
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "row")));
|
||||||
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
|
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
|
||||||
@ -7645,7 +7403,6 @@ TextEdit::TextEdit() {
|
|||||||
indent_size = 4;
|
indent_size = 4;
|
||||||
text.set_indent_size(indent_size);
|
text.set_indent_size(indent_size);
|
||||||
text.clear();
|
text.clear();
|
||||||
text.set_color_regions(&color_regions);
|
|
||||||
|
|
||||||
h_scroll = memnew(HScrollBar);
|
h_scroll = memnew(HScrollBar);
|
||||||
v_scroll = memnew(VScrollBar);
|
v_scroll = memnew(VScrollBar);
|
||||||
@ -7669,7 +7426,6 @@ TextEdit::TextEdit() {
|
|||||||
selection.selecting_column = 0;
|
selection.selecting_column = 0;
|
||||||
selection.selecting_text = false;
|
selection.selecting_text = false;
|
||||||
selection.active = false;
|
selection.active = false;
|
||||||
syntax_coloring = false;
|
|
||||||
|
|
||||||
block_caret = false;
|
block_caret = false;
|
||||||
caret_blink_enabled = false;
|
caret_blink_enabled = false;
|
||||||
@ -7765,195 +7521,5 @@ TextEdit::~TextEdit() {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Dictionary TextEdit::_get_line_syntax_highlighting(int p_line) {
|
Dictionary TextEdit::_get_line_syntax_highlighting(int p_line) {
|
||||||
if (syntax_highlighting_cache.has(p_line)) {
|
return syntax_highlighter.is_null() && !setting_text ? Dictionary() : syntax_highlighter->get_line_syntax_highlighting(p_line);
|
||||||
return syntax_highlighting_cache[p_line];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syntax_highlighter.is_valid()) {
|
|
||||||
Dictionary color_map = syntax_highlighter->get_line_syntax_highlighting(p_line);
|
|
||||||
syntax_highlighting_cache[p_line] = color_map;
|
|
||||||
return color_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary color_map;
|
|
||||||
|
|
||||||
bool prev_is_char = false;
|
|
||||||
bool prev_is_number = false;
|
|
||||||
bool in_keyword = false;
|
|
||||||
bool in_word = false;
|
|
||||||
bool in_function_name = false;
|
|
||||||
bool in_member_variable = false;
|
|
||||||
bool is_hex_notation = false;
|
|
||||||
Color keyword_color;
|
|
||||||
Color color;
|
|
||||||
|
|
||||||
int in_region = _is_line_in_region(p_line);
|
|
||||||
int deregion = 0;
|
|
||||||
|
|
||||||
const RBMap<int, TextEdit::Text::ColorRegionInfo> cri_map = text.get_color_region_info(p_line);
|
|
||||||
const String &str = text[p_line];
|
|
||||||
Color prev_color;
|
|
||||||
for (int j = 0; j < str.length(); j++) {
|
|
||||||
Dictionary highlighter_info;
|
|
||||||
|
|
||||||
if (deregion > 0) {
|
|
||||||
deregion--;
|
|
||||||
if (deregion == 0) {
|
|
||||||
in_region = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deregion != 0) {
|
|
||||||
if (color != prev_color) {
|
|
||||||
prev_color = color;
|
|
||||||
highlighter_info["color"] = color;
|
|
||||||
color_map[j] = highlighter_info;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
color = cache.font_color;
|
|
||||||
|
|
||||||
bool is_char = _is_text_char(str[j]);
|
|
||||||
bool is_symbol = _is_symbol(str[j]);
|
|
||||||
bool is_number = _is_number(str[j]);
|
|
||||||
|
|
||||||
// Allow ABCDEF in hex notation.
|
|
||||||
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
|
||||||
is_number = true;
|
|
||||||
} else {
|
|
||||||
is_hex_notation = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation.
|
|
||||||
if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
|
||||||
is_number = true;
|
|
||||||
is_symbol = false;
|
|
||||||
is_char = false;
|
|
||||||
|
|
||||||
if (str[j] == 'x' && str[j - 1] == '0') {
|
|
||||||
is_hex_notation = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_word && _is_char(str[j]) && !is_number) {
|
|
||||||
in_word = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((in_keyword || in_word) && !is_hex_notation) {
|
|
||||||
is_number = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_symbol && str[j] != '.' && in_word) {
|
|
||||||
in_word = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_symbol && cri_map.has(j)) {
|
|
||||||
const TextEdit::Text::ColorRegionInfo &cri = cri_map[j];
|
|
||||||
|
|
||||||
if (in_region == -1) {
|
|
||||||
if (!cri.end) {
|
|
||||||
in_region = cri.region;
|
|
||||||
}
|
|
||||||
} else if (in_region == cri.region && !color_regions[cri.region].line_only) { // Ignore otherwise.
|
|
||||||
if (cri.end || color_regions[cri.region].eq) {
|
|
||||||
deregion = color_regions[cri.region].eq ? color_regions[cri.region].begin_key.length() : color_regions[cri.region].end_key.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_char) {
|
|
||||||
in_keyword = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_region == -1 && !in_keyword && is_char && !prev_is_char) {
|
|
||||||
int to = j;
|
|
||||||
while (to < str.length() && _is_text_char(str[to])) {
|
|
||||||
to++;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t hash = String::hash(&str[j], to - j);
|
|
||||||
StrRange range(&str[j], to - j);
|
|
||||||
|
|
||||||
const Color *col = keywords.custom_getptr(range, hash);
|
|
||||||
|
|
||||||
if (!col) {
|
|
||||||
col = member_keywords.custom_getptr(range, hash);
|
|
||||||
|
|
||||||
if (col) {
|
|
||||||
for (int k = j - 1; k >= 0; k--) {
|
|
||||||
if (str[k] == '.') {
|
|
||||||
col = nullptr; // Member indexing not allowed.
|
|
||||||
break;
|
|
||||||
} else if (str[k] > 32) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (col) {
|
|
||||||
in_keyword = true;
|
|
||||||
keyword_color = *col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_function_name && in_word && !in_keyword) {
|
|
||||||
int k = j;
|
|
||||||
while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for space between name and bracket.
|
|
||||||
while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str[k] == '(') {
|
|
||||||
in_function_name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
|
||||||
int k = j;
|
|
||||||
while (k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str[k] == '.') {
|
|
||||||
in_member_variable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_symbol) {
|
|
||||||
in_function_name = false;
|
|
||||||
in_member_variable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_region >= 0) {
|
|
||||||
color = color_regions[in_region].color;
|
|
||||||
} else if (in_keyword) {
|
|
||||||
color = keyword_color;
|
|
||||||
} else if (in_member_variable) {
|
|
||||||
color = cache.member_variable_color;
|
|
||||||
} else if (in_function_name) {
|
|
||||||
color = cache.function_color;
|
|
||||||
} else if (is_symbol) {
|
|
||||||
color = cache.symbol_color;
|
|
||||||
} else if (is_number) {
|
|
||||||
color = cache.number_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_is_char = is_char;
|
|
||||||
prev_is_number = is_number;
|
|
||||||
|
|
||||||
if (color != prev_color) {
|
|
||||||
prev_color = color;
|
|
||||||
highlighter_info["color"] = color;
|
|
||||||
color_map[j] = highlighter_info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
syntax_highlighting_cache[p_line] = color_map;
|
|
||||||
return color_map;
|
|
||||||
}
|
}
|
||||||
|
@ -43,32 +43,8 @@ class TextEdit : public Control {
|
|||||||
GDCLASS(TextEdit, Control);
|
GDCLASS(TextEdit, Control);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct ColorRegion {
|
|
||||||
Color color;
|
|
||||||
String begin_key;
|
|
||||||
String end_key;
|
|
||||||
bool line_only;
|
|
||||||
bool eq;
|
|
||||||
ColorRegion(const String &p_begin_key = "", const String &p_end_key = "", const Color &p_color = Color(), bool p_line_only = false) {
|
|
||||||
begin_key = p_begin_key;
|
|
||||||
end_key = p_end_key;
|
|
||||||
color = p_color;
|
|
||||||
line_only = p_line_only || p_end_key == "";
|
|
||||||
eq = begin_key == end_key;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Text {
|
class Text {
|
||||||
public:
|
public:
|
||||||
struct ColorRegionInfo {
|
|
||||||
int region;
|
|
||||||
bool end;
|
|
||||||
ColorRegionInfo() {
|
|
||||||
region = 0;
|
|
||||||
end = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Line {
|
struct Line {
|
||||||
int width_cache : 24;
|
int width_cache : 24;
|
||||||
bool marked : 1;
|
bool marked : 1;
|
||||||
@ -78,7 +54,6 @@ public:
|
|||||||
bool safe : 1;
|
bool safe : 1;
|
||||||
bool has_info : 1;
|
bool has_info : 1;
|
||||||
int wrap_amount_cache : 24;
|
int wrap_amount_cache : 24;
|
||||||
RBMap<int, ColorRegionInfo> region_info;
|
|
||||||
Ref<Texture> info_icon;
|
Ref<Texture> info_icon;
|
||||||
String info;
|
String info;
|
||||||
String data;
|
String data;
|
||||||
@ -95,7 +70,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Vector<ColorRegion> *color_regions;
|
|
||||||
mutable Vector<Line> text;
|
mutable Vector<Line> text;
|
||||||
Ref<Font> font;
|
Ref<Font> font;
|
||||||
int indent_size;
|
int indent_size;
|
||||||
@ -105,14 +79,12 @@ public:
|
|||||||
public:
|
public:
|
||||||
void set_indent_size(int p_indent_size);
|
void set_indent_size(int p_indent_size);
|
||||||
void set_font(const Ref<Font> &p_font);
|
void set_font(const Ref<Font> &p_font);
|
||||||
void set_color_regions(const Vector<ColorRegion> *p_regions) { color_regions = p_regions; }
|
|
||||||
|
|
||||||
int get_line_width(int p_line) const;
|
int get_line_width(int p_line) const;
|
||||||
int get_max_width(bool p_exclude_hidden = false) const;
|
int get_max_width(bool p_exclude_hidden = false) const;
|
||||||
int get_char_width(CharType c, CharType next_c, int px) const;
|
int get_char_width(CharType c, CharType next_c, int px) const;
|
||||||
void set_line_wrap_amount(int p_line, int p_wrap_amount) const;
|
void set_line_wrap_amount(int p_line, int p_wrap_amount) const;
|
||||||
int get_line_wrap_amount(int p_line) const;
|
int get_line_wrap_amount(int p_line) const;
|
||||||
const RBMap<int, ColorRegionInfo> &get_color_region_info(int p_line) const;
|
|
||||||
|
|
||||||
void set(int p_line, const String &p_text);
|
void set(int p_line, const String &p_text);
|
||||||
void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
|
void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
|
||||||
@ -231,11 +203,7 @@ private:
|
|||||||
Color font_color;
|
Color font_color;
|
||||||
Color font_color_selected;
|
Color font_color_selected;
|
||||||
Color font_color_readonly;
|
Color font_color_readonly;
|
||||||
Color keyword_color;
|
|
||||||
Color control_flow_keyword_color;
|
Color control_flow_keyword_color;
|
||||||
Color number_color;
|
|
||||||
Color function_color;
|
|
||||||
Color member_variable_color;
|
|
||||||
Color selection_color;
|
Color selection_color;
|
||||||
Color mark_color;
|
Color mark_color;
|
||||||
Color bookmark_color;
|
Color bookmark_color;
|
||||||
@ -248,7 +216,6 @@ private:
|
|||||||
Color word_highlighted_color;
|
Color word_highlighted_color;
|
||||||
Color search_result_color;
|
Color search_result_color;
|
||||||
Color search_result_border_color;
|
Color search_result_border_color;
|
||||||
Color symbol_color;
|
|
||||||
Color background_color;
|
Color background_color;
|
||||||
|
|
||||||
int row_height;
|
int row_height;
|
||||||
@ -258,6 +225,7 @@ private:
|
|||||||
int fold_gutter_width;
|
int fold_gutter_width;
|
||||||
int info_gutter_width;
|
int info_gutter_width;
|
||||||
int minimap_width;
|
int minimap_width;
|
||||||
|
|
||||||
Cache() {
|
Cache() {
|
||||||
row_height = 0;
|
row_height = 0;
|
||||||
line_spacing = 0;
|
line_spacing = 0;
|
||||||
@ -269,7 +237,6 @@ private:
|
|||||||
}
|
}
|
||||||
} cache;
|
} cache;
|
||||||
|
|
||||||
RBMap<int, int> color_region_cache;
|
|
||||||
RBMap<int, Dictionary> syntax_highlighting_cache;
|
RBMap<int, Dictionary> syntax_highlighting_cache;
|
||||||
|
|
||||||
struct TextOperation {
|
struct TextOperation {
|
||||||
@ -314,13 +281,10 @@ private:
|
|||||||
|
|
||||||
//syntax coloring
|
//syntax coloring
|
||||||
Ref<SyntaxHighlighter> syntax_highlighter;
|
Ref<SyntaxHighlighter> syntax_highlighter;
|
||||||
HashMap<String, Color> keywords;
|
RBSet<String> keywords;
|
||||||
HashMap<String, Color> member_keywords;
|
|
||||||
|
|
||||||
Dictionary _get_line_syntax_highlighting(int p_line);
|
Dictionary _get_line_syntax_highlighting(int p_line);
|
||||||
|
|
||||||
Vector<ColorRegion> color_regions;
|
|
||||||
|
|
||||||
RBSet<String> completion_prefixes;
|
RBSet<String> completion_prefixes;
|
||||||
bool completion_enabled;
|
bool completion_enabled;
|
||||||
List<ScriptCodeCompletionOption> completion_sources;
|
List<ScriptCodeCompletionOption> completion_sources;
|
||||||
@ -344,7 +308,6 @@ private:
|
|||||||
uint32_t saved_version;
|
uint32_t saved_version;
|
||||||
|
|
||||||
bool readonly;
|
bool readonly;
|
||||||
bool syntax_coloring;
|
|
||||||
bool indent_using_spaces;
|
bool indent_using_spaces;
|
||||||
int indent_size;
|
int indent_size;
|
||||||
String space_indent;
|
String space_indent;
|
||||||
@ -513,7 +476,6 @@ private:
|
|||||||
void _update_caches();
|
void _update_caches();
|
||||||
void _cursor_changed_emit();
|
void _cursor_changed_emit();
|
||||||
void _text_changed_emit();
|
void _text_changed_emit();
|
||||||
void _line_edited_from(int p_line);
|
|
||||||
|
|
||||||
void _push_current_op();
|
void _push_current_op();
|
||||||
|
|
||||||
@ -562,12 +524,8 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ref<SyntaxHighlighter> get_syntax_highlighting();
|
Ref<SyntaxHighlighter> get_syntax_highlighter();
|
||||||
void set_syntax_highlighting(Ref<SyntaxHighlighter> p_syntax_highlighter);
|
void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
|
||||||
|
|
||||||
int _is_line_in_region(int p_line);
|
|
||||||
ColorRegion _get_color_region(int p_region) const;
|
|
||||||
RBMap<int, Text::ColorRegionInfo> _get_line_color_region_info(int p_line) const;
|
|
||||||
|
|
||||||
enum MenuItems {
|
enum MenuItems {
|
||||||
MENU_CUT,
|
MENU_CUT,
|
||||||
@ -709,9 +667,6 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void set_syntax_coloring(bool p_enabled);
|
|
||||||
bool is_syntax_coloring_enabled() const;
|
|
||||||
|
|
||||||
void cut();
|
void cut();
|
||||||
void copy();
|
void copy();
|
||||||
void paste();
|
void paste();
|
||||||
@ -765,17 +720,8 @@ public:
|
|||||||
void set_insert_mode(bool p_enabled);
|
void set_insert_mode(bool p_enabled);
|
||||||
bool is_insert_mode() const;
|
bool is_insert_mode() const;
|
||||||
|
|
||||||
void add_keyword_color(const String &p_keyword, const Color &p_color);
|
void add_keyword(const String &p_keyword);
|
||||||
bool has_keyword_color(String p_keyword) const;
|
void clear_keywords();
|
||||||
Color get_keyword_color(String p_keyword) const;
|
|
||||||
|
|
||||||
void add_color_region(const String &p_begin_key = String(), const String &p_end_key = String(), const Color &p_color = Color(), bool p_line_only = false);
|
|
||||||
void clear_colors();
|
|
||||||
|
|
||||||
void add_member_keyword(const String &p_keyword, const Color &p_color);
|
|
||||||
bool has_member_color(String p_member) const;
|
|
||||||
Color get_member_color(String p_member) const;
|
|
||||||
void clear_member_keywords();
|
|
||||||
|
|
||||||
double get_v_scroll() const;
|
double get_v_scroll() const;
|
||||||
void set_v_scroll(double p_scroll);
|
void set_v_scroll(double p_scroll);
|
||||||
|
@ -357,6 +357,7 @@ void register_scene_types() {
|
|||||||
|
|
||||||
ClassDB::register_class<TextEdit>();
|
ClassDB::register_class<TextEdit>();
|
||||||
ClassDB::register_class<SyntaxHighlighter>();
|
ClassDB::register_class<SyntaxHighlighter>();
|
||||||
|
ClassDB::register_class<CodeHighlighter>();
|
||||||
|
|
||||||
ClassDB::register_virtual_class<TreeItem>();
|
ClassDB::register_virtual_class<TreeItem>();
|
||||||
ClassDB::register_class<OptionButton>();
|
ClassDB::register_class<OptionButton>();
|
||||||
|
@ -475,13 +475,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
|||||||
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
|
theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
|
||||||
theme->set_color("caret_color", "TextEdit", control_font_color);
|
theme->set_color("caret_color", "TextEdit", control_font_color);
|
||||||
theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0));
|
theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0));
|
||||||
theme->set_color("symbol_color", "TextEdit", control_font_color_hover);
|
|
||||||
theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
|
theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
|
||||||
theme->set_color("line_number_color", "TextEdit", Color(0.67, 0.67, 0.67, 0.4));
|
theme->set_color("line_number_color", "TextEdit", Color(0.67, 0.67, 0.67, 0.4));
|
||||||
theme->set_color("safe_line_number_color", "TextEdit", Color(0.67, 0.78, 0.67, 0.6));
|
theme->set_color("safe_line_number_color", "TextEdit", Color(0.67, 0.78, 0.67, 0.6));
|
||||||
theme->set_color("function_color", "TextEdit", Color(0.4, 0.64, 0.81));
|
|
||||||
theme->set_color("member_variable_color", "TextEdit", Color(0.9, 0.31, 0.35));
|
|
||||||
theme->set_color("number_color", "TextEdit", Color(0.92, 0.58, 0.2));
|
|
||||||
theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
|
theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
|
||||||
|
|
||||||
theme->set_constant("completion_lines", "TextEdit", 7);
|
theme->set_constant("completion_lines", "TextEdit", 7);
|
||||||
|
@ -34,44 +34,614 @@
|
|||||||
#include "scene/gui/text_edit.h"
|
#include "scene/gui/text_edit.h"
|
||||||
|
|
||||||
Dictionary SyntaxHighlighter::get_line_syntax_highlighting(int p_line) {
|
Dictionary SyntaxHighlighter::get_line_syntax_highlighting(int p_line) {
|
||||||
return call("_get_line_syntax_highlighting", p_line);
|
if (highlighting_cache.has(p_line)) {
|
||||||
|
return highlighting_cache[p_line];
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary color_map;
|
||||||
|
if (text_edit == nullptr) {
|
||||||
|
return color_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptInstance *si = get_script_instance();
|
||||||
|
if (si && si->has_method("_get_line_syntax_highlighting")) {
|
||||||
|
color_map = si->call("_get_line_syntax_highlighting", p_line);
|
||||||
|
} else {
|
||||||
|
color_map = _get_line_syntax_highlighting(p_line);
|
||||||
|
}
|
||||||
|
highlighting_cache[p_line] = color_map;
|
||||||
|
return color_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyntaxHighlighter::_line_edited_from(int p_line) {
|
||||||
|
if (highlighting_cache.size() < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cache_size = highlighting_cache.back()->key();
|
||||||
|
for (int i = p_line - 1; i <= cache_size; i++) {
|
||||||
|
if (highlighting_cache.has(i)) {
|
||||||
|
highlighting_cache.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyntaxHighlighter::clear_highlighting_cache() {
|
||||||
|
highlighting_cache.clear();
|
||||||
|
|
||||||
|
ScriptInstance *si = get_script_instance();
|
||||||
|
if (si && si->has_method("_clear_highlighting_cache")) {
|
||||||
|
si->call("_clear_highlighting_cache");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_clear_highlighting_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighter::update_cache() {
|
void SyntaxHighlighter::update_cache() {
|
||||||
call("_update_cache");
|
clear_highlighting_cache();
|
||||||
|
|
||||||
|
if (text_edit == nullptr) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String SyntaxHighlighter::_get_name() const {
|
|
||||||
ScriptInstance *si = get_script_instance();
|
ScriptInstance *si = get_script_instance();
|
||||||
if (si && si->has_method("_get_name")) {
|
|
||||||
return si->call("_get_name");
|
if (si && si->has_method("_update_cache")) {
|
||||||
}
|
si->call("_update_cache");
|
||||||
return "Unamed";
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array SyntaxHighlighter::_get_supported_languages() const {
|
_update_cache();
|
||||||
ScriptInstance *si = get_script_instance();
|
|
||||||
if (si && si->has_method("_get_supported_languages")) {
|
|
||||||
return si->call("_get_supported_languages");
|
|
||||||
}
|
|
||||||
return Array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) {
|
void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) {
|
||||||
|
if (text_edit && ObjectDB::get_instance(text_edit_instance_id)) {
|
||||||
|
text_edit->disconnect("line_edited_from", this, "_line_edited_from");
|
||||||
|
}
|
||||||
|
|
||||||
text_edit = p_text_edit;
|
text_edit = p_text_edit;
|
||||||
|
if (p_text_edit == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
text_edit_instance_id = text_edit->get_instance_id();
|
||||||
|
text_edit->connect("line_edited_from", this, "_line_edited_from");
|
||||||
|
update_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEdit *SyntaxHighlighter::get_text_edit() {
|
TextEdit *SyntaxHighlighter::get_text_edit() {
|
||||||
return text_edit;
|
return text_edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyntaxHighlighter::SyntaxHighlighter() {
|
||||||
|
text_edit = NULL;
|
||||||
|
}
|
||||||
|
SyntaxHighlighter::~SyntaxHighlighter() {}
|
||||||
|
|
||||||
void SyntaxHighlighter::_bind_methods() {
|
void SyntaxHighlighter::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("_get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::_get_line_syntax_highlighting);
|
ClassDB::bind_method(D_METHOD("get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::get_line_syntax_highlighting);
|
||||||
ClassDB::bind_method(D_METHOD("_update_cache"), &SyntaxHighlighter::_update_cache);
|
ClassDB::bind_method(D_METHOD("update_cache"), &SyntaxHighlighter::update_cache);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_highlighting_cache"), &SyntaxHighlighter::clear_highlighting_cache);
|
||||||
ClassDB::bind_method(D_METHOD("get_text_edit"), &SyntaxHighlighter::get_text_edit);
|
ClassDB::bind_method(D_METHOD("get_text_edit"), &SyntaxHighlighter::get_text_edit);
|
||||||
|
|
||||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name"));
|
ClassDB::bind_method(D_METHOD("_get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::_get_line_syntax_highlighting);
|
||||||
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_supported_languages"));
|
ClassDB::bind_method(D_METHOD("_update_cache"), &SyntaxHighlighter::_update_cache);
|
||||||
|
ClassDB::bind_method(D_METHOD("_clear_highlighting_cache"), &SyntaxHighlighter::_clear_highlighting_cache);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("_line_edited_from"), &SyntaxHighlighter::_line_edited_from);
|
||||||
|
|
||||||
BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_line_syntax_highlighting", PropertyInfo(Variant::INT, "p_line")));
|
BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_line_syntax_highlighting", PropertyInfo(Variant::INT, "p_line")));
|
||||||
BIND_VMETHOD(MethodInfo("_update_cache"));
|
BIND_VMETHOD(MethodInfo("_update_cache"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool _is_char(CharType c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _is_hex_symbol(CharType c) {
|
||||||
|
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) {
|
||||||
|
Dictionary color_map;
|
||||||
|
|
||||||
|
bool prev_is_char = false;
|
||||||
|
bool prev_is_number = false;
|
||||||
|
bool in_keyword = false;
|
||||||
|
bool in_word = false;
|
||||||
|
bool in_function_name = false;
|
||||||
|
bool in_member_variable = false;
|
||||||
|
bool is_hex_notation = false;
|
||||||
|
Color keyword_color;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
color_region_cache[p_line] = -1;
|
||||||
|
int in_region = -1;
|
||||||
|
if (p_line != 0) {
|
||||||
|
if (!color_region_cache.has(p_line - 1)) {
|
||||||
|
get_line_syntax_highlighting(p_line - 1);
|
||||||
|
}
|
||||||
|
in_region = color_region_cache[p_line - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const String &str = text_edit->get_line(p_line);
|
||||||
|
const int line_length = str.length();
|
||||||
|
Color prev_color;
|
||||||
|
for (int j = 0; j < line_length; j++) {
|
||||||
|
Dictionary highlighter_info;
|
||||||
|
|
||||||
|
color = font_color;
|
||||||
|
bool is_char = !is_symbol(str[j]);
|
||||||
|
bool is_a_symbol = is_symbol(str[j]);
|
||||||
|
bool is_number = (str[j] >= '0' && str[j] <= '9');
|
||||||
|
|
||||||
|
/* color regions */
|
||||||
|
if (is_a_symbol || in_region != -1) {
|
||||||
|
int from = j;
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from != line_length) {
|
||||||
|
/* check if we are in entering a region */
|
||||||
|
if (in_region == -1) {
|
||||||
|
for (int c = 0; c < color_regions.size(); c++) {
|
||||||
|
/* check there is enough room */
|
||||||
|
int chars_left = line_length - from;
|
||||||
|
int start_key_length = color_regions[c].start_key.length();
|
||||||
|
int end_key_length = color_regions[c].end_key.length();
|
||||||
|
if (chars_left < start_key_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the line */
|
||||||
|
bool match = true;
|
||||||
|
const CharType *start_key = color_regions[c].start_key.get_data();
|
||||||
|
for (int k = 0; k < start_key_length; k++) {
|
||||||
|
if (start_key[k] != str[from + k]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
in_region = c;
|
||||||
|
from += start_key_length;
|
||||||
|
|
||||||
|
/* check if it's the whole line */
|
||||||
|
if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) {
|
||||||
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[c].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
j = line_length;
|
||||||
|
if (!color_regions[c].line_only) {
|
||||||
|
color_region_cache[p_line] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == line_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are in one find the end key */
|
||||||
|
if (in_region != -1) {
|
||||||
|
/* check there is enough room */
|
||||||
|
int chars_left = line_length - from;
|
||||||
|
int end_key_length = color_regions[in_region].end_key.length();
|
||||||
|
if (chars_left < end_key_length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the line */
|
||||||
|
int region_end_index = -1;
|
||||||
|
const CharType *end_key = color_regions[in_region].start_key.get_data();
|
||||||
|
for (; from < line_length; from++) {
|
||||||
|
if (!is_a_symbol) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[from] == '\\') {
|
||||||
|
from++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < end_key_length; k++) {
|
||||||
|
if (end_key[k] == str[from + k]) {
|
||||||
|
region_end_index = from;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (region_end_index != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_color = color_regions[in_region].color;
|
||||||
|
highlighter_info["color"] = color_regions[in_region].color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
|
||||||
|
j = from;
|
||||||
|
if (region_end_index == -1) {
|
||||||
|
color_region_cache[p_line] = in_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_region = -1;
|
||||||
|
prev_is_char = false;
|
||||||
|
prev_is_number = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow ABCDEF in hex notation.
|
||||||
|
if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) {
|
||||||
|
is_number = true;
|
||||||
|
} else {
|
||||||
|
is_hex_notation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation.
|
||||||
|
if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
|
||||||
|
is_number = true;
|
||||||
|
is_a_symbol = false;
|
||||||
|
is_char = false;
|
||||||
|
|
||||||
|
if (str[j] == 'x' && str[j - 1] == '0') {
|
||||||
|
is_hex_notation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_word && _is_char(str[j]) && !is_number) {
|
||||||
|
in_word = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((in_keyword || in_word) && !is_hex_notation) {
|
||||||
|
is_number = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_a_symbol && str[j] != '.' && in_word) {
|
||||||
|
in_word = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_char) {
|
||||||
|
in_keyword = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_keyword && is_char && !prev_is_char) {
|
||||||
|
int to = j;
|
||||||
|
while (to < line_length && !is_symbol(str[to])) {
|
||||||
|
to++;
|
||||||
|
}
|
||||||
|
|
||||||
|
String word = str.substr(j, to - j);
|
||||||
|
Color col = Color();
|
||||||
|
if (keywords.has(word)) {
|
||||||
|
col = keywords[word];
|
||||||
|
} else if (member_keywords.has(word)) {
|
||||||
|
col = member_keywords[word];
|
||||||
|
for (int k = j - 1; k >= 0; k--) {
|
||||||
|
if (str[k] == '.') {
|
||||||
|
col = Color(); //member indexing not allowed
|
||||||
|
break;
|
||||||
|
} else if (str[k] > 32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col != Color()) {
|
||||||
|
in_keyword = true;
|
||||||
|
keyword_color = col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_function_name && in_word && !in_keyword) {
|
||||||
|
int k = j;
|
||||||
|
while (k < line_length && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for space between name and bracket.
|
||||||
|
while (k < line_length && (str[k] == '\t' || str[k] == ' ')) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[k] == '(') {
|
||||||
|
in_function_name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) {
|
||||||
|
int k = j;
|
||||||
|
while (k > 0 && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') {
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[k] == '.') {
|
||||||
|
in_member_variable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_a_symbol) {
|
||||||
|
in_function_name = false;
|
||||||
|
in_member_variable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_keyword) {
|
||||||
|
color = keyword_color;
|
||||||
|
} else if (in_member_variable) {
|
||||||
|
color = member_color;
|
||||||
|
} else if (in_function_name) {
|
||||||
|
color = function_color;
|
||||||
|
} else if (is_a_symbol) {
|
||||||
|
color = symbol_color;
|
||||||
|
} else if (is_number) {
|
||||||
|
color = number_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_is_char = is_char;
|
||||||
|
prev_is_number = is_number;
|
||||||
|
|
||||||
|
if (color != prev_color) {
|
||||||
|
prev_color = color;
|
||||||
|
highlighter_info["color"] = color;
|
||||||
|
color_map[j] = highlighter_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return color_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::_clear_highlighting_cache() {
|
||||||
|
color_region_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::_update_cache() {
|
||||||
|
font_color = text_edit->get_theme_color("font_color");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::add_keyword_color(const String &p_keyword, const Color &p_color) {
|
||||||
|
keywords[p_keyword] = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::remove_keyword_color(const String &p_keyword) {
|
||||||
|
keywords.erase(p_keyword);
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodeHighlighter::has_keyword_color(const String &p_keyword) const {
|
||||||
|
return keywords.has(p_keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_keyword_color(const String &p_keyword) const {
|
||||||
|
ERR_FAIL_COND_V(!keywords.has(p_keyword), Color());
|
||||||
|
return keywords[p_keyword];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_keyword_colors(const Dictionary p_keywords) {
|
||||||
|
keywords.clear();
|
||||||
|
keywords = p_keywords;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::clear_keyword_colors() {
|
||||||
|
keywords.clear();
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary CodeHighlighter::get_keyword_colors() const {
|
||||||
|
return keywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::add_member_keyword_color(const String &p_member_keyword, const Color &p_color) {
|
||||||
|
member_keywords[p_member_keyword] = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::remove_member_keyword_color(const String &p_member_keyword) {
|
||||||
|
member_keywords.erase(p_member_keyword);
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodeHighlighter::has_member_keyword_color(const String &p_member_keyword) const {
|
||||||
|
return member_keywords.has(p_member_keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_member_keyword_color(const String &p_member_keyword) const {
|
||||||
|
ERR_FAIL_COND_V(!member_keywords.has(p_member_keyword), Color());
|
||||||
|
return member_keywords[p_member_keyword];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_member_keyword_colors(const Dictionary &p_member_keywords) {
|
||||||
|
member_keywords.clear();
|
||||||
|
member_keywords = p_member_keywords;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::clear_member_keyword_colors() {
|
||||||
|
member_keywords.clear();
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary CodeHighlighter::get_member_keyword_colors() const {
|
||||||
|
return member_keywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
|
||||||
|
/*
|
||||||
|
for (int i = 0; i < p_start_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "color regions must start with a symbol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_end_key.length() > 0) {
|
||||||
|
for (int i = 0; i < p_end_key.length(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(!is_symbol(p_end_key[i]), "color regions must end with a symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "color region with start key '" + p_start_key + "' already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRegion color_region;
|
||||||
|
color_region.color = p_color;
|
||||||
|
color_region.start_key = p_start_key;
|
||||||
|
color_region.end_key = p_end_key;
|
||||||
|
color_region.line_only = p_line_only;
|
||||||
|
color_regions.push_back(color_region);
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::remove_color_region(const String &p_start_key) {
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
if (color_regions[i].start_key == p_start_key) {
|
||||||
|
color_regions.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodeHighlighter::has_color_region(const String &p_start_key) const {
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
if (color_regions[i].start_key == p_start_key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_color_regions(const Dictionary &p_color_regions) {
|
||||||
|
color_regions.clear();
|
||||||
|
|
||||||
|
List<Variant> keys;
|
||||||
|
p_color_regions.get_key_list(&keys);
|
||||||
|
|
||||||
|
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||||
|
String key = E->get();
|
||||||
|
|
||||||
|
String start_key = key.get_slice(" ", 0);
|
||||||
|
String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String();
|
||||||
|
|
||||||
|
add_color_region(start_key, end_key, p_color_regions[key], end_key == "");
|
||||||
|
}
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::clear_color_regions() {
|
||||||
|
color_regions.clear();
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary CodeHighlighter::get_color_regions() const {
|
||||||
|
Dictionary r_color_regions;
|
||||||
|
for (int i = 0; i < color_regions.size(); i++) {
|
||||||
|
ColorRegion region = color_regions[i];
|
||||||
|
r_color_regions[region.start_key + (region.end_key.empty() ? "" : " " + region.end_key)] = region.color;
|
||||||
|
}
|
||||||
|
return r_color_regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &CodeHighlighter::add_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_keyword_color", "keyword"), &CodeHighlighter::remove_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("has_keyword_color", "keyword"), &CodeHighlighter::has_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_keyword_color", "keyword"), &CodeHighlighter::get_keyword_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_keyword_colors", "keywords"), &CodeHighlighter::set_keyword_colors);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_keyword_colors"), &CodeHighlighter::clear_keyword_colors);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_keyword_colors"), &CodeHighlighter::get_keyword_colors);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("add_member_keyword_color", "member_keyword", "color"), &CodeHighlighter::add_member_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_member_keyword_color", "member_keyword"), &CodeHighlighter::remove_member_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("has_member_keyword_color", "member_keyword"), &CodeHighlighter::has_member_keyword_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_member_keyword_color", "member_keyword"), &CodeHighlighter::get_member_keyword_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_member_keyword_colors", "member_keyword"), &CodeHighlighter::set_member_keyword_colors);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_member_keyword_colors"), &CodeHighlighter::clear_member_keyword_colors);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_member_keyword_colors"), &CodeHighlighter::get_member_keyword_colors);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("add_color_region", "p_start_key", "p_end_key", "p_color", "p_line_only"), &CodeHighlighter::add_color_region, DEFVAL(false));
|
||||||
|
ClassDB::bind_method(D_METHOD("remove_color_region", "p_start_key"), &CodeHighlighter::remove_color_region);
|
||||||
|
ClassDB::bind_method(D_METHOD("has_color_region", "p_start_key"), &CodeHighlighter::has_color_region);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_color_regions", "p_color_regions"), &CodeHighlighter::set_color_regions);
|
||||||
|
ClassDB::bind_method(D_METHOD("clear_color_regions"), &CodeHighlighter::clear_color_regions);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_color_regions"), &CodeHighlighter::get_color_regions);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_function_color", "color"), &CodeHighlighter::set_function_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_function_color"), &CodeHighlighter::get_function_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_number_color", "color"), &CodeHighlighter::set_number_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_number_color"), &CodeHighlighter::get_number_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_symbol_color", "color"), &CodeHighlighter::set_symbol_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_symbol_color"), &CodeHighlighter::get_symbol_color);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_member_variable_color", "color"), &CodeHighlighter::set_member_variable_color);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_member_variable_color"), &CodeHighlighter::get_member_variable_color);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "number_color"), "set_number_color", "get_number_color");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "symbol_color"), "set_symbol_color", "get_symbol_color");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "function_color"), "set_function_color", "get_function_color");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "member_variable_color"), "set_member_variable_color", "get_member_variable_color");
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "keyword_colors"), "set_keyword_colors", "get_keyword_colors");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "member_keyword_colors"), "set_member_keyword_colors", "get_member_keyword_colors");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "color_regions"), "set_color_regions", "get_color_regions");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_number_color(Color p_color) {
|
||||||
|
number_color = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_number_color() const {
|
||||||
|
return number_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_symbol_color(Color p_color) {
|
||||||
|
symbol_color = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_symbol_color() const {
|
||||||
|
return symbol_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_function_color(Color p_color) {
|
||||||
|
function_color = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_function_color() const {
|
||||||
|
return function_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeHighlighter::set_member_variable_color(Color p_color) {
|
||||||
|
member_color = p_color;
|
||||||
|
clear_highlighting_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color CodeHighlighter::get_member_variable_color() const {
|
||||||
|
return member_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeHighlighter::CodeHighlighter() {
|
||||||
|
}
|
||||||
|
CodeHighlighter::~CodeHighlighter() {
|
||||||
|
}
|
@ -38,26 +38,107 @@ class TextEdit;
|
|||||||
class SyntaxHighlighter : public Resource {
|
class SyntaxHighlighter : public Resource {
|
||||||
GDCLASS(SyntaxHighlighter, Resource)
|
GDCLASS(SyntaxHighlighter, Resource)
|
||||||
|
|
||||||
protected:
|
|
||||||
TextEdit *text_edit;
|
|
||||||
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Dictionary get_line_syntax_highlighting(int p_line);
|
Dictionary get_line_syntax_highlighting(int p_line);
|
||||||
virtual Dictionary _get_line_syntax_highlighting(int p_line) { return Dictionary(); }
|
virtual Dictionary _get_line_syntax_highlighting(int p_line) { return Dictionary(); }
|
||||||
|
|
||||||
|
void clear_highlighting_cache();
|
||||||
|
virtual void _clear_highlighting_cache() {}
|
||||||
|
|
||||||
void update_cache();
|
void update_cache();
|
||||||
virtual void _update_cache() {}
|
virtual void _update_cache() {}
|
||||||
|
|
||||||
virtual String _get_name() const;
|
|
||||||
virtual Array _get_supported_languages() const;
|
|
||||||
|
|
||||||
void set_text_edit(TextEdit *p_text_edit);
|
void set_text_edit(TextEdit *p_text_edit);
|
||||||
TextEdit *get_text_edit();
|
TextEdit *get_text_edit();
|
||||||
|
|
||||||
SyntaxHighlighter() {}
|
SyntaxHighlighter();
|
||||||
virtual ~SyntaxHighlighter() {}
|
~SyntaxHighlighter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ObjectID text_edit_instance_id; // For validity check
|
||||||
|
TextEdit *text_edit;
|
||||||
|
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RBMap<int, Dictionary> highlighting_cache;
|
||||||
|
void _line_edited_from(int p_line);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CodeHighlighter : public SyntaxHighlighter {
|
||||||
|
GDCLASS(CodeHighlighter, SyntaxHighlighter)
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Dictionary _get_line_syntax_highlighting(int p_line) override;
|
||||||
|
|
||||||
|
virtual void _clear_highlighting_cache() override;
|
||||||
|
virtual void _update_cache() override;
|
||||||
|
|
||||||
|
void add_keyword_color(const String &p_keyword, const Color &p_color);
|
||||||
|
void remove_keyword_color(const String &p_keyword);
|
||||||
|
bool has_keyword_color(const String &p_keyword) const;
|
||||||
|
Color get_keyword_color(const String &p_keyword) const;
|
||||||
|
|
||||||
|
void set_keyword_colors(const Dictionary p_keywords);
|
||||||
|
void clear_keyword_colors();
|
||||||
|
Dictionary get_keyword_colors() const;
|
||||||
|
|
||||||
|
void add_member_keyword_color(const String &p_member_keyword, const Color &p_color);
|
||||||
|
void remove_member_keyword_color(const String &p_member_keyword);
|
||||||
|
bool has_member_keyword_color(const String &p_member_keyword) const;
|
||||||
|
Color get_member_keyword_color(const String &p_member_keyword) const;
|
||||||
|
|
||||||
|
void set_member_keyword_colors(const Dictionary &p_color_regions);
|
||||||
|
void clear_member_keyword_colors();
|
||||||
|
Dictionary get_member_keyword_colors() const;
|
||||||
|
|
||||||
|
void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
|
||||||
|
void remove_color_region(const String &p_start_key);
|
||||||
|
bool has_color_region(const String &p_start_key) const;
|
||||||
|
|
||||||
|
void set_color_regions(const Dictionary &p_member_keyword);
|
||||||
|
void clear_color_regions();
|
||||||
|
Dictionary get_color_regions() const;
|
||||||
|
|
||||||
|
void set_number_color(Color p_color);
|
||||||
|
Color get_number_color() const;
|
||||||
|
|
||||||
|
void set_symbol_color(Color p_color);
|
||||||
|
Color get_symbol_color() const;
|
||||||
|
|
||||||
|
void set_function_color(Color p_color);
|
||||||
|
Color get_function_color() const;
|
||||||
|
|
||||||
|
void set_member_variable_color(Color p_color);
|
||||||
|
Color get_member_variable_color() const;
|
||||||
|
|
||||||
|
CodeHighlighter();
|
||||||
|
~CodeHighlighter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ColorRegion {
|
||||||
|
Color color;
|
||||||
|
String start_key;
|
||||||
|
String end_key;
|
||||||
|
bool line_only;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<ColorRegion> color_regions;
|
||||||
|
RBMap<int, int> color_region_cache;
|
||||||
|
|
||||||
|
Dictionary keywords;
|
||||||
|
Dictionary member_keywords;
|
||||||
|
|
||||||
|
Color font_color;
|
||||||
|
Color member_color;
|
||||||
|
Color function_color;
|
||||||
|
Color symbol_color;
|
||||||
|
Color number_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user