diff options
Diffstat (limited to 'scene/gui/code_edit.cpp')
-rw-r--r-- | scene/gui/code_edit.cpp | 87 |
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; } |