Skip to content

Made menu_item::Name private and use cached VisualLength whenever possible.#1114

Open
MKadaner wants to merge 1 commit into
FarGroup:masterfrom
MKadaner:mzk/cache-menu_item-VisualLength
Open

Made menu_item::Name private and use cached VisualLength whenever possible.#1114
MKadaner wants to merge 1 commit into
FarGroup:masterfrom
MKadaner:mzk/cache-menu_item-VisualLength

Conversation

@MKadaner

@MKadaner MKadaner commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

With support of fullwidth characters, calculating the visual length of menu item name may be expensive.

Let's cache the visual length once it is calculated. The new field does not even increase sizeof(menu_item).

Checklist

  • I have followed the contributing guidelines.
  • I have discussed this with project maintainers: N/A

    If not checked, I accept that this work might be rejected in favor of a different great big ineffable plan.

Details

  1. Made menu_item::Name private.
  2. Added accessors.
  3. Added necessary constructors.
  4. Replaced direct use of menu_item::Name with accessors calls.

Comment thread far/vmenu.hpp Outdated
return Name;
}

string& MutableName() noexcept

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the usages of this follow the MutableName() = NewValue; pattern.
Do we really need it?
Maybe something more conventional like SetName(NewValue) will do?

It's too easy to abuse it now by holding a mutable reference and modifying it randomly later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, MutableName is not exactly a good idea. I started from SetName but hit a couple of awkward places:

append(ListItem.MutableName(), L" \""sv, strFriendlyName, L"\""sv);

and especially

NewItem.MutableName().erase(NewItem.GetName().cbegin(), NewBegin);

If you are OK with the use of SetName here, I will sure like it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

append(ListItem.MutableName(), L" \""sv, strFriendlyName, L"\""sv);

ListItem.SetName(concat(ListItem.GetName(), ...))

NewItem.MutableName().erase(NewItem.GetName().cbegin(), NewBegin);

NewItem.SetName(NewItem.GetName().substr(NewBegin - NewItem.GetName().cbegin()))

Doesn't look too bad.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant

ListItem.SetName(far::format(L"{} \"{}\""sv, ListItem.GetName(), strFriendlyName));

Which is not really bad, considering.

Comment thread far/vmenu.hpp Outdated
menu_item() = default;

template<typename T> requires std::constructible_from<string, T>
menu_item(T&& Name, LISTITEMFLAGS Flags, DWORD AccelKey = {})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a template here?
We're going to construct a string anyway, so might as well just accept it by value and move it into Name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from when I experimented with overloaded constructors to reduce code churn at call sites.

P.S. C++ Core Guidelines suggest passing “will-move-from” parameters by rvalue reference (also, overview of parameter passing techniques).

This topic is somewhat controversial around me. What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

X&& binds to rvalues, which requires an explicit std::move at the call site if passing an lvalue

It is somewhat controversial indeed. What if we don't want to / can't move it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we would have to explicitly instantiate the object, like string{ MyUnmovableVar }. So, everything is very explicit at the call site, which from my point of view is an advantage. May help avoiding perf issues when we accidentally make a copy. I've seen it couple of times.

@MKadaner MKadaner force-pushed the mzk/cache-menu_item-VisualLength branch from 3263ce3 to 31d946b Compare July 6, 2026 00:41
@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants