diff --git a/README.asciidoc b/README.asciidoc index d9fede30..7e305f44 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -229,6 +229,8 @@ Some keys allow you to select a text object: for a word this will not select trailing spaces. * _[_: selects to object start * _]_: selects to object end + * _{_: extends selections to object start + * _}_: extends selections to object end After this key, you need to enter a second key in order to specify which object you want. @@ -245,6 +247,9 @@ object you want. * _p_: select the paragraph * _i_: select the current indentation block +For nestable objects, a count can be used in order to specify which surrounding +level to select. + Registers --------- diff --git a/src/normal.cc b/src/normal.cc index 911ec90a..4cde30e3 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -572,17 +572,47 @@ void indent(Context& context, int) void deindent(Context& context, int) { - int width = context.options()["indentwidth"].get(); + const auto& indent = context.options()["indent"].get(); + size_t width = 0; + size_t tabstop = context.options()["tabstop"].get(); + for (auto& c : indent) + { + if (c == '\t') + width = (width / tabstop + 1) * tabstop; + else + ++width; + } + Editor& editor = context.editor(); DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select((SelectionList)std::move(sels)); }); - editor.select(select_whole_lines); - editor.multi_select(std::bind(select_all_matches, _1, _2, - Regex{"^\\h{1," + to_string(width) + "}"})); + editor.multi_select([width,tabstop](const Buffer& buf, const Selection& sel) { + SelectionList res; + for (auto line = sel.min().line; line < sel.max().line+1; ++line) + { + size_t cur_width = 0; + auto& content = buf[line]; + for (auto column = 0_byte; column < content.length(); ++column) + { + if (content[column] == ' ') + ++cur_width; + else if (content[column] == '\t') + cur_width = (cur_width / tabstop + 1) * tabstop; + else + break; + if (cur_width == width) + { + res.emplace_back(line, BufferCoord{line, column}); + break; + } + } + } + return res; + }); editor.erase(); } -template +template void select_object(Context& context, int param) { int level = param <= 0 ? 0 : param - 1; @@ -605,7 +635,7 @@ void select_object(Context& context, int param) for (auto& sel : selectors) { if (c == sel.key) - return context.editor().select(std::bind(sel.func, _1, _2, flags)); + return context.editor().select(std::bind(sel.func, _1, _2, flags), mode); } static constexpr struct @@ -625,7 +655,7 @@ void select_object(Context& context, int param) if (sur.pair.first == c or sur.pair.second == c or (sur.name != 0 and sur.name == c)) return context.editor().select(std::bind(select_surrounding, _1, _2, - sur.pair, level, flags)); + sur.pair, level, flags), mode); } }, "select object", "b,(,): parenthesis block\n" @@ -950,6 +980,8 @@ KeyMap keymap = { { Key::Modifiers::Alt, 'a' }, select_object }, { { Key::Modifiers::None, ']' }, select_object }, { { Key::Modifiers::None, '[' }, select_object }, + { { Key::Modifiers::None, '}' }, select_object }, + { { Key::Modifiers::None, '{' }, select_object }, { { Key::Modifiers::Alt, 'j' }, join }, { { Key::Modifiers::Alt, 'J' }, join_select_spaces },