| // Copyright 2024 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #ifndef SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ | |
| #define SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ | |
| #include <cstdint> | |
| #include <tuple> | |
| #include <type_traits> | |
| // Forward declarations | |
| namespace tint { | |
| template <typename... VALUES> | |
| struct ScopedTextStyle; | |
| } | |
| namespace tint { | |
| /// TextStyle is a styling that can be applied to span of a StyledText. | |
| class TextStyle { | |
| public: | |
| /// Bits is the integer type used to store the text style. | |
| using Bits = uint16_t; | |
| /// Bit patterns | |
| static constexpr Bits kStyleMask /* */ = 0b00'00000'0000'00'111; | |
| static constexpr Bits kStyleUnderlined /* */ = 0b00'00000'0000'00'001; | |
| static constexpr Bits kStyleBold /* */ = 0b00'00000'0000'00'010; | |
| static constexpr Bits kStyleNoQuote /* */ = 0b00'00000'0000'00'100; | |
| static constexpr Bits kCompareMask /* */ = 0b00'00000'0000'11'000; | |
| static constexpr Bits kCompareMatch /* */ = 0b00'00000'0000'01'000; | |
| static constexpr Bits kCompareMismatch /* */ = 0b00'00000'0000'10'000; | |
| static constexpr Bits kSeverityMask /* */ = 0b00'00000'1111'00'000; | |
| static constexpr Bits kSeverityDefault /* */ = 0b00'00000'0000'00'000; | |
| static constexpr Bits kSeveritySuccess /* */ = 0b00'00000'0001'00'000; | |
| static constexpr Bits kSeverityWarning /* */ = 0b00'00000'0010'00'000; | |
| static constexpr Bits kSeverityError /* */ = 0b00'00000'0011'00'000; | |
| static constexpr Bits kSeverityFatal /* */ = 0b00'00000'0100'00'000; | |
| static constexpr Bits kKindMask /* */ = 0b00'11111'0000'00'000; | |
| static constexpr Bits kKindCode /* */ = 0b00'00001'0000'00'000; | |
| static constexpr Bits kKindKeyword /* */ = 0b00'00011'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindVariable /* */ = 0b00'00101'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindType /* */ = 0b00'00111'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindFunction /* */ = 0b00'01001'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindEnum /* */ = 0b00'01011'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindLiteral /* */ = 0b00'01101'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindAttribute /* */ = 0b00'01111'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindComment /* */ = 0b00'10001'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindLabel /* */ = 0b00'10011'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindInstruction /* */ = 0b00'10101'0000'00'000; // includes kKindCode | |
| static constexpr Bits kKindSquiggle /* */ = 0b00'00010'0000'00'000; | |
| /// Getters | |
| constexpr bool IsBold() const { return (bits & kStyleBold) != 0; } | |
| constexpr bool IsUnderlined() const { return (bits & kStyleUnderlined) == kStyleUnderlined; } | |
| constexpr bool IsNoQuote() const { return (bits & kStyleNoQuote) == kStyleNoQuote; } | |
| constexpr bool HasCompare() const { return (bits & kCompareMask) != 0; } | |
| constexpr bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; } | |
| constexpr bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; } | |
| constexpr bool HasSeverity() const { return (bits & kSeverityMask) != 0; } | |
| constexpr bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; } | |
| constexpr bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; } | |
| constexpr bool IsError() const { return (bits & kSeverityMask) == kSeverityError; } | |
| constexpr bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; } | |
| constexpr bool HasKind() const { return (bits & kKindMask) != 0; } | |
| constexpr bool IsCode() const { return (bits & kKindCode) == kKindCode; } | |
| constexpr bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; } | |
| constexpr bool IsVariable() const { return (bits & kKindMask) == kKindVariable; } | |
| constexpr bool IsType() const { return (bits & kKindMask) == kKindType; } | |
| constexpr bool IsFunction() const { return (bits & kKindMask) == kKindFunction; } | |
| constexpr bool IsEnum() const { return (bits & kKindMask) == kKindEnum; } | |
| constexpr bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; } | |
| constexpr bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; } | |
| constexpr bool IsComment() const { return (bits & kKindMask) == kKindComment; } | |
| constexpr bool IsLabel() const { return (bits & kKindMask) == kKindLabel; } | |
| constexpr bool IsInstruction() const { return (bits & kKindMask) == kKindInstruction; } | |
| constexpr bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; } | |
| /// Equality operator | |
| constexpr bool operator==(TextStyle other) const { return bits == other.bits; } | |
| /// Inequality operator | |
| constexpr bool operator!=(TextStyle other) const { return bits != other.bits; } | |
| /// @returns the combination of this TextStyle and @p other. | |
| /// If both this TextStyle and @p other have a compare style, severity style or kind style, then | |
| /// the style collision will resolve by using the style of @p other. | |
| constexpr TextStyle operator+(TextStyle other) const { | |
| Bits out = other.bits; | |
| out |= bits & kStyleMask; | |
| if (HasCompare() && !other.HasCompare()) { | |
| out |= bits & kCompareMask; | |
| } | |
| if (HasSeverity() && !other.HasSeverity()) { | |
| out |= bits & kSeverityMask; | |
| } | |
| if (HasKind() && !other.HasKind()) { | |
| out |= bits & kKindMask; | |
| } | |
| return TextStyle{out}; | |
| } | |
| /// @returns a new ScopedTextStyle of @p values using with this TextStyle | |
| template <typename... VALUES> | |
| inline ScopedTextStyle<VALUES...> operator()(VALUES&&... values) const; | |
| /// The style bit pattern | |
| Bits bits = 0; | |
| }; | |
| /// ScopedTextStyle is a span of text, styled with a TextStyle | |
| template <typename... VALUES> | |
| struct ScopedTextStyle { | |
| std::tuple<VALUES...> values; | |
| TextStyle style; | |
| }; | |
| template <typename... VALUES> | |
| ScopedTextStyle<VALUES...> TextStyle::operator()(VALUES&&... values) const { | |
| return ScopedTextStyle<VALUES...>{std::forward_as_tuple(values...), *this}; | |
| } | |
| namespace detail { | |
| template <typename T> | |
| struct IsScopedTextStyle : std::false_type {}; | |
| template <typename... VALUES> | |
| struct IsScopedTextStyle<ScopedTextStyle<VALUES...> > : std::true_type {}; | |
| } // namespace detail | |
| /// Resolves to true iff T is a ScopedTextStyle. | |
| template <typename T> | |
| static constexpr bool IsScopedTextStyle = detail::IsScopedTextStyle<T>::value; | |
| } // namespace tint | |
| namespace tint::style { | |
| /// Plain renders text without any styling | |
| inline constexpr TextStyle Plain = TextStyle{}; | |
| /// Bold renders text with a heavy weight | |
| inline constexpr TextStyle Bold = TextStyle{TextStyle::kStyleBold}; | |
| /// Underlined renders text with an underline | |
| inline constexpr TextStyle Underlined = TextStyle{TextStyle::kStyleUnderlined}; | |
| /// Code renders without a single quote when printed as plain text. | |
| inline constexpr TextStyle NoQuote = TextStyle{TextStyle::kStyleNoQuote}; | |
| /// Match renders text with the compare-match style | |
| inline constexpr TextStyle Match = TextStyle{TextStyle::kCompareMatch}; | |
| /// Mismatch renders text with the compare-mismatch style | |
| inline constexpr TextStyle Mismatch = TextStyle{TextStyle::kCompareMismatch}; | |
| /// Success renders text with the styling for a successful status | |
| inline constexpr TextStyle Success = TextStyle{TextStyle::kSeveritySuccess}; | |
| /// Warning renders text with the styling for a warning status | |
| inline constexpr TextStyle Warning = TextStyle{TextStyle::kSeverityWarning}; | |
| /// Error renders text with the styling for a error status | |
| inline constexpr TextStyle Error = TextStyle{TextStyle::kSeverityError}; | |
| /// Fatal renders text with the styling for a fatal status | |
| inline constexpr TextStyle Fatal = TextStyle{TextStyle::kSeverityFatal}; | |
| /// Code renders text with a 'code' style | |
| inline constexpr TextStyle Code = TextStyle{TextStyle::kKindCode}; | |
| /// Keyword renders text with a 'code' style that represents a 'keyword' token | |
| inline constexpr TextStyle Keyword = TextStyle{TextStyle::kKindKeyword}; | |
| /// Variable renders text with a 'code' style that represents a 'variable' token | |
| inline constexpr TextStyle Variable = TextStyle{TextStyle::kKindVariable}; | |
| /// Type renders text with a 'code' style that represents a 'type' token | |
| inline constexpr TextStyle Type = TextStyle{TextStyle::kKindType}; | |
| /// Function renders text with a 'code' style that represents a 'function' token | |
| inline constexpr TextStyle Function = TextStyle{TextStyle::kKindFunction}; | |
| /// Enum renders text with a 'code' style that represents a 'enum' token | |
| inline constexpr TextStyle Enum = TextStyle{TextStyle::kKindEnum}; | |
| /// Literal renders text with a 'code' style that represents a 'literal' token | |
| inline constexpr TextStyle Literal = TextStyle{TextStyle::kKindLiteral}; | |
| /// Attribute renders text with a 'code' style that represents an 'attribute' token | |
| inline constexpr TextStyle Attribute = TextStyle{TextStyle::kKindAttribute}; | |
| /// Comment renders text with a 'code' style that represents an 'comment' token | |
| inline constexpr TextStyle Comment = TextStyle{TextStyle::kKindComment}; | |
| /// Label renders text with a 'code' style that represents an 'label' token | |
| inline constexpr TextStyle Label = TextStyle{TextStyle::kKindLabel}; | |
| /// Instruction renders text with a 'code' style that represents an 'instruction' token | |
| inline constexpr TextStyle Instruction = TextStyle{TextStyle::kKindInstruction}; | |
| /// Squiggle renders text with a squiggle-highlight style (`^^^^^`) | |
| inline constexpr TextStyle Squiggle = TextStyle{TextStyle::kKindSquiggle}; | |
| } // namespace tint::style | |
| #endif // SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ |