Repository: microsoft/terminal
File: src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp (C++)

Code before:
            };
        }();

        if (_Args)
        {
            auto nameFromArgs = _Args.GenerateName();
            if (!nameFromArgs.empty())
            {
                return nameFromArgs;
            }
        }

        const auto found = GeneratedActionNames.find(_Action);
        return found != GeneratedActionNames.end() ? found->second : L"";
    }

    // Function Description:
    // - This will generate an ID for this ActionAndArgs, based on the ShortcutAction and the Args
    // - It will always create the same ID if the ShortcutAction and the Args are the same
    // - Note: this should only be called for User-created actions
    // - Example: The "SendInput 'abc'" action will have the generated ID "User.sendInput.<hash of 'abc'>"
    // Return Value:
    // - The ID, based on the ShortcutAction and the Args
    winrt::hstring ActionAndArgs::GenerateID() const
    {
        if (_Action != ShortcutAction::Invalid)
        {
            auto actionKeyString = ActionToStringMap.find(_Action)->second;
            auto result = RS_(L"OriginTagUser") + L"." + std::wstring{ actionKeyString.begin(), actionKeyString.end() };
            if (_Args)
            {
                // If there are args, append the hash of the args
                result = result + L"." + std::to_wstring(_Args.Hash());
            }
            return result;
        }
        return L"";
    }

    winrt::hstring ActionAndArgs::Serialize(const winrt::Windows::Foundation::Collections::IVector<Model::ActionAndArgs>& args)
    {
        Json::Value json{ Json::objectValue };
        JsonUtils::SetValueForKey(json, "actions", args);
        Json::StreamWriterBuilder wbuilder;
        auto str = Json::writeString(wbuilder, json);
        return winrt::to_hstring(str);
    }
    winrt::Windows::Foundation::Collections::IVector<Model::ActionAndArgs> ActionAndArgs::Deserialize(winrt::hstring content)
    {
        auto data = winrt::to_string(content);


Review comment (suggestion):
These IDs are very similar to our `InternalActionID` except instead of also hashing the `ShortcutAction`, we only hash the `Args` and we leave the `ShortcutAction` as a string. Since these will end up in the user file, I prefer this as it will be more readable

Code after:
                { ShortcutAction::OpenScratchpad, RS_(L"OpenScratchpadKey") },
                { ShortcutAction::OpenAbout, RS_(L"OpenAboutCommandKey") },
            };
        }();

        if (_Args)
        {
            auto nameFromArgs = _Args.GenerateName();
            if (!nameFromArgs.empty())
            {
                return nameFromArgs;
            }
        }

        const auto found = GeneratedActionNames.find(_Action);
        return found != GeneratedActionNames.end() ? found->second : L"";
    }

    // Function Description:
    // - This will generate an ID for this ActionAndArgs, based on the ShortcutAction and the Args
    // - It will always create the same ID if the ShortcutAction and the Args are the same
    // - Note: this should only be called for User-created actions
    // - Example: The "SendInput 'abc'" action will have the generated ID "User.sendInput.<hash of 'abc'>"
    // Return Value:
    // - The ID, based on the ShortcutAction and the Args
    winrt::hstring ActionAndArgs::GenerateID() const
    {
        if (_Action != ShortcutAction::Invalid)
        {
            auto actionKeyString = ActionToStringMap.find(_Action)->second;
            auto result = fmt::format(FMT_COMPILE(L"User.{}"), actionKeyString);
            if (_Args)
            {
                // If there are args, we need to append the hash of the args
                // However, to make it a little more presentable we
                // 1. truncate the hash to 32 bits
                // 2. convert it to a hex string
                // there is a _tiny_ chance of collision because of the truncate but unlikely for
                // the number of commands a user is expected to have
                const auto argsHash32 = static_cast<uint32_t>(_Args.Hash() & 0xFFFFFFFF);
                // {0:X} formats the truncated hash to an uppercase hex string
                fmt::format_to(std::back_inserter(result), FMT_COMPILE(L".{:X}"), argsHash32);
            }
            return winrt::hstring{ result };
        }
        return L"";
    }

    winrt::hstring ActionAndArgs::Serialize(const winrt::Windows::Foundation::Collections::IVector<Model::ActionAndArgs>& args)
    {
        Json::Value json{ Json::objectValue };