diff --git a/doc/pages/expansions.asciidoc b/doc/pages/expansions.asciidoc index 63980b8e4..1823560c5 100644 --- a/doc/pages/expansions.asciidoc +++ b/doc/pages/expansions.asciidoc @@ -311,6 +311,12 @@ The following expansions are supported (with required context _in italics_): the number of bytes from the start of the line to the cursor (like `%val{cursor_column}`), and all are 1-based decimal integers +*%val{selections_char_desc}*:: + _in window scope_ + + unquoted list of the ranges of all selections, in the same format as + `%val{selection_desc}`, except that the columns are in codepoints rather + than bytes + *%val{selections_desc}*:: _in window scope_ + unquoted list of the ranges of all selections, in the same format as diff --git a/src/main.cc b/src/main.cc index 5fc49b590..8ebd6f765 100644 --- a/src/main.cc +++ b/src/main.cc @@ -252,7 +252,11 @@ static const EnvVarDesc builtin_env_vars[] = { { }, { "selections_desc", false, [](StringView name, const Context& context, Quoting quoting) - { return selection_list_to_string(context.selections()); } + { return selection_list_to_string(context.selections()); } + }, { + "selections_char_desc", false, + [](StringView name, const Context& context, Quoting quoting) + { return selection_list_to_string(context.selections()); } }, { "selection_length", false, [](StringView name, const Context& context, Quoting quoting) -> String @@ -793,7 +797,7 @@ int run_server(StringView session, StringView server_init, kak_assert(local_client); const String client_name = local_client->context().name(); const String buffer_name = local_client->context().buffer().name(); - const String selections = selection_list_to_string(local_client->context().selections()); + const String selections = selection_list_to_string(local_client->context().selections()); ClientManager::instance().remove_client(*local_client, true, 0); client_manager.clear_client_trash(); diff --git a/src/selection.cc b/src/selection.cc index a5b2c7b18..412d4f2d9 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -480,13 +480,13 @@ String selection_to_string(const Selection& selection) cursor.line + 1, cursor.column + 1); } -String selection_list_to_string(const SelectionList& selections) +String selection_to_string_char(const Buffer& buffer, const Selection& selection) { - auto beg = &*selections.begin(), end = &*selections.end(); - auto main = beg + selections.main_index(); - using View = ConstArrayView; - return join(concatenated(View{main, end}, View{beg, main}) | - transform(selection_to_string), ' ', false); + const auto& cursor = selection.cursor(); + const auto& anchor = selection.anchor(); + return format("{}.{},{}.{}", + anchor.line + 1, buffer[anchor.line].char_count_to(anchor.column) + 1, + cursor.line + 1, buffer[cursor.line].char_count_to(cursor.column) + 1); } Selection selection_from_string(StringView desc) diff --git a/src/selection.hh b/src/selection.hh index 5c47f878c..568b438a0 100644 --- a/src/selection.hh +++ b/src/selection.hh @@ -95,7 +95,6 @@ struct SelectionList SelectionList(Buffer& buffer, Vector s, size_t timestamp); void update(bool merge = true); - void check_invariant() const; const Selection& main() const { return (*this)[m_main]; } @@ -157,9 +156,27 @@ private: Vector compute_modified_ranges(const Buffer& buffer, size_t timestamp); -String selection_to_string(const Selection& selection); -String selection_list_to_string(const SelectionList& selection); Selection selection_from_string(StringView desc); +String selection_to_string(const Selection& selection); +String selection_to_string_char(const Buffer& buffer, const Selection& selection); + +template +String selection_list_to_string(const SelectionList& selections) +{ + auto& buffer = selections.buffer(); + kak_assert(selections.timestamp() == buffer.timestamp()); + + auto to_string = [&](const Selection& selection) { + return char_columns ? selection_to_string_char(buffer, selection) + : selection_to_string(selection); + }; + + auto beg = &*selections.begin(), end = &*selections.end(); + auto main = beg + selections.main_index(); + using View = ConstArrayView; + return join(concatenated(View{main, end}, View{beg, main}) | + transform(to_string), ' ', false); +} template SelectionList selection_list_from_strings(Buffer& buffer, StringArray&& descs, size_t timestamp, size_t main) diff --git a/test/compose/selections_char_desc-expansion/cmd b/test/compose/selections_char_desc-expansion/cmd new file mode 100644 index 000000000..e69de29bb diff --git a/test/compose/selections_char_desc-expansion/in b/test/compose/selections_char_desc-expansion/in new file mode 100644 index 000000000..1b1b4d091 --- /dev/null +++ b/test/compose/selections_char_desc-expansion/in @@ -0,0 +1,4 @@ +sin%(gle)-byte +%(λx.)λy.y x - start on wide char + ∃e∈%(C.∀)g∈C.g⊗e≡e⊗g≡e - tabs, ending on wide char + %(x̦̏)- combining characters diff --git a/test/compose/selections_char_desc-expansion/kak_selections_char_desc b/test/compose/selections_char_desc-expansion/kak_selections_char_desc new file mode 100644 index 000000000..caf68a816 --- /dev/null +++ b/test/compose/selections_char_desc-expansion/kak_selections_char_desc @@ -0,0 +1 @@ +4.2,4.4 1.4,1.6 2.1,2.3 3.5,3.7