factor word and WORD selectors

This commit is contained in:
Maxime Coste 2012-03-07 19:20:32 +00:00
parent 7e01867d55
commit 782b557660
3 changed files with 62 additions and 83 deletions

View File

@ -758,12 +758,12 @@ std::unordered_map<Key, std::function<void (Editor& editor, int count)>> keymap
{ { Key::Modifiers::None, '|' }, do_pipe }, { { Key::Modifiers::None, '|' }, do_pipe },
{ { Key::Modifiers::None, ' ' }, [](Editor& editor, int count) { if (count == 0) editor.clear_selections(); { { Key::Modifiers::None, ' ' }, [](Editor& editor, int count) { if (count == 0) editor.clear_selections();
else editor.keep_selection(count-1); } }, else editor.keep_selection(count-1); } },
{ { Key::Modifiers::None, 'w' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word); } while(--count > 0); } }, { { Key::Modifiers::None, 'w' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word<false>); } while(--count > 0); } },
{ { Key::Modifiers::None, 'e' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end); } while(--count > 0); } }, { { Key::Modifiers::None, 'e' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end<false>); } while(--count > 0); } },
{ { Key::Modifiers::None, 'b' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word); } while(--count > 0); } }, { { Key::Modifiers::None, 'b' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word<false>); } while(--count > 0); } },
{ { Key::Modifiers::None, 'W' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word, true); } while(--count > 0); } }, { { Key::Modifiers::None, 'W' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word<false>, true); } while(--count > 0); } },
{ { Key::Modifiers::None, 'E' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end, true); } while(--count > 0); } }, { { Key::Modifiers::None, 'E' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end<false>, true); } while(--count > 0); } },
{ { Key::Modifiers::None, 'B' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word, true); } while(--count > 0); } }, { { Key::Modifiers::None, 'B' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word<false>, true); } while(--count > 0); } },
{ { Key::Modifiers::None, 'x' }, [](Editor& editor, int count) { do { editor.select(select_line, false); } while(--count > 0); } }, { { Key::Modifiers::None, 'x' }, [](Editor& editor, int count) { do { editor.select(select_line, false); } while(--count > 0); } },
{ { Key::Modifiers::None, 'X' }, [](Editor& editor, int count) { do { editor.select(select_line, true); } while(--count > 0); } }, { { Key::Modifiers::None, 'X' }, [](Editor& editor, int count) { do { editor.select(select_line, true); } while(--count > 0); } },
{ { Key::Modifiers::None, 'm' }, [](Editor& editor, int count) { editor.select(select_matching); } }, { { Key::Modifiers::None, 'm' }, [](Editor& editor, int count) { editor.select(select_matching); } },
@ -785,12 +785,12 @@ std::unordered_map<Key, std::function<void (Editor& editor, int count)>> keymap
{ { Key::Modifiers::Alt, 'T' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, false), true); } }, { { Key::Modifiers::Alt, 'T' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, false), true); } },
{ { Key::Modifiers::Alt, 'F' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, true), true); } }, { { Key::Modifiers::Alt, 'F' }, [](Editor& editor, int count) { editor.select(std::bind(select_to_reverse, _1, get_key().key, count, true), true); } },
{ { Key::Modifiers::Alt, 'w' }, [](Editor& editor, int count) { do { editor.select(select_to_next_WORD); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'w' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word<true>); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'e' }, [](Editor& editor, int count) { do { editor.select(select_to_next_WORD_end); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'e' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end<true>); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'b' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_WORD); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'b' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word<true>); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'W' }, [](Editor& editor, int count) { do { editor.select(select_to_next_WORD, true); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'W' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word<true>, true); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'E' }, [](Editor& editor, int count) { do { editor.select(select_to_next_WORD_end, true); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'E' }, [](Editor& editor, int count) { do { editor.select(select_to_next_word_end<true>, true); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'B' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_WORD, true); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'B' }, [](Editor& editor, int count) { do { editor.select(select_to_previous_word<true>, true); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'l' }, [](Editor& editor, int count) { do { editor.select(select_to_eol, false); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'l' }, [](Editor& editor, int count) { do { editor.select(select_to_eol, false); } while(--count > 0); } },
{ { Key::Modifiers::Alt, 'L' }, [](Editor& editor, int count) { do { editor.select(select_to_eol, true); } while(--count > 0); } }, { { Key::Modifiers::Alt, 'L' }, [](Editor& editor, int count) { do { editor.select(select_to_eol, true); } while(--count > 0); } },

View File

@ -6,17 +6,24 @@
namespace Kakoune namespace Kakoune
{ {
static bool is_eol(char c) namespace
{
bool is_eol(char c)
{ {
return c == '\n'; return c == '\n';
} }
static bool is_blank(char c) bool is_blank(char c)
{ {
return c == ' ' or c == '\t'; return c == ' ' or c == '\t';
} }
static bool is_word(char c) template<bool punctuation_is_word = false>
bool is_word(char c);
template<>
bool is_word<false>(char c)
{ {
if (c >= '0' and c <= '9') if (c >= '0' and c <= '9')
return true; return true;
@ -29,6 +36,12 @@ static bool is_word(char c)
return false; return false;
} }
template<>
bool is_word<true>(char c)
{
return !is_blank(c) and !is_eol(c);
}
static bool is_punctuation(char c) static bool is_punctuation(char c)
{ {
return not (is_word(c) or is_blank(c) or is_eol(c)); return not (is_word(c) or is_blank(c) or is_eol(c));
@ -42,8 +55,8 @@ enum class CharCategories
Punctuation, Punctuation,
}; };
template<bool punctuation_is_not_word = true> template<bool punctuation_is_word = false>
static CharCategories categorize(char c) CharCategories categorize(char c)
{ {
if (is_word(c)) if (is_word(c))
return CharCategories::Word; return CharCategories::Word;
@ -51,8 +64,8 @@ static CharCategories categorize(char c)
return CharCategories::EndOfLine; return CharCategories::EndOfLine;
if (is_blank(c)) if (is_blank(c))
return CharCategories::Blank; return CharCategories::Blank;
return punctuation_is_not_word ? CharCategories::Punctuation return punctuation_is_word ? CharCategories::Word
: CharCategories::Word; : CharCategories::Punctuation;
} }
template<typename T> template<typename T>
@ -71,30 +84,37 @@ bool skip_while_reverse(BufferIterator& it, T condition)
return not it.is_end() and condition(*it); return not it.is_end() and condition(*it);
} }
}
template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection) SelectionAndCaptures select_to_next_word(const Selection& selection)
{ {
BufferIterator begin = selection.last(); BufferIterator begin = selection.last();
if (categorize(*begin) != categorize(*(begin+1))) if (categorize<punctuation_is_word>(*begin) !=
categorize<punctuation_is_word>(*(begin+1)))
++begin; ++begin;
skip_while(begin, is_eol); skip_while(begin, is_eol);
BufferIterator end = begin+1; BufferIterator end = begin+1;
if (is_punctuation(*begin)) if (not punctuation_is_word and is_punctuation(*begin))
skip_while(end, is_punctuation); skip_while(end, is_punctuation);
else if (is_word(*begin)) else if (is_word<punctuation_is_word>(*begin))
skip_while(end, is_word); skip_while(end, is_word<punctuation_is_word>);
bool with_end = skip_while(end, is_blank); bool with_end = skip_while(end, is_blank);
return Selection(begin, with_end ? end : end-1); return Selection(begin, with_end ? end : end-1);
} }
template SelectionAndCaptures select_to_next_word<false>(const Selection&);
template SelectionAndCaptures select_to_next_word<true>(const Selection&);
template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection) SelectionAndCaptures select_to_next_word_end(const Selection& selection)
{ {
BufferIterator begin = selection.last(); BufferIterator begin = selection.last();
if (categorize(*begin) != categorize(*(begin+1))) if (categorize<punctuation_is_word>(*begin) !=
categorize<punctuation_is_word>(*(begin+1)))
++begin; ++begin;
skip_while(begin, is_eol); skip_while(begin, is_eol);
@ -102,19 +122,23 @@ SelectionAndCaptures select_to_next_word_end(const Selection& selection)
skip_while(end, is_blank); skip_while(end, is_blank);
bool with_end = false; bool with_end = false;
if (is_punctuation(*end)) if (not punctuation_is_word and is_punctuation(*end))
with_end = skip_while(end, is_punctuation); with_end = skip_while(end, is_punctuation);
else if (is_word(*end)) else if (is_word<punctuation_is_word>(*end))
with_end = skip_while(end, is_word); with_end = skip_while(end, is_word<punctuation_is_word>);
return Selection(begin, with_end ? end : end-1); return Selection(begin, with_end ? end : end-1);
} }
template SelectionAndCaptures select_to_next_word_end<false>(const Selection&);
template SelectionAndCaptures select_to_next_word_end<true>(const Selection&);
template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection) SelectionAndCaptures select_to_previous_word(const Selection& selection)
{ {
BufferIterator begin = selection.last(); BufferIterator begin = selection.last();
if (categorize(*begin) != categorize(*(begin-1))) if (categorize<punctuation_is_word>(*begin) !=
categorize<punctuation_is_word>(*(begin-1)))
--begin; --begin;
skip_while_reverse(begin, is_eol); skip_while_reverse(begin, is_eol);
@ -122,61 +146,15 @@ SelectionAndCaptures select_to_previous_word(const Selection& selection)
skip_while_reverse(end, is_blank); skip_while_reverse(end, is_blank);
bool with_end = false; bool with_end = false;
if (is_punctuation(*end)) if (not punctuation_is_word and is_punctuation(*end))
with_end = skip_while_reverse(end, is_punctuation); with_end = skip_while_reverse(end, is_punctuation);
else if (is_word(*end)) else if (is_word<punctuation_is_word>(*end))
with_end = skip_while_reverse(end, is_word); with_end = skip_while_reverse(end, is_word<punctuation_is_word>);
return Selection(begin, with_end ? end : end+1);
}
SelectionAndCaptures select_to_next_WORD(const Selection& selection)
{
BufferIterator begin = selection.last();
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
++begin;
skip_while(begin, is_eol);
BufferIterator end = begin+1;
skip_while(end, [] (char c) { return !is_blank(c) and !is_eol(c); });
bool with_end = skip_while(end, is_blank);
return Selection(begin, with_end ? end : end-1);
}
SelectionAndCaptures select_to_next_WORD_end(const Selection& selection)
{
BufferIterator begin = selection.last();
if (categorize<false>(*begin) != categorize<false>(*(begin+1)))
++begin;
skip_while(begin, is_eol);
BufferIterator end = begin+1;
skip_while(end, is_blank);
bool with_end = skip_while(end, [] (char c) { return !is_blank(c)
and !is_eol(c); });
return Selection(begin, with_end ? end : end-1);
}
SelectionAndCaptures select_to_previous_WORD(const Selection& selection)
{
BufferIterator begin = selection.last();
if (categorize<false>(*begin) != categorize<false>(*(begin-1)))
--begin;
skip_while_reverse(begin, is_eol);
BufferIterator end = begin;
skip_while_reverse(end, is_blank);
bool with_end = skip_while_reverse(end, [] (char c) { return !is_blank(c)
and !is_eol(c); });
return Selection(begin, with_end ? end : end+1); return Selection(begin, with_end ? end : end+1);
} }
template SelectionAndCaptures select_to_previous_word<false>(const Selection&);
template SelectionAndCaptures select_to_previous_word<true>(const Selection&);
SelectionAndCaptures select_line(const Selection& selection) SelectionAndCaptures select_line(const Selection& selection)
{ {

View File

@ -6,12 +6,13 @@
namespace Kakoune namespace Kakoune
{ {
template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word(const Selection& selection); SelectionAndCaptures select_to_next_word(const Selection& selection);
template<bool punctuation_is_word>
SelectionAndCaptures select_to_next_word_end(const Selection& selection); SelectionAndCaptures select_to_next_word_end(const Selection& selection);
template<bool punctuation_is_word>
SelectionAndCaptures select_to_previous_word(const Selection& selection); SelectionAndCaptures select_to_previous_word(const Selection& selection);
SelectionAndCaptures select_to_next_WORD(const Selection& selection);
SelectionAndCaptures select_to_next_WORD_end(const Selection& selection);
SelectionAndCaptures select_to_previous_WORD(const Selection& selection);
SelectionAndCaptures select_line(const Selection& selection); SelectionAndCaptures select_line(const Selection& selection);
SelectionAndCaptures select_matching(const Selection& selection); SelectionAndCaptures select_matching(const Selection& selection);
SelectionAndCaptures select_surrounding(const Selection& selection, SelectionAndCaptures select_surrounding(const Selection& selection,