Browse Source

Improved extend selection for non-bracket languages like Python and Julia

merge-requests/404/merge
eidheim 5 years ago
parent
commit
9a67a7557e
  1. 167
      src/source.cpp

167
src/source.cpp

@ -1548,7 +1548,7 @@ void Source::View::extend_selection() {
// Attempt to select a sentence, for instance: int a = 2;
if(!is_bracket_language) { // If for instance cmake, meson or python
if(!select_matching_brackets) {
bool select_end_block = is_language({"cmake", "meson"});
bool select_end_block = is_language({"cmake", "meson", "julia"});
auto get_tabs = [this](Gtk::TextIter iter) -> boost::optional<int> {
iter = get_buffer()->get_iter_at_line(iter.get_line());
@ -1563,94 +1563,134 @@ void Source::View::extend_selection() {
return tabs;
};
// Forward start to non-empty line
start = start_stored;
end = end_stored;
if(start == get_buffer()->begin() && end == get_buffer()->end()) {
get_buffer()->select_range(start, end);
return;
}
// Select following line with code (for instance when inside comment)
// Forward start to non-empty line
forward_to_code(start);
start = get_buffer()->get_iter_at_line(start.get_line());
while(!start.is_end() && (*start == ' ' || *start == '\t') && start.forward_char()) {
}
// Forward end to end of line
end = end_stored;
// Forward end of line
if(start > end)
end = start;
if(!end.ends_line())
end.forward_to_line_end();
end = get_iter_at_line_end(end.get_line());
while(end.backward_char() && (*end == ' ' || *end == '\t' || end.ends_line())) {
}
end.forward_char();
if(end == end_stored) // Cancel line selection if the line is already selected
start = start_stored;
// Try select block that starts at cursor
auto iter = end;
if(auto end_tabs = get_tabs(end)) {
bool can_select_end_block = false;
while(iter.forward_char()) {
auto tabs = get_tabs(iter);
if(!tabs || tabs > end_tabs || (select_end_block && can_select_end_block && tabs == end_tabs)) {
if(!iter.ends_line())
iter.forward_to_line_end();
end = iter;
if(tabs > end_tabs)
can_select_end_block = true;
else if(tabs == end_tabs)
if(start != start_stored || end != end_stored) {
get_buffer()->select_range(start, end);
return;
}
// Select current line
// Backward to line start
start = get_buffer()->get_iter_at_line(start.get_line());
auto start_tabs = get_tabs(start);
while((*start == ' ' || *start == '\t' || start.ends_line()) && start.forward_char()) {
}
// Forward to line end
end = get_iter_at_line_end(end.get_line());
bool include_children = false;
if(start_tabs) {
while(end.forward_char()) {
auto tabs = get_tabs(end);
if(tabs) {
if(tabs > start_tabs)
include_children = true;
else if(tabs == start_tabs) {
if(include_children && select_end_block)
end = get_iter_at_line_end(end.get_line());
break;
continue;
}
else
break;
}
end = get_iter_at_line_end(end.get_line());
}
while(end > end_stored && end.starts_line() && end.ends_line() && end.backward_char()) {
}
// Backward end to non-empty line
while(end.backward_char() && (*end == ' ' || *end == '\t' || end.ends_line())) {
}
end.forward_char();
if(start == start_stored && end == end_stored) { // Try select block that cursor is within
// Backward start to line with less indentation
auto iter = get_buffer()->get_iter_at_line(start.get_line());
auto start_tabs = get_tabs(iter);
if(start_tabs >= 0) {
while(iter.backward_char()) {
auto tabs = get_tabs(iter);
iter = get_buffer()->get_iter_at_line(iter.get_line());
if(tabs >= 0 && tabs < start_tabs) {
start = iter;
if(start != start_stored || end != end_stored) {
get_buffer()->select_range(start, end);
return;
}
// Select block that cursor is within
// Backward start block start
if(start_tabs > 0) {
start = get_buffer()->get_iter_at_line(start.get_line());
while(start.backward_char()) {
auto tabs = get_tabs(start);
if(tabs && tabs < start_tabs)
break;
start = get_buffer()->get_iter_at_line(start.get_line());
}
while((*start == ' ' || *start == '\t' || start.ends_line()) && start.forward_char()) {
}
// Forward to block end
end = get_iter_at_line_end(end.get_line());
while(end.forward_char()) {
auto tabs = get_tabs(end);
if(tabs && tabs < start_tabs)
break;
end = get_iter_at_line_end(end.get_line());
}
// Forward start to non-empty line
start = get_buffer()->get_iter_at_line(start.get_line());
while(!start.is_end() && (*start == ' ' || *start == '\t') && start.forward_char()) {
// Backward end to non-empty line
while(end.backward_char() && (*end == ' ' || *end == '\t' || end.ends_line())) {
}
end.forward_char();
if(start != start_stored) {
// Forward end through lines with higher indentation
start_tabs = get_tabs(start);
iter = end;
if(start_tabs >= 0) {
while(iter.forward_char()) {
auto tabs = get_tabs(iter);
if(tabs < 0 || tabs > start_tabs || (select_end_block && tabs == start_tabs)) {
if(!iter.ends_line())
iter.forward_to_line_end();
end = iter;
if(tabs == start_tabs)
break;
continue;
if(start != start_stored || end != end_stored) {
get_buffer()->select_range(start, end);
return;
}
break;
// Select expression surrounding block
// Backward to expression starting block
if(start.backward_char()) {
backward_to_code(start);
if(start_tabs > get_tabs(start)) {
start = get_buffer()->get_iter_at_line(start.get_line());
while((*start == ' ' || *start == '\t' || start.ends_line()) && start.forward_char()) {
}
}
while(end > end_stored && end.starts_line() && end.ends_line() && end.backward_char()) {
else
start = start_stored;
}
// Forward to expression ending block
if(select_end_block) {
forward_to_code(end);
if(start_tabs > get_tabs(end)) {
end = get_iter_at_line_end(end.get_line());
while(end.backward_char() && (*end == ' ' || *end == '\t' || end.ends_line())) {
}
end.forward_char();
}
else
end = end_stored;
}
if(start == start_stored && end == end_stored) {
start = get_buffer()->begin();
end = get_buffer()->end();
if(start != start_stored || end != end_stored) {
get_buffer()->select_range(start, end);
return;
}
}
// Select no_spellcheck_tag block if markdown
if(no_spellcheck_tag && language_id == "markdown" && start_stored.has_tag(no_spellcheck_tag) && end_stored.has_tag(no_spellcheck_tag) &&
(!start.has_tag(no_spellcheck_tag) || !end.has_tag(no_spellcheck_tag))) {
start = start_stored;
end = end_stored;
if(language_id == "markdown" && no_spellcheck_tag && start.has_tag(no_spellcheck_tag) && end.has_tag(no_spellcheck_tag)) {
if(!start.starts_tag(no_spellcheck_tag))
start.backward_to_tag_toggle(no_spellcheck_tag);
if(!end.ends_tag(no_spellcheck_tag))
@ -1667,13 +1707,13 @@ void Source::View::extend_selection() {
if(!end.ends_line())
end.forward_char();
if(start == start_stored && end == end_stored) {
start = get_buffer()->begin();
end = get_buffer()->end();
if(start != start_stored || end != end_stored) {
get_buffer()->select_range(start, end);
return;
}
}
get_buffer()->select_range(start, end);
get_buffer()->select_range(get_buffer()->begin(), get_buffer()->end());
return;
}
}
@ -1709,9 +1749,8 @@ void Source::View::extend_selection() {
if(start == start_stored && end == end_stored) { // In case of no change due to inbalanced brackets
previous_extended_selections.pop_back();
if(!start.backward_char() && !end.forward_char()) {
if(!start.backward_char() && !end.forward_char())
return;
}
get_buffer()->select_range(start, end);
extend_selection();
return;

Loading…
Cancel
Save