summaryrefslogtreecommitdiff
path: root/scene/gui/code_edit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/code_edit.cpp')
-rw-r--r--scene/gui/code_edit.cpp87
1 files changed, 60 insertions, 27 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 5f3ab18cca..5d1106bb41 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -296,7 +296,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
mpos.x = get_size().x - mpos.x;
}
- Point2i pos = get_line_column_at_pos(Point2i(mpos.x, mpos.y));
+ Point2i pos = get_line_column_at_pos(mpos);
int line = pos.y;
int col = pos.x;
@@ -321,7 +321,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
mpos.x = get_size().x - mpos.x;
}
- Point2i pos = get_line_column_at_pos(Point2i(mpos.x, mpos.y));
+ Point2i pos = get_line_column_at_pos(mpos);
int line = pos.y;
int col = pos.x;
@@ -467,7 +467,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
/* MISC */
- if (k->is_action("ui_cancel", true)) {
+ if (!code_hint.is_empty() && k->is_action("ui_cancel", true)) {
set_code_hint("");
accept_event();
return;
@@ -654,7 +654,7 @@ void CodeEdit::_backspace_internal() {
// For space indentation we need to do a simple unindent if there are no chars to the left, acting in the
// same way as tabs.
if (indent_using_spaces && cc != 0) {
- if (get_first_non_whitespace_column(cl) > cc) {
+ if (get_first_non_whitespace_column(cl) >= cc) {
prev_column = cc - _calculate_spaces_till_next_left_indent(cc);
prev_line = cl;
}
@@ -987,10 +987,10 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
/* No need to move the brace below if we are not taking the text with us. */
if (p_split_current_line) {
brace_indent = true;
- ins += "\n" + ins.substr(1, ins.length() - 2);
+ ins += "\n" + ins.substr(indent_text.size(), ins.length() - 2);
} else {
brace_indent = false;
- ins = "\n" + ins.substr(1, ins.length() - 2);
+ ins = "\n" + ins.substr(indent_text.size(), ins.length() - 2);
}
}
}
@@ -1400,15 +1400,21 @@ void CodeEdit::fold_line(int p_line) {
}
/* Find the last line to be hidden. */
- int end_line = get_line_count();
+ const int line_count = get_line_count() - 1;
+ int end_line = line_count;
int in_comment = is_in_comment(p_line);
int in_string = (in_comment == -1) ? is_in_string(p_line) : -1;
if (in_string != -1 || in_comment != -1) {
end_line = get_delimiter_end_position(p_line, get_line(p_line).size() - 1).y;
- /* End line is the same therefore we have a block. */
+ /* End line is the same therefore we have a block of single line delimiters. */
if (end_line == p_line) {
- for (int i = p_line + 1; i < get_line_count(); i++) {
+ for (int i = p_line + 1; i <= line_count; i++) {
+ if (i == line_count) {
+ end_line = line_count;
+ break;
+ }
+
if ((in_string != -1 && is_in_string(i) == -1) || (in_comment != -1 && is_in_comment(i) == -1)) {
end_line = i - 1;
break;
@@ -1417,14 +1423,27 @@ void CodeEdit::fold_line(int p_line) {
}
} else {
int start_indent = get_indent_level(p_line);
- for (int i = p_line + 1; i < get_line_count(); i++) {
+ for (int i = p_line + 1; i <= line_count; i++) {
if (get_line(p_line).strip_edges().size() == 0 || is_in_string(i) != -1 || is_in_comment(i) != -1) {
end_line = i;
continue;
}
- if (get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0) {
+ if (i == line_count) {
+ /* Do not fold empty last line of script if any */
+ end_line = i;
+ if (get_line(i).strip_edges().size() == 0) {
+ end_line--;
+ }
+ break;
+ }
+
+ if ((get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0)) {
+ /* Keep an empty line unfolded if any */
end_line = i - 1;
+ if (get_line(i - 1).strip_edges().size() == 0 && i - 2 > p_line) {
+ end_line = i - 2;
+ }
break;
}
}
@@ -1603,7 +1622,8 @@ Point2 CodeEdit::get_delimiter_start_position(int p_line, int p_column) const {
}
/* Region was found on this line and is not a multiline continuation. */
- if (start_position.x != -1 && start_position.x != get_line(p_line).length() + 1) {
+ int line_length = get_line(p_line).length();
+ if (start_position.x != -1 && line_length > 0 && start_position.x != line_length + 1) {
start_position.y = p_line;
return start_position;
}
@@ -1622,7 +1642,8 @@ Point2 CodeEdit::get_delimiter_start_position(int p_line, int p_column) const {
start_position.x = delimiter_cache[i].back()->key();
/* Make sure it's not a multiline continuation. */
- if (start_position.x != get_line(i).length() + 1) {
+ line_length = get_line(i).length();
+ if (line_length > 0 && start_position.x != line_length + 1) {
break;
}
}
@@ -1704,14 +1725,17 @@ bool CodeEdit::is_code_completion_enabled() const {
void CodeEdit::set_code_completion_prefixes(const TypedArray<String> &p_prefixes) {
code_completion_prefixes.clear();
for (int i = 0; i < p_prefixes.size(); i++) {
- code_completion_prefixes.insert(p_prefixes[i]);
+ const String prefix = p_prefixes[i];
+
+ ERR_CONTINUE_MSG(prefix.is_empty(), "Code completion prefix cannot be empty.");
+ code_completion_prefixes.insert(prefix[0]);
}
}
TypedArray<String> CodeEdit::get_code_completion_prefixes() const {
TypedArray<String> prefixes;
- for (Set<String>::Element *E = code_completion_prefixes.front(); E; E = E->next()) {
- prefixes.push_back(E->get());
+ for (const Set<char32_t>::Element *E = code_completion_prefixes.front(); E; E = E->next()) {
+ prefixes.push_back(String::chr(E->get()));
}
return prefixes;
}
@@ -1774,9 +1798,9 @@ void CodeEdit::request_code_completion(bool p_force) {
String line = get_line(get_caret_line());
int ofs = CLAMP(get_caret_column(), 0, line.length());
- if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) {
+ if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(line[ofs - 1]))) {
emit_signal(SNAME("request_code_completion"));
- } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[ofs - 2]))) {
+ } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(line[ofs - 2])) {
emit_signal(SNAME("request_code_completion"));
}
}
@@ -1937,7 +1961,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column() > 0 && get_caret_column() < get_line(caret_line).length()) {
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column() + 1);
- if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
+ if (pre_brace_pair != -1 && pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
remove_text(caret_line, get_caret_column() - 2, caret_line, get_caret_column());
if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1) != pre_brace_pair) {
set_caret_column(get_caret_column() - 1);
@@ -1948,7 +1972,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
end_complex_operation();
cancel_code_completion();
- if (code_completion_prefixes.has(String::chr(last_completion_char))) {
+ if (code_completion_prefixes.has(last_completion_char)) {
request_code_completion();
}
}
@@ -2013,7 +2037,9 @@ String CodeEdit::get_text_for_symbol_lookup() {
void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
symbol_lookup_word = p_valid ? symbol_lookup_new_word : "";
symbol_lookup_new_word = "";
- _set_symbol_lookup_word(symbol_lookup_word);
+ if (lookup_symbol_word != symbol_lookup_word) {
+ _set_symbol_lookup_word(symbol_lookup_word);
+ }
}
void CodeEdit::_bind_methods() {
@@ -2548,7 +2574,10 @@ int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) c
}
void CodeEdit::_add_delimiter(const String &p_start_key, const String &p_end_key, bool p_line_only, DelimiterType p_type) {
- if (p_start_key.length() > 0) {
+ // If we are the editor allow "null" as a valid start key, otherwise users cannot add delimiters via the inspector.
+ if (!(Engine::get_singleton()->is_editor_hint() && p_start_key == "null")) {
+ ERR_FAIL_COND_MSG(p_start_key.is_empty(), "delimiter start key cannot be empty");
+
for (int i = 0; i < p_start_key.length(); i++) {
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "delimiter must start with a symbol");
}
@@ -2613,7 +2642,11 @@ void CodeEdit::_set_delimiters(const TypedArray<String> &p_delimiters, Delimiter
_clear_delimiters(p_type);
for (int i = 0; i < p_delimiters.size(); i++) {
- String key = p_delimiters[i].is_null() ? "" : p_delimiters[i];
+ String key = p_delimiters[i];
+
+ if (key.is_empty()) {
+ continue;
+ }
const String start_key = key.get_slice(" ", 0);
const String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String();
@@ -2734,7 +2767,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
bool prev_is_word = false;
/* Cancel if we are at the close of a string. */
- if (in_string == -1 && first_quote_col == cofs - 1) {
+ if (caret_column > 0 && in_string == -1 && first_quote_col == cofs - 1) {
cancel_code_completion();
return;
/* In a string, therefore we are trying to complete the string text. */
@@ -2744,7 +2777,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
/* If we have a space, previous word might be a keyword. eg "func |". */
} else if (cofs > 0 && line[cofs - 1] == ' ') {
int ofs = cofs - 1;
- while (ofs >= 0 && line[ofs] == ' ') {
+ while (ofs > 0 && line[ofs] == ' ') {
ofs--;
}
prev_is_word = _is_char(line[ofs]);
@@ -2760,9 +2793,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
/* If all else fails, check for a prefix. */
/* Single space between caret and prefix is okay. */
bool prev_is_prefix = false;
- if (cofs > 0 && code_completion_prefixes.has(String::chr(line[cofs - 1]))) {
+ if (cofs > 0 && code_completion_prefixes.has(line[cofs - 1])) {
prev_is_prefix = true;
- } else if (cofs > 1 && line[cofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[cofs - 2]))) {
+ } else if (cofs > 1 && line[cofs - 1] == ' ' && code_completion_prefixes.has(line[cofs - 2])) {
prev_is_prefix = true;
}