diff --git a/src/main.cc b/src/main.cc index 0be62ce38..7faf87127 100644 --- a/src/main.cc +++ b/src/main.cc @@ -691,29 +691,30 @@ void do_join(Editor& editor, int count) editor.move_selections({0, -1}); } -template -void do_select_surrounding(Editor& editor, int count) +template +void do_select_object(Editor& editor, int count) { - Key key = get_key(); - const char id = key.key; - - static const std::unordered_map> id_to_matching = + typedef std::function Selector; + static const std::unordered_map key_to_selector = { - { '(', { '(', ')' } }, - { ')', { '(', ')' } }, - { 'b', { '(', ')' } }, - { '{', { '{', '}' } }, - { '}', { '{', '}' } }, - { 'B', { '{', '}' } }, - { '[', { '[', ']' } }, - { ']', { '[', ']' } }, - { '<', { '<', '>' } }, - { '>', { '<', '>' } } + { { Key::Modifiers::None, '(' }, std::bind(select_surrounding, _1, std::pair{ '(', ')' }, inner) }, + { { Key::Modifiers::None, ')' }, std::bind(select_surrounding, _1, std::pair{ '(', ')' }, inner) }, + { { Key::Modifiers::None, 'b' }, std::bind(select_surrounding, _1, std::pair{ '(', ')' }, inner) }, + { { Key::Modifiers::None, '{' }, std::bind(select_surrounding, _1, std::pair{ '{', '}' }, inner) }, + { { Key::Modifiers::None, '}' }, std::bind(select_surrounding, _1, std::pair{ '{', '}' }, inner) }, + { { Key::Modifiers::None, 'B' }, std::bind(select_surrounding, _1, std::pair{ '{', '}' }, inner) }, + { { Key::Modifiers::None, '[' }, std::bind(select_surrounding, _1, std::pair{ '[', ']' }, inner) }, + { { Key::Modifiers::None, ']' }, std::bind(select_surrounding, _1, std::pair{ '[', ']' }, inner) }, + { { Key::Modifiers::None, '<' }, std::bind(select_surrounding, _1, std::pair{ '<', '>' }, inner) }, + { { Key::Modifiers::None, '>' }, std::bind(select_surrounding, _1, std::pair{ '<', '>' }, inner) }, + { { Key::Modifiers::None, 'w' }, std::bind(select_whole_word, _1, inner) }, + { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, inner) }, }; - auto matching = id_to_matching.find(id); - if (matching != id_to_matching.end()) - editor.select(std::bind(select_surrounding, _1, matching->second, inside)); + Key key = get_key(); + auto it = key_to_selector.find(key); + if (it != key_to_selector.end()) + editor.select(it->second); } std::unordered_map> keymap = @@ -779,8 +780,8 @@ std::unordered_map> keymap { { Key::Modifiers::None, 'u' }, [](Editor& editor, int count) { do { if (not editor.undo()) { NCurses::print_status("nothing left to undo"); break; } } while(--count > 0); } }, { { Key::Modifiers::None, 'U' }, [](Editor& editor, int count) { do { if (not editor.redo()) { NCurses::print_status("nothing left to redo"); break; } } while(--count > 0); } }, - { { Key::Modifiers::Alt, 'i' }, do_select_surrounding }, - { { Key::Modifiers::Alt, 'a' }, do_select_surrounding }, + { { Key::Modifiers::Alt, 'i' }, do_select_object }, + { { Key::Modifiers::Alt, 'a' }, do_select_object }, { { Key::Modifiers::Alt, 't' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, false)); } }, { { Key::Modifiers::Alt, 'f' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, true)); } }, diff --git a/src/selectors.cc b/src/selectors.cc index bb88697ff..bcad49a4c 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -319,6 +319,34 @@ SelectionAndCaptures select_to_eol_reverse(const Selection& selection) return Selection(begin, end.is_begin() ? end : end+1); } +template +SelectionAndCaptures select_whole_word(const Selection& selection, bool inner) +{ + BufferIterator first = selection.last(); + BufferIterator last = first; + if (is_word(*first)) + { + if (not skip_while_reverse(first, is_word)) + ++first; + skip_while(last, is_word); + if (not inner) + skip_while(last, is_blank); + } + else if (not inner) + { + if (not skip_while_reverse(first, is_blank)) + ++first; + skip_while(last, is_blank); + if (not is_word(*last)) + return selection; + skip_while(last, is_word); + } + --last; + return Selection(first, last); +} +template SelectionAndCaptures select_whole_word(const Selection&, bool); +template SelectionAndCaptures select_whole_word(const Selection&, bool); + SelectionAndCaptures select_whole_lines(const Selection& selection) { BufferIterator first = selection.first(); diff --git a/src/selectors.hh b/src/selectors.hh index 18588454f..c1d24e883 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -27,6 +27,8 @@ SelectionAndCaptures select_to_reverse(const Selection& selection, SelectionAndCaptures select_to_eol(const Selection& selection); SelectionAndCaptures select_to_eol_reverse(const Selection& selection); +template +SelectionAndCaptures select_whole_word(const Selection& selection, bool inner); SelectionAndCaptures select_whole_lines(const Selection& selection); SelectionAndCaptures select_whole_buffer(const Selection& selection);