summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2012-01-04 14:18:08 +0000
committerMaxime Coste <frrrwww@gmail.com>2012-01-04 14:18:08 +0000
commit8b1b1d9cd83d3c6b6fa1c0e4a2adb02ab585a985 (patch)
tree14f5e45bb72db18d415aa169fd6d9630ce29abb3 /src
parente59bdd931e6fa3d4e0c9b7a5d97ca559f894a391 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/main.cc27
-rw-r--r--src/selectors.cc49
-rw-r--r--src/selectors.hh3
3 files changed, 79 insertions, 0 deletions
diff --git a/src/main.cc b/src/main.cc
index 1501b78c..ce89d0ee 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -708,6 +708,30 @@ void do_join(Window& window, int count)
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 =
{
{ { 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.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, '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); } },
diff --git a/src/selectors.cc b/src/selectors.cc
index 9266514b..342b2170 100644
--- a/src/selectors.cc
+++ b/src/selectors.cc
@@ -242,6 +242,55 @@ Selection select_matching(const BufferIterator& 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)
{
BufferIterator end = cursor;
diff --git a/src/selectors.hh b/src/selectors.hh
index a092e869..79fb53e9 100644
--- a/src/selectors.hh
+++ b/src/selectors.hh
@@ -14,6 +14,9 @@ Selection select_to_next_WORD_end(const BufferIterator& cursor);
Selection select_to_previous_WORD(const BufferIterator& cursor);
Selection select_line(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_reverse(const BufferIterator& cursor, char c, int count, bool inclusive);