Skip to content

Rework formatting for logs and fmt::format#1890

Open
Alphalaneous wants to merge 3 commits intogeode-sdk:mainfrom
Alphalaneous:rework-formatting
Open

Rework formatting for logs and fmt::format#1890
Alphalaneous wants to merge 3 commits intogeode-sdk:mainfrom
Alphalaneous:rework-formatting

Conversation

@Alphalaneous
Copy link
Copy Markdown
Contributor

  • Separate formatting from the log headers and source

  • Runtime formatting for CCObjects

    • Provide tools for registering CCObjects to be formatted easily, even for your own mods
      • Generally useful for API mods that add UI elements and wanting to simply be able to format the object
      • This also brings the ability for CCObjects within containers to have their information shown in a lot as well
    • Uses a Wrapper class for CCObjects instead of just an (ugly) wrapCocosObj method to wrap them. Enabling using the fmt::formatter directly, and thus allowing us to parse for specifiers too.
      • You can use format::wrap with a CCObject to format it outside of logs, such as fmt::format("My Object: {}", format::wrap(CCString::create("Wow!")));
  • New formats for CCFloat, CCDouble, CCInteger, CCBool, CCString, CCSet, CCDictionary, CCTouch, CCFiniteTimeAction, and CCActionInterval

  • Prettify container formats by default, use the raw specifier to disable prettifying: log::info("{:raw}", this->m_myDict);

Note that I did not remove the format_as for CCObject, CCArray, and CCNode, even though they are now obsolete. As that would be considered a breaking change. These will still function the same if someone is calling them for any reason.

geode::Result<std::string> format(cocos2d::CCObject const* obj, std::string_view specifier) override {
if (!geode::cast::typeinfo_cast<T*>(obj)) return geode::Err("Incorrect Type");
if (!m_formatter) return geode::Err("No formatter callback");
if (m_formatter) return geode::Ok(m_formatter(static_cast<T*>(const_cast<cocos2d::CCObject*>(obj)), specifier));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the redundant if (m_formatter) here can be a bit confusing so i'd remove it

cocos2d::CCObject* m_obj;
};

class FormatBase {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

since you use unique_ptr, I recommend adding a virtual destructor to this class. Most formatters probably won't have any state, but without a virtual destructor you make it so that their destructors never get to run at all which can cause subtle bugs

});

format::registerFormat<CCArray>([] (CCArray* self, std::string_view specifier) -> std::string {
if (!self && !self->count()) return "[empty]";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this check sounds erroneous, did you mean !self || !self->count()

});

format::registerFormat<CCSet>([] (CCSet* self, std::string_view specifier) -> std::string {
if (!self && !self->count()) return "[empty]";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ditto

}

void addFormat(std::string_view name, std::unique_ptr<FormatBase> format) {
m_formatCallbacks.insert(m_formatCallbacks.begin(), std::move(format));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is there a specific reason why this inserts at the beginning (which is going to be O(n) always)? if this is to make new listeners highest priority, IMO just iterate in reverse when calling

Comment on lines +119 to +134
fmt::memory_buffer buffer;
buffer.push_back('[');

bool first = true;

for (auto obj : self->asExt()) {
if (!first) buffer.append(std::string_view(", "));
if (!rawFormat) buffer.append(std::string_view("\n\t"));
first = false;

buffer.append(fmt::format("{}", format::wrap(obj)));
}

if (!rawFormat) buffer.push_back('\n');
buffer.push_back(']');
return fmt::to_string(buffer);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would recommend using geode::utils::StringBuffer (in here and all other functions), it's going to be more efficient and less verbose to use (e.g. you can directly do buffer.append(", ") or buffer.append("{}", format::wrap(obj))

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