You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-19 14:31:59 +00:00
Add multi caret support to CodeEdit
This commit is contained in:
@@ -610,37 +610,41 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
|
|||||||
|
|
||||||
// Overridable actions
|
// Overridable actions
|
||||||
void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode, int p_caret) {
|
void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode, int p_caret) {
|
||||||
bool had_selection = has_selection();
|
start_action(EditAction::ACTION_TYPING);
|
||||||
String selection_text = (had_selection ? get_selected_text() : "");
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
|
for (const int &i : caret_edit_order) {
|
||||||
|
if (p_caret != -1 && p_caret != i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool had_selection = has_selection(i);
|
||||||
|
String selection_text = (had_selection ? get_selected_text(i) : "");
|
||||||
|
|
||||||
if (had_selection) {
|
if (had_selection) {
|
||||||
begin_complex_operation();
|
delete_selection(i);
|
||||||
delete_selection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the old character if in overtype mode and no selection.
|
// Remove the old character if in overtype mode and no selection.
|
||||||
if (is_overtype_mode_enabled() && !had_selection) {
|
if (is_overtype_mode_enabled() && !had_selection) {
|
||||||
begin_complex_operation();
|
// Make sure we don't try and remove empty space.
|
||||||
|
if (get_caret_column(i) < get_line(get_caret_line(i)).length()) {
|
||||||
/* Make sure we don't try and remove empty space. */
|
remove_text(get_caret_line(i), get_caret_column(i), get_caret_line(i), get_caret_column(i) + 1);
|
||||||
if (get_caret_column() < get_line(get_caret_line()).length()) {
|
|
||||||
remove_text(get_caret_line(), get_caret_column(), get_caret_line(), get_caret_column() + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char32_t chr[2] = { (char32_t)p_unicode, 0 };
|
const char32_t chr[2] = { (char32_t)p_unicode, 0 };
|
||||||
|
|
||||||
if (auto_brace_completion_enabled) {
|
if (auto_brace_completion_enabled) {
|
||||||
int cl = get_caret_line();
|
int cl = get_caret_line(i);
|
||||||
int cc = get_caret_column();
|
int cc = get_caret_column(i);
|
||||||
|
|
||||||
if (had_selection) {
|
if (had_selection) {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
|
|
||||||
String close_key = get_auto_brace_completion_close_key(chr);
|
String close_key = get_auto_brace_completion_close_key(chr);
|
||||||
if (!close_key.is_empty()) {
|
if (!close_key.is_empty()) {
|
||||||
insert_text_at_caret(selection_text + close_key);
|
insert_text_at_caret(selection_text + close_key, i);
|
||||||
set_caret_column(get_caret_column() - 1);
|
set_caret_column(get_caret_column(i) - 1, i == 0, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int caret_move_offset = 1;
|
int caret_move_offset = 1;
|
||||||
@@ -648,30 +652,28 @@ void CodeEdit::_handle_unicode_input_internal(const uint32_t p_unicode, int p_ca
|
|||||||
int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
|
int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
|
||||||
|
|
||||||
if (has_string_delimiter(chr) && cc > 0 && !is_symbol(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
|
if (has_string_delimiter(chr) && cc > 0 && !is_symbol(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
} else if (cc < get_line(cl).length() && !is_symbol(get_line(cl)[cc])) {
|
} else if (cc < get_line(cl).length() && !is_symbol(get_line(cl)[cc])) {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
} else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
|
} else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
|
||||||
caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
|
caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
|
||||||
} else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
|
} else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
} else {
|
} else {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
|
|
||||||
int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
|
int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
|
||||||
if (pre_brace_pair != -1) {
|
if (pre_brace_pair != -1) {
|
||||||
insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
|
insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_caret_column(cc + caret_move_offset);
|
set_caret_column(cc + caret_move_offset, i == 0, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
insert_text_at_caret(chr);
|
insert_text_at_caret(chr, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((is_overtype_mode_enabled() && !had_selection) || (had_selection)) {
|
|
||||||
end_complex_operation();
|
|
||||||
}
|
}
|
||||||
|
end_action();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEdit::_backspace_internal(int p_caret) {
|
void CodeEdit::_backspace_internal(int p_caret) {
|
||||||
@@ -684,15 +686,22 @@ void CodeEdit::_backspace_internal(int p_caret) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cc = get_caret_column();
|
begin_complex_operation();
|
||||||
int cl = get_caret_line();
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
|
for (const int &i : caret_edit_order) {
|
||||||
|
if (p_caret != -1 && p_caret != i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cc = get_caret_column(i);
|
||||||
|
int cl = get_caret_line(i);
|
||||||
|
|
||||||
if (cc == 0 && cl == 0) {
|
if (cc == 0 && cl == 0) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl > 0 && _is_line_hidden(cl - 1)) {
|
if (cl > 0 && _is_line_hidden(cl - 1)) {
|
||||||
unfold_line(get_caret_line() - 1);
|
unfold_line(get_caret_line(i) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int prev_line = cc ? cl : cl - 1;
|
int prev_line = cc ? cl : cl - 1;
|
||||||
@@ -710,9 +719,11 @@ void CodeEdit::_backspace_internal(int p_caret) {
|
|||||||
} else {
|
} else {
|
||||||
remove_text(prev_line, prev_column, cl, cc);
|
remove_text(prev_line, prev_column, cl, cc);
|
||||||
}
|
}
|
||||||
set_caret_line(prev_line, false, true);
|
set_caret_line(prev_line, false, true, 0, i);
|
||||||
set_caret_column(prev_column);
|
set_caret_column(prev_column, i == 0, i);
|
||||||
return;
|
|
||||||
|
adjust_carets_after_edit(i, prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,8 +738,13 @@ void CodeEdit::_backspace_internal(int p_caret) {
|
|||||||
|
|
||||||
remove_text(prev_line, prev_column, cl, cc);
|
remove_text(prev_line, prev_column, cl, cc);
|
||||||
|
|
||||||
set_caret_line(prev_line, false, true);
|
set_caret_line(prev_line, false, true, 0, i);
|
||||||
set_caret_column(prev_column);
|
set_caret_column(prev_column, i == 0, i);
|
||||||
|
|
||||||
|
adjust_carets_after_edit(i, prev_line, prev_column, cl, cc);
|
||||||
|
}
|
||||||
|
merge_overlapping_carets();
|
||||||
|
end_complex_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Indent management */
|
/* Indent management */
|
||||||
@@ -803,10 +819,15 @@ void CodeEdit::do_indent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spaces_to_add = _calculate_spaces_till_next_right_indent(get_caret_column());
|
begin_complex_operation();
|
||||||
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
|
for (const int &i : caret_edit_order) {
|
||||||
|
int spaces_to_add = _calculate_spaces_till_next_right_indent(get_caret_column(i));
|
||||||
if (spaces_to_add > 0) {
|
if (spaces_to_add > 0) {
|
||||||
insert_text_at_caret(String(" ").repeat(spaces_to_add));
|
insert_text_at_caret(String(" ").repeat(spaces_to_add), i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
end_complex_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEdit::indent_lines() {
|
void CodeEdit::indent_lines() {
|
||||||
@@ -815,19 +836,20 @@ void CodeEdit::indent_lines() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
begin_complex_operation();
|
begin_complex_operation();
|
||||||
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
/* This value informs us by how much we changed selection position by indenting right. */
|
for (const int &c : caret_edit_order) {
|
||||||
/* Default is 1 for tab indentation. */
|
// This value informs us by how much we changed selection position by indenting right.
|
||||||
|
// Default is 1 for tab indentation.
|
||||||
int selection_offset = 1;
|
int selection_offset = 1;
|
||||||
|
|
||||||
int start_line = get_caret_line();
|
int start_line = get_caret_line(c);
|
||||||
int end_line = start_line;
|
int end_line = start_line;
|
||||||
if (has_selection()) {
|
if (has_selection(c)) {
|
||||||
start_line = get_selection_from_line();
|
start_line = get_selection_from_line(c);
|
||||||
end_line = get_selection_to_line();
|
end_line = get_selection_to_line(c);
|
||||||
|
|
||||||
/* Ignore the last line if the selection is not past the first column. */
|
// Ignore the last line if the selection is not past the first column.
|
||||||
if (get_selection_to_column() == 0) {
|
if (get_selection_to_column(c) == 0) {
|
||||||
selection_offset = 0;
|
selection_offset = 0;
|
||||||
end_line--;
|
end_line--;
|
||||||
}
|
}
|
||||||
@@ -835,7 +857,7 @@ void CodeEdit::indent_lines() {
|
|||||||
|
|
||||||
for (int i = start_line; i <= end_line; i++) {
|
for (int i = start_line; i <= end_line; i++) {
|
||||||
const String line_text = get_line(i);
|
const String line_text = get_line(i);
|
||||||
if (line_text.size() == 0 && has_selection()) {
|
if (line_text.size() == 0 && has_selection(c)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,19 +866,19 @@ void CodeEdit::indent_lines() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't really care where selection is - we just need to know indentation level at the beginning of the line. */
|
// We don't really care where selection is - we just need to know indentation level at the beginning of the line.
|
||||||
/* Since we will add this many spaces, we want to move the whole selection and caret by this much. */
|
// Since we will add this many spaces, we want to move the whole selection and caret by this much.
|
||||||
int spaces_to_add = _calculate_spaces_till_next_right_indent(get_first_non_whitespace_column(i));
|
int spaces_to_add = _calculate_spaces_till_next_right_indent(get_first_non_whitespace_column(i));
|
||||||
set_line(i, String(" ").repeat(spaces_to_add) + line_text);
|
set_line(i, String(" ").repeat(spaces_to_add) + line_text);
|
||||||
selection_offset = spaces_to_add;
|
selection_offset = spaces_to_add;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix selection and caret being off after shifting selection right.*/
|
// Fix selection and caret being off after shifting selection right.
|
||||||
if (has_selection()) {
|
if (has_selection(c)) {
|
||||||
select(start_line, get_selection_from_column() + selection_offset, get_selection_to_line(), get_selection_to_column() + selection_offset);
|
select(start_line, get_selection_from_column(c) + selection_offset, get_selection_to_line(c), get_selection_to_column(c) + selection_offset, c);
|
||||||
|
}
|
||||||
|
set_caret_column(get_caret_column(c) + selection_offset, false, c);
|
||||||
}
|
}
|
||||||
set_caret_column(get_caret_column() + selection_offset, false);
|
|
||||||
|
|
||||||
end_complex_operation();
|
end_complex_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,17 +894,21 @@ void CodeEdit::do_unindent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cl = get_caret_line();
|
begin_complex_operation();
|
||||||
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
|
for (const int &c : caret_edit_order) {
|
||||||
|
int cl = get_caret_line(c);
|
||||||
const String &line = get_line(cl);
|
const String &line = get_line(cl);
|
||||||
|
|
||||||
if (line[cc - 1] == '\t') {
|
if (line[cc - 1] == '\t') {
|
||||||
remove_text(cl, cc - 1, cl, cc);
|
remove_text(cl, cc - 1, cl, cc);
|
||||||
set_caret_column(MAX(0, cc - 1));
|
set_caret_column(MAX(0, cc - 1), c == 0, c);
|
||||||
return;
|
adjust_carets_after_edit(c, cl, cc, cl, cc - 1);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line[cc - 1] != ' ') {
|
if (line[cc - 1] != ' ') {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spaces_to_remove = _calculate_spaces_till_next_left_indent(cc);
|
int spaces_to_remove = _calculate_spaces_till_next_left_indent(cc);
|
||||||
@@ -894,8 +920,10 @@ void CodeEdit::do_unindent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
remove_text(cl, cc - spaces_to_remove, cl, cc);
|
remove_text(cl, cc - spaces_to_remove, cl, cc);
|
||||||
set_caret_column(MAX(0, cc - spaces_to_remove));
|
set_caret_column(MAX(0, cc - spaces_to_remove), c == 0, c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
end_complex_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEdit::unindent_lines() {
|
void CodeEdit::unindent_lines() {
|
||||||
@@ -905,21 +933,23 @@ void CodeEdit::unindent_lines() {
|
|||||||
|
|
||||||
begin_complex_operation();
|
begin_complex_operation();
|
||||||
|
|
||||||
/* Moving caret and selection after unindenting can get tricky because */
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
/* changing content of line can move caret and selection on its own (if new line ends before previous position of either), */
|
for (const int &c : caret_edit_order) {
|
||||||
/* therefore we just remember initial values and at the end of the operation offset them by number of removed characters. */
|
// Moving caret and selection after unindenting can get tricky because
|
||||||
|
// changing content of line can move caret and selection on its own (if new line ends before previous position of either)
|
||||||
|
// therefore we just remember initial values and at the end of the operation offset them by number of removed characters.
|
||||||
int removed_characters = 0;
|
int removed_characters = 0;
|
||||||
int initial_selection_end_column = 0;
|
int initial_selection_end_column = 0;
|
||||||
int initial_cursor_column = get_caret_column();
|
int initial_cursor_column = get_caret_column(c);
|
||||||
|
|
||||||
int start_line = get_caret_line();
|
int start_line = get_caret_line(c);
|
||||||
int end_line = start_line;
|
int end_line = start_line;
|
||||||
if (has_selection()) {
|
if (has_selection(c)) {
|
||||||
start_line = get_selection_from_line();
|
start_line = get_selection_from_line(c);
|
||||||
end_line = get_selection_to_line();
|
end_line = get_selection_to_line(c);
|
||||||
|
|
||||||
/* Ignore the last line if the selection is not past the first column. */
|
// Ignore the last line if the selection is not past the first column.
|
||||||
initial_selection_end_column = get_selection_to_column();
|
initial_selection_end_column = get_selection_to_column(c);
|
||||||
if (initial_selection_end_column == 0) {
|
if (initial_selection_end_column == 0) {
|
||||||
end_line--;
|
end_line--;
|
||||||
}
|
}
|
||||||
@@ -943,9 +973,9 @@ void CodeEdit::unindent_lines() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (line_text.begins_with(" ")) {
|
if (line_text.begins_with(" ")) {
|
||||||
/* When unindenting we aim to remove spaces before line that has selection no matter what is selected, */
|
// When unindenting we aim to remove spaces before line that has selection no matter what is selected.
|
||||||
/* Here we remove only enough spaces to align text to nearest full multiple of indentation_size. */
|
// Here we remove only enough spaces to align text to nearest full multiple of indentation_size.
|
||||||
/* In case where selection begins at the start of indentation_size multiple we remove whole indentation level. */
|
// In case where selection begins at the start of indentation_size multiple we remove whole indentation level.
|
||||||
int spaces_to_remove = _calculate_spaces_till_next_left_indent(get_first_non_whitespace_column(i));
|
int spaces_to_remove = _calculate_spaces_till_next_left_indent(get_first_non_whitespace_column(i));
|
||||||
line_text = line_text.substr(spaces_to_remove, line_text.length());
|
line_text = line_text.substr(spaces_to_remove, line_text.length());
|
||||||
|
|
||||||
@@ -957,19 +987,19 @@ void CodeEdit::unindent_lines() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_selection()) {
|
if (has_selection(c)) {
|
||||||
/* Fix selection being off by one on the first line. */
|
// Fix selection being off by one on the first line.
|
||||||
if (first_line_edited) {
|
if (first_line_edited) {
|
||||||
select(get_selection_from_line(), get_selection_from_column() - removed_characters, get_selection_to_line(), initial_selection_end_column);
|
select(get_selection_from_line(c), get_selection_from_column(c) - removed_characters, get_selection_to_line(c), initial_selection_end_column, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix selection being off by one on the last line. */
|
// Fix selection being off by one on the last line.
|
||||||
if (last_line_edited) {
|
if (last_line_edited) {
|
||||||
select(get_selection_from_line(), get_selection_from_column(), get_selection_to_line(), initial_selection_end_column - removed_characters);
|
select(get_selection_from_line(c), get_selection_from_column(c), get_selection_to_line(c), initial_selection_end_column - removed_characters, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_caret_column(initial_cursor_column - removed_characters, false);
|
set_caret_column(initial_cursor_column - removed_characters, false, c);
|
||||||
|
}
|
||||||
end_complex_operation();
|
end_complex_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -990,15 +1020,18 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When not splitting the line, we need to factor in indentation from the end of the current line. */
|
begin_complex_operation();
|
||||||
const int cc = p_split_current_line ? get_caret_column() : get_line(get_caret_line()).length();
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
const int cl = get_caret_line();
|
for (const int &i : caret_edit_order) {
|
||||||
|
// When not splitting the line, we need to factor in indentation from the end of the current line.
|
||||||
|
const int cc = p_split_current_line ? get_caret_column(i) : get_line(get_caret_line(i)).length();
|
||||||
|
const int cl = get_caret_line(i);
|
||||||
|
|
||||||
const String line = get_line(cl);
|
const String line = get_line(cl);
|
||||||
|
|
||||||
String ins = "\n";
|
String ins = "\n";
|
||||||
|
|
||||||
/* Append current indentation. */
|
// Append current indentation.
|
||||||
int space_count = 0;
|
int space_count = 0;
|
||||||
int line_col = 0;
|
int line_col = 0;
|
||||||
for (; line_col < cc; line_col++) {
|
for (; line_col < cc; line_col++) {
|
||||||
@@ -1024,9 +1057,9 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
|||||||
unfold_line(cl);
|
unfold_line(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Indent once again if the previous line needs it, ie ':'. */
|
// Indent once again if the previous line needs it, ie ':'.
|
||||||
/* Then add an addition new line for any closing pairs aka '()'. */
|
// Then add an addition new line for any closing pairs aka '()'.
|
||||||
/* Skip this in comments or if we are going above. */
|
// Skip this in comments or if we are going above.
|
||||||
bool brace_indent = false;
|
bool brace_indent = false;
|
||||||
if (auto_indent && !p_above && cc > 0 && is_in_comment(cl) == -1) {
|
if (auto_indent && !p_above && cc > 0 && is_in_comment(cl) == -1) {
|
||||||
bool should_indent = false;
|
bool should_indent = false;
|
||||||
@@ -1040,8 +1073,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure this is the last char, trailing whitespace or comments are okay. */
|
// Make sure this is the last char, trailing whitespace or comments are okay.
|
||||||
/* Increment column for comments because the delimiter (#) should be ignored. */
|
// Increment column for comments because the delimiter (#) should be ignored.
|
||||||
if (should_indent && (!is_whitespace(c) && is_in_comment(cl, line_col + 1) == -1)) {
|
if (should_indent && (!is_whitespace(c) && is_in_comment(cl, line_col + 1) == -1)) {
|
||||||
should_indent = false;
|
should_indent = false;
|
||||||
}
|
}
|
||||||
@@ -1052,7 +1085,7 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
|||||||
|
|
||||||
String closing_pair = get_auto_brace_completion_close_key(String::chr(indent_char));
|
String closing_pair = get_auto_brace_completion_close_key(String::chr(indent_char));
|
||||||
if (!closing_pair.is_empty() && line.find(closing_pair, cc) == cc) {
|
if (!closing_pair.is_empty() && line.find(closing_pair, cc) == cc) {
|
||||||
/* No need to move the brace below if we are not taking the text with us. */
|
// No need to move the brace below if we are not taking the text with us.
|
||||||
if (p_split_current_line) {
|
if (p_split_current_line) {
|
||||||
brace_indent = true;
|
brace_indent = true;
|
||||||
ins += "\n" + ins.substr(indent_text.size(), ins.length() - 2);
|
ins += "\n" + ins.substr(indent_text.size(), ins.length() - 2);
|
||||||
@@ -1064,32 +1097,31 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_complex_operation();
|
|
||||||
|
|
||||||
bool first_line = false;
|
bool first_line = false;
|
||||||
if (!p_split_current_line) {
|
if (!p_split_current_line) {
|
||||||
deselect();
|
deselect(i);
|
||||||
|
|
||||||
if (p_above) {
|
if (p_above) {
|
||||||
if (cl > 0) {
|
if (cl > 0) {
|
||||||
set_caret_line(cl - 1, false);
|
set_caret_line(cl - 1, false, true, 0, i);
|
||||||
set_caret_column(get_line(get_caret_line()).length());
|
set_caret_column(get_line(get_caret_line(i)).length(), i == 0, i);
|
||||||
} else {
|
} else {
|
||||||
set_caret_column(0);
|
set_caret_column(0, i == 0, i);
|
||||||
first_line = true;
|
first_line = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
set_caret_column(line.length());
|
set_caret_column(line.length(), i == 0, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_text_at_caret(ins);
|
insert_text_at_caret(ins, i);
|
||||||
|
|
||||||
if (first_line) {
|
if (first_line) {
|
||||||
set_caret_line(0);
|
set_caret_line(0, i == 0, true, 0, i);
|
||||||
} else if (brace_indent) {
|
} else if (brace_indent) {
|
||||||
set_caret_line(get_caret_line() - 1, false);
|
set_caret_line(get_caret_line(i) - 1, false, true, 0, i);
|
||||||
set_caret_column(get_line(get_caret_line()).length());
|
set_caret_column(get_line(get_caret_line(i)).length(), i == 0, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end_complex_operation();
|
end_complex_operation();
|
||||||
@@ -1522,22 +1554,26 @@ void CodeEdit::fold_line(int p_line) {
|
|||||||
_set_line_as_hidden(i, true);
|
_set_line_as_hidden(i, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix selection. */
|
for (int i = 0; i < get_caret_count(); i++) {
|
||||||
if (has_selection()) {
|
// Fix selection.
|
||||||
if (_is_line_hidden(get_selection_from_line()) && _is_line_hidden(get_selection_to_line())) {
|
if (has_selection(i)) {
|
||||||
deselect();
|
if (_is_line_hidden(get_selection_from_line(i)) && _is_line_hidden(get_selection_to_line(i))) {
|
||||||
} else if (_is_line_hidden(get_selection_from_line())) {
|
deselect(i);
|
||||||
select(p_line, 9999, get_selection_to_line(), get_selection_to_column());
|
} else if (_is_line_hidden(get_selection_from_line(i))) {
|
||||||
} else if (_is_line_hidden(get_selection_to_line())) {
|
select(p_line, 9999, get_selection_to_line(i), get_selection_to_column(i), i);
|
||||||
select(get_selection_from_line(), get_selection_from_column(), p_line, 9999);
|
} else if (_is_line_hidden(get_selection_to_line(i))) {
|
||||||
|
select(get_selection_from_line(i), get_selection_from_column(i), p_line, 9999, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset caret. */
|
// Reset caret.
|
||||||
if (_is_line_hidden(get_caret_line())) {
|
if (_is_line_hidden(get_caret_line(i))) {
|
||||||
set_caret_line(p_line, false, false);
|
set_caret_line(p_line, false, false, 0, i);
|
||||||
set_caret_column(get_line(p_line).length(), false);
|
set_caret_column(get_line(p_line).length(), false, i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_overlapping_carets();
|
||||||
queue_redraw();
|
queue_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1950,17 +1986,19 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char32_t caret_last_completion_char;
|
||||||
begin_complex_operation();
|
begin_complex_operation();
|
||||||
|
Vector<int> caret_edit_order = get_caret_index_edit_order();
|
||||||
int caret_line = get_caret_line();
|
for (const int &i : caret_edit_order) {
|
||||||
|
int caret_line = get_caret_line(i);
|
||||||
|
|
||||||
const String &insert_text = code_completion_options[code_completion_current_selected].insert_text;
|
const String &insert_text = code_completion_options[code_completion_current_selected].insert_text;
|
||||||
const String &display_text = code_completion_options[code_completion_current_selected].display;
|
const String &display_text = code_completion_options[code_completion_current_selected].display;
|
||||||
|
|
||||||
if (p_replace) {
|
if (p_replace) {
|
||||||
/* Find end of current section */
|
// Find end of current section.
|
||||||
const String line = get_line(caret_line);
|
const String line = get_line(caret_line);
|
||||||
int caret_col = get_caret_column();
|
int caret_col = get_caret_column(i);
|
||||||
int caret_remove_line = caret_line;
|
int caret_remove_line = caret_line;
|
||||||
|
|
||||||
bool merge_text = true;
|
bool merge_text = true;
|
||||||
@@ -1982,14 +2020,15 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace. */
|
// Replace.
|
||||||
remove_text(caret_line, get_caret_column() - code_completion_base.length(), caret_remove_line, caret_col);
|
remove_text(caret_line, get_caret_column(i) - code_completion_base.length(), caret_remove_line, caret_col);
|
||||||
set_caret_column(get_caret_column() - code_completion_base.length(), false);
|
adjust_carets_after_edit(i, caret_line, caret_col - code_completion_base.length(), caret_remove_line, caret_col);
|
||||||
insert_text_at_caret(insert_text);
|
set_caret_column(get_caret_column(i) - code_completion_base.length(), false, i);
|
||||||
|
insert_text_at_caret(insert_text, i);
|
||||||
} else {
|
} else {
|
||||||
/* Get first non-matching char. */
|
// Get first non-matching char.
|
||||||
const String line = get_line(caret_line);
|
const String line = get_line(caret_line);
|
||||||
int caret_col = get_caret_column();
|
int caret_col = get_caret_column(i);
|
||||||
int matching_chars = code_completion_base.length();
|
int matching_chars = code_completion_base.length();
|
||||||
for (; matching_chars <= insert_text.length(); matching_chars++) {
|
for (; matching_chars <= insert_text.length(); matching_chars++) {
|
||||||
if (caret_col >= line.length() || line[caret_col] != insert_text[matching_chars]) {
|
if (caret_col >= line.length() || line[caret_col] != insert_text[matching_chars]) {
|
||||||
@@ -1998,50 +2037,57 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
|
|||||||
caret_col++;
|
caret_col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove base completion text. */
|
// Remove base completion text.
|
||||||
remove_text(caret_line, get_caret_column() - code_completion_base.length(), caret_line, get_caret_column());
|
remove_text(caret_line, get_caret_column(i) - code_completion_base.length(), caret_line, get_caret_column(i));
|
||||||
set_caret_column(get_caret_column() - code_completion_base.length(), false);
|
adjust_carets_after_edit(i, caret_line, get_caret_column(i) - code_completion_base.length(), caret_line, get_caret_column(i));
|
||||||
|
set_caret_column(get_caret_column(i) - code_completion_base.length(), false, i);
|
||||||
|
|
||||||
/* Merge with text. */
|
// Merge with text.
|
||||||
insert_text_at_caret(insert_text.substr(0, code_completion_base.length()));
|
insert_text_at_caret(insert_text.substr(0, code_completion_base.length()), i);
|
||||||
set_caret_column(caret_col, false);
|
set_caret_column(caret_col, false, i);
|
||||||
insert_text_at_caret(insert_text.substr(matching_chars));
|
insert_text_at_caret(insert_text.substr(matching_chars), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle merging of symbols eg strings, brackets. */
|
//* Handle merging of symbols eg strings, brackets.
|
||||||
const String line = get_line(caret_line);
|
const String line = get_line(caret_line);
|
||||||
char32_t next_char = line[get_caret_column()];
|
char32_t next_char = line[get_caret_column(i)];
|
||||||
char32_t last_completion_char = insert_text[insert_text.length() - 1];
|
char32_t last_completion_char = insert_text[insert_text.length() - 1];
|
||||||
|
if (i == 0) {
|
||||||
|
caret_last_completion_char = last_completion_char;
|
||||||
|
}
|
||||||
char32_t last_completion_char_display = display_text[display_text.length() - 1];
|
char32_t last_completion_char_display = display_text[display_text.length() - 1];
|
||||||
|
|
||||||
int pre_brace_pair = get_caret_column() > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column()) : -1;
|
int pre_brace_pair = get_caret_column(i) > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column(i)) : -1;
|
||||||
int post_brace_pair = get_caret_column() < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column()) : -1;
|
int post_brace_pair = get_caret_column(i) < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column(i)) : -1;
|
||||||
|
|
||||||
if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
||||||
remove_text(caret_line, get_caret_column(), caret_line, get_caret_column() + 1);
|
remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
|
||||||
|
adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
|
||||||
remove_text(caret_line, get_caret_column(), caret_line, get_caret_column() + 1);
|
remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
|
||||||
|
adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
|
||||||
} else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
|
} else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
|
||||||
insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key);
|
insert_text_at_caret(auto_brace_completion_pairs[pre_brace_pair].close_key, i);
|
||||||
set_caret_column(get_caret_column() - auto_brace_completion_pairs[pre_brace_pair].close_key.length());
|
set_caret_column(get_caret_column(i) - auto_brace_completion_pairs[pre_brace_pair].close_key.length(), i == 0, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column() > 0 && get_caret_column() < get_line(caret_line).length()) {
|
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column(i) > 0 && get_caret_column(i) < get_line(caret_line).length()) {
|
||||||
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column() + 1);
|
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column(i) + 1);
|
||||||
if (pre_brace_pair != -1 && 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(i) - 1)) {
|
||||||
remove_text(caret_line, get_caret_column() - 2, caret_line, get_caret_column());
|
remove_text(caret_line, get_caret_column(i) - 2, caret_line, get_caret_column(i));
|
||||||
if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1) != pre_brace_pair) {
|
adjust_carets_after_edit(i, caret_line, get_caret_column(i) - 2, caret_line, get_caret_column(i));
|
||||||
set_caret_column(get_caret_column() - 1);
|
if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column(i) - 1) != pre_brace_pair) {
|
||||||
|
set_caret_column(get_caret_column(i) - 1, i == 0, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end_complex_operation();
|
end_complex_operation();
|
||||||
|
|
||||||
cancel_code_completion();
|
cancel_code_completion();
|
||||||
if (code_completion_prefixes.has(last_completion_char)) {
|
if (code_completion_prefixes.has(caret_last_completion_char)) {
|
||||||
request_code_completion();
|
request_code_completion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2399,6 +2445,7 @@ void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p_gutter == line_number_gutter) {
|
if (p_gutter == line_number_gutter) {
|
||||||
|
remove_secondary_carets();
|
||||||
set_selection_mode(TextEdit::SelectionMode::SELECTION_MODE_LINE, p_line, 0);
|
set_selection_mode(TextEdit::SelectionMode::SELECTION_MODE_LINE, p_line, 0);
|
||||||
select(p_line, 0, p_line + 1, 0);
|
select(p_line, 0, p_line + 1, 0);
|
||||||
set_caret_line(p_line + 1);
|
set_caret_line(p_line + 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user