blob: a9ce9e116fb9d45726e58563b85457f0c2f1cb01 [file] [log] [blame]
// 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 <string_view>
#include <tuple>
#include <type_traits>
#include "src/tint/utils/containers/enum_set.h"
// 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 /* */ = 0b0000'0000'0000'0011;
static constexpr Bits kStyleUnderlined /* */ = 0b0000'0000'0000'0001;
static constexpr Bits kStyleBold /* */ = 0b0000'0000'0000'0010;
static constexpr Bits kCompareMask /* */ = 0b0000'0000'0000'1100;
static constexpr Bits kCompareMatch /* */ = 0b0000'0000'0000'0100;
static constexpr Bits kCompareMismatch /* */ = 0b0000'0000'0000'1000;
static constexpr Bits kSeverityMask /* */ = 0b0000'0000'1111'0000;
static constexpr Bits kSeverityDefault /* */ = 0b0000'0000'0000'0000;
static constexpr Bits kSeveritySuccess /* */ = 0b0000'0000'0001'0000;
static constexpr Bits kSeverityWarning /* */ = 0b0000'0000'0010'0000;
static constexpr Bits kSeverityError /* */ = 0b0000'0000'0011'0000;
static constexpr Bits kSeverityFatal /* */ = 0b0000'0000'0100'0000;
static constexpr Bits kKindMask /* */ = 0b0000'1111'0000'0000;
static constexpr Bits kKindCode /* */ = 0b0000'0001'0000'0000;
static constexpr Bits kKindKeyword /* */ = 0b0000'0011'0000'0000;
static constexpr Bits kKindVariable /* */ = 0b0000'0101'0000'0000;
static constexpr Bits kKindType /* */ = 0b0000'0111'0000'0000;
static constexpr Bits kKindFunction /* */ = 0b0000'1001'0000'0000;
static constexpr Bits kKindEnum /* */ = 0b0000'1011'0000'0000;
static constexpr Bits kKindLiteral /* */ = 0b0000'1101'0000'0000;
static constexpr Bits kKindAttribute /* */ = 0b0000'1111'0000'0000;
static constexpr Bits kKindSquiggle /* */ = 0b0000'0010'0000'0000;
/// Getters
bool IsBold() const { return (bits & kStyleBold) != 0; }
bool IsUnderlined() const { return (bits & kStyleUnderlined) != 0; }
bool HasCompare() const { return (bits & kCompareMask) != 0; }
bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; }
bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; }
bool HasSeverity() const { return (bits & kSeverityMask) != 0; }
bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; }
bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; }
bool IsError() const { return (bits & kSeverityMask) == kSeverityError; }
bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; }
bool HasKind() const { return (bits & kKindMask) != 0; }
bool IsCode() const { return (bits & kKindCode) != 0; }
bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; }
bool IsVariable() const { return (bits & kKindMask) == kKindVariable; }
bool IsType() const { return (bits & kKindMask) == kKindType; }
bool IsFunction() const { return (bits & kKindMask) == kKindFunction; }
bool IsEnum() const { return (bits & kKindMask) == kKindEnum; }
bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; }
bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; }
bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; }
/// Equality operator
bool operator==(TextStyle other) const { return bits == other.bits; }
/// Inequality operator
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.
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
static constexpr TextStyle Plain = TextStyle{};
/// Bold renders text with a heavy weight
static constexpr TextStyle Bold = TextStyle{TextStyle::kStyleBold};
/// Underlined renders text with an underline
static constexpr TextStyle Underlined = TextStyle{TextStyle::kStyleUnderlined};
/// Underlined renders text with the compare-match style
static constexpr TextStyle Match = TextStyle{TextStyle::kCompareMatch};
/// Underlined renders text with the compare-mismatch style
static constexpr TextStyle Mismatch = TextStyle{TextStyle::kCompareMismatch};
/// Success renders text with the styling for a successful status
static constexpr TextStyle Success = TextStyle{TextStyle::kSeveritySuccess};
/// Warning renders text with the styling for a warning status
static constexpr TextStyle Warning = TextStyle{TextStyle::kSeverityWarning};
/// Error renders text with the styling for a error status
static constexpr TextStyle Error = TextStyle{TextStyle::kSeverityError};
/// Fatal renders text with the styling for a fatal status
static constexpr TextStyle Fatal = TextStyle{TextStyle::kSeverityFatal};
/// Code renders text with a 'code' style
static constexpr TextStyle Code = TextStyle{TextStyle::kKindCode};
/// Keyword renders text with a 'code' style that represents a 'keyword' token
static constexpr TextStyle Keyword = TextStyle{TextStyle::kKindKeyword};
/// Variable renders text with a 'code' style that represents a 'variable' token
static constexpr TextStyle Variable = TextStyle{TextStyle::kKindVariable};
/// Type renders text with a 'code' style that represents a 'type' token
static constexpr TextStyle Type = TextStyle{TextStyle::kKindType};
/// Function renders text with a 'code' style that represents a 'function' token
static constexpr TextStyle Function = TextStyle{TextStyle::kKindFunction};
/// Enum renders text with a 'code' style that represents a 'enum' token
static constexpr TextStyle Enum = TextStyle{TextStyle::kKindEnum};
/// Literal renders text with a 'code' style that represents a 'literal' token
static constexpr TextStyle Literal = TextStyle{TextStyle::kKindLiteral};
/// Attribute renders text with a 'code' style that represents an 'attribute' token
static constexpr TextStyle Attribute = TextStyle{TextStyle::kKindAttribute};
/// Squiggle renders text with a squiggle-highlight style (`^^^^^`)
static constexpr TextStyle Squiggle = TextStyle{TextStyle::kKindSquiggle};
} // namespace tint::style
#endif // SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_