Selectors: add select_surrounding to select blocks
Alt-a followed by []()<>{}bB selects the block surrounding current selection end. Alt-i is similar but selects only the inside of the block.
This commit is contained in:
parent
e59bdd931e
commit
8b1b1d9cd8
27
src/main.cc
27
src/main.cc
|
@ -708,6 +708,30 @@ void do_join(Window& window, int count)
|
||||||
window.move_cursor({0, -1});
|
window.move_cursor({0, -1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool inside>
|
||||||
|
void do_select_surrounding(Window& window, int count)
|
||||||
|
{
|
||||||
|
char id = getch();
|
||||||
|
|
||||||
|
static const std::unordered_map<char, std::pair<char, char>> id_to_matching =
|
||||||
|
{
|
||||||
|
{ '(', { '(', ')' } },
|
||||||
|
{ ')', { '(', ')' } },
|
||||||
|
{ 'b', { '(', ')' } },
|
||||||
|
{ '{', { '{', '}' } },
|
||||||
|
{ '}', { '{', '}' } },
|
||||||
|
{ 'B', { '{', '}' } },
|
||||||
|
{ '[', { '[', ']' } },
|
||||||
|
{ ']', { '[', ']' } },
|
||||||
|
{ '<', { '<', '>' } },
|
||||||
|
{ '>', { '<', '>' } }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto matching = id_to_matching.find(id);
|
||||||
|
if (matching != id_to_matching.end())
|
||||||
|
window.select(std::bind(select_surrounding, _1, matching->second, inside));
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<Key, std::function<void (Window& window, int count)>> keymap =
|
std::unordered_map<Key, std::function<void (Window& window, int count)>> keymap =
|
||||||
{
|
{
|
||||||
{ { Key::Modifiers::None, 'h' }, [](Window& window, int count) { window.move_cursor(DisplayCoord(0, -std::max(count,1))); } },
|
{ { Key::Modifiers::None, 'h' }, [](Window& window, int count) { window.move_cursor(DisplayCoord(0, -std::max(count,1))); } },
|
||||||
|
@ -767,6 +791,9 @@ std::unordered_map<Key, std::function<void (Window& window, int count)>> keymap
|
||||||
{ { Key::Modifiers::None, 'u' }, [](Window& window, int count) { do { if (not window.undo()) { print_status("nothing left to undo"); break; } } while(--count > 0); } },
|
{ { Key::Modifiers::None, 'u' }, [](Window& window, int count) { do { if (not window.undo()) { print_status("nothing left to undo"); break; } } while(--count > 0); } },
|
||||||
{ { Key::Modifiers::None, 'U' }, [](Window& window, int count) { do { if (not window.redo()) { print_status("nothing left to redo"); break; } } while(--count > 0); } },
|
{ { Key::Modifiers::None, 'U' }, [](Window& window, int count) { do { if (not window.redo()) { print_status("nothing left to redo"); break; } } while(--count > 0); } },
|
||||||
|
|
||||||
|
{ { Key::Modifiers::Alt, 'i' }, do_select_surrounding<true> },
|
||||||
|
{ { Key::Modifiers::Alt, 'a' }, do_select_surrounding<false> },
|
||||||
|
|
||||||
{ { Key::Modifiers::Alt, 't' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, false)); } },
|
{ { Key::Modifiers::Alt, 't' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, false)); } },
|
||||||
{ { Key::Modifiers::Alt, 'f' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, true)); } },
|
{ { Key::Modifiers::Alt, 'f' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, true)); } },
|
||||||
{ { Key::Modifiers::Alt, 'T' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, false), true); } },
|
{ { Key::Modifiers::Alt, 'T' }, [](Window& window, int count) { window.select(std::bind(select_to_reverse, _1, getch(), count, false), true); } },
|
||||||
|
|
|
@ -242,6 +242,55 @@ Selection select_matching(const BufferIterator& cursor)
|
||||||
return Selection(cursor, cursor);
|
return Selection(cursor, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Selection select_surrounding(const BufferIterator& cursor,
|
||||||
|
const std::pair<char, char>& matching,
|
||||||
|
bool inside)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
BufferIterator first = cursor;
|
||||||
|
while (not first.is_begin())
|
||||||
|
{
|
||||||
|
if (*first == matching.second)
|
||||||
|
++level;
|
||||||
|
else if (*first == matching.first)
|
||||||
|
{
|
||||||
|
if (level == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
--level;
|
||||||
|
}
|
||||||
|
--first;
|
||||||
|
}
|
||||||
|
if (level != 0 or *first != matching.first)
|
||||||
|
return Selection(cursor, cursor);
|
||||||
|
|
||||||
|
level = 0;
|
||||||
|
BufferIterator last = first + 1;
|
||||||
|
while (not last.is_end())
|
||||||
|
{
|
||||||
|
if (*last == matching.first)
|
||||||
|
++level;
|
||||||
|
else if (*last == matching.second)
|
||||||
|
{
|
||||||
|
if (level == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
--level;
|
||||||
|
}
|
||||||
|
++last;
|
||||||
|
}
|
||||||
|
if (level != 0 or *last != matching.second)
|
||||||
|
return Selection(cursor, cursor);
|
||||||
|
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
++first;
|
||||||
|
if (first != last)
|
||||||
|
--last;
|
||||||
|
}
|
||||||
|
return Selection(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
Selection select_to(const BufferIterator& cursor, char c, int count, bool inclusive)
|
Selection select_to(const BufferIterator& cursor, char c, int count, bool inclusive)
|
||||||
{
|
{
|
||||||
BufferIterator end = cursor;
|
BufferIterator end = cursor;
|
||||||
|
|
|
@ -14,6 +14,9 @@ Selection select_to_next_WORD_end(const BufferIterator& cursor);
|
||||||
Selection select_to_previous_WORD(const BufferIterator& cursor);
|
Selection select_to_previous_WORD(const BufferIterator& cursor);
|
||||||
Selection select_line(const BufferIterator& cursor);
|
Selection select_line(const BufferIterator& cursor);
|
||||||
Selection select_matching(const BufferIterator& cursor);
|
Selection select_matching(const BufferIterator& cursor);
|
||||||
|
Selection select_surrounding(const BufferIterator& cursor,
|
||||||
|
const std::pair<char, char>& matching,
|
||||||
|
bool inside);
|
||||||
|
|
||||||
Selection select_to(const BufferIterator& cursor, char c, int count, bool inclusive);
|
Selection select_to(const BufferIterator& cursor, char c, int count, bool inclusive);
|
||||||
Selection select_to_reverse(const BufferIterator& cursor, char c, int count, bool inclusive);
|
Selection select_to_reverse(const BufferIterator& cursor, char c, int count, bool inclusive);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user