diff --git a/README.asciidoc b/README.asciidoc index 069336c8..15db7b81 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -218,6 +218,7 @@ object you want. * _W_: select the whole WORD * _s_: select the sentence * _p_: select the paragraph + * _i_: select the current indentation block Registers --------- diff --git a/src/normal.cc b/src/normal.cc index 964d819e..81526b9c 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -582,6 +582,7 @@ void select_object(Context& context) { { Key::Modifiers::None, 'W' }, std::bind(select_whole_word, _1, _2, flags) }, { { Key::Modifiers::None, 's' }, std::bind(select_whole_sentence, _1, _2, flags) }, { { Key::Modifiers::None, 'p' }, std::bind(select_whole_paragraph, _1, _2, flags) }, + { { Key::Modifiers::None, 'i' }, std::bind(select_whole_indent, _1, _2, flags) }, }; auto it = key_to_selector.find(key); diff --git a/src/selectors.cc b/src/selectors.cc index 946c5761..63b17a06 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -494,6 +494,45 @@ Selection select_whole_paragraph(const Buffer& buffer, const Selection& selectio : Selection{last.coord(), first.coord()}; } +static CharCount get_indent(const String& str, int tabstop) +{ + CharCount indent = 0; + for (auto& c : str) + { + if (c == ' ') + ++indent; + else if (c =='\t') + indent = (indent / tabstop + 1) * tabstop; + else + break; + } + return indent; +} + +Selection select_whole_indent(const Buffer& buffer, const Selection& selection, ObjectFlags flags) +{ + int tabstop = buffer.options()["tabstop"].get(); + LineCount line = selection.last().line; + auto indent = get_indent(buffer[line], tabstop); + + LineCount begin_line = line - 1; + if (flags & ObjectFlags::ToBegin) + { + while (begin_line >= 0 and (buffer[begin_line] == "\n" or get_indent(buffer[begin_line], tabstop) >= indent)) + --begin_line; + } + ++begin_line; + LineCount end_line = line + 1; + if (flags & ObjectFlags::ToEnd) + { + LineCount end = buffer.line_count(); + while (end_line < end and (buffer[end_line] == "\n" or get_indent(buffer[end_line], tabstop) >= indent)) + ++end_line; + } + --end_line; + return Selection{begin_line, {end_line, buffer[end_line].length() - 1}}; +} + Selection select_whole_lines(const Buffer& buffer, const Selection& selection) { // no need to be utf8 aware for is_eol as we only use \n as line seperator diff --git a/src/selectors.hh b/src/selectors.hh index 33d1dee1..a564eea7 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -48,6 +48,8 @@ Selection select_whole_sentence(const Buffer& buffer, const Selection& selection ObjectFlags flags); Selection select_whole_paragraph(const Buffer& buffer, const Selection& selection, ObjectFlags flags); +Selection select_whole_indent(const Buffer& buffer, const Selection& selection, + ObjectFlags flags); Selection select_whole_lines(const Buffer& buffer, const Selection& selection); Selection select_whole_buffer(const Buffer& buffer, const Selection& selection); Selection trim_partial_lines(const Buffer& buffer, const Selection& selection);