File indexing completed on 2024-04-28 05:49:01
0001 /* 0002 SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com> 0003 0004 SPDX-License-Identifier: MIT 0005 */ 0006 #include "semantic_tokens_legend.h" 0007 0008 #include <KSyntaxHighlighting/Theme> 0009 #include <KTextEditor/Editor> 0010 0011 SemanticTokensLegend::SemanticTokensLegend(QObject *parent) 0012 : QObject(parent) 0013 { 0014 themeChange(KTextEditor::Editor::instance()); 0015 connect(KTextEditor::Editor::instance(), &KTextEditor::Editor::configChanged, this, &SemanticTokensLegend::themeChange); 0016 } 0017 0018 enum { 0019 FuncAttr = 0, 0020 TypeAttr, 0021 MacroAttr, 0022 CommentAttr, 0023 VarParamAttr, 0024 ConstantAttr, 0025 KeywordAttr, 0026 }; 0027 0028 void SemanticTokensLegend::themeChange(KTextEditor::Editor *e) 0029 { 0030 if (!e) { 0031 return; 0032 } 0033 0034 using Style = KSyntaxHighlighting::Theme::TextStyle; 0035 0036 const auto theme = e->theme(); 0037 0038 QColor f = QColor::fromRgba(theme.textColor(Style::Function)); 0039 QColor fs = QColor::fromRgba(theme.selectedTextColor(Style::Function)); 0040 if (!fixedAttrs[FuncAttr]) { 0041 fixedAttrs[FuncAttr] = new KTextEditor::Attribute(); 0042 } 0043 fixedAttrs[FuncAttr]->setForeground(f); 0044 fixedAttrs[FuncAttr]->setSelectedForeground(fs); 0045 fixedAttrs[FuncAttr]->setFontBold(theme.isBold(Style::Function)); 0046 fixedAttrs[FuncAttr]->setFontItalic(theme.isItalic(Style::Function)); 0047 0048 if (!fixedAttrs[VarParamAttr]) { 0049 fixedAttrs[VarParamAttr] = new KTextEditor::Attribute(); 0050 } 0051 { 0052 // This is only for function parameter which are not 0053 // directly supported by themes so we load some hard 0054 // coded values here for some of the themes we have 0055 // and for others we just read the "Variable" text-style. 0056 QColor v; 0057 QColor vs; 0058 bool italic = false; 0059 static const char MonokaiVP[] = "#fd971f"; 0060 static const char DraculaVP[] = "#ffb86c"; 0061 static const char AyuDarkLightVP[] = "#a37acc"; 0062 static const char AyuMirageVP[] = "#d4bfff"; 0063 if (theme.name() == QStringLiteral("Monokai")) { 0064 v = QColor(MonokaiVP); 0065 vs = v; 0066 italic = true; 0067 } else if (theme.name() == QStringLiteral("Dracula")) { 0068 v = QColor(DraculaVP); 0069 vs = v; 0070 italic = true; 0071 } else if (theme.name() == QStringLiteral("ayu Light") || theme.name() == QStringLiteral("ayu Dark")) { 0072 v = QColor(AyuDarkLightVP); 0073 vs = v; 0074 } else if (theme.name() == QStringLiteral("ayu Mirage")) { 0075 v = QColor(AyuMirageVP); 0076 vs = v; 0077 } else { 0078 v = QColor::fromRgba(theme.textColor(Style::Variable)); 0079 italic = theme.isItalic(Style::Variable); 0080 vs = QColor::fromRgba(theme.selectedTextColor(Style::Variable)); 0081 } 0082 0083 fixedAttrs[VarParamAttr]->setForeground(v); 0084 fixedAttrs[VarParamAttr]->setSelectedForeground(vs); 0085 fixedAttrs[VarParamAttr]->setFontBold(theme.isBold(Style::Variable)); 0086 fixedAttrs[VarParamAttr]->setFontItalic(italic); 0087 } 0088 0089 QColor c = QColor::fromRgba(theme.textColor(Style::Constant)); 0090 QColor cs = QColor::fromRgba(theme.selectedTextColor(Style::Constant)); 0091 if (!fixedAttrs[ConstantAttr]) { 0092 fixedAttrs[ConstantAttr] = new KTextEditor::Attribute(); 0093 } 0094 fixedAttrs[ConstantAttr]->setForeground(c); 0095 fixedAttrs[ConstantAttr]->setSelectedForeground(cs); 0096 fixedAttrs[ConstantAttr]->setFontBold(theme.isBold(Style::Constant)); 0097 fixedAttrs[ConstantAttr]->setFontItalic(theme.isItalic(Style::Constant)); 0098 0099 QColor k = QColor::fromRgba(theme.textColor(Style::Keyword)); 0100 QColor ks = QColor::fromRgba(theme.selectedTextColor(Style::Keyword)); 0101 if (!fixedAttrs[KeywordAttr]) { 0102 fixedAttrs[KeywordAttr] = new KTextEditor::Attribute(); 0103 } 0104 fixedAttrs[KeywordAttr]->setForeground(k); 0105 fixedAttrs[KeywordAttr]->setSelectedForeground(ks); 0106 fixedAttrs[KeywordAttr]->setFontBold(theme.isBold(Style::Keyword)); 0107 fixedAttrs[KeywordAttr]->setFontItalic(theme.isItalic(Style::Keyword)); 0108 0109 QColor cm = QColor::fromRgba(theme.textColor(Style::Comment)); 0110 QColor cms = QColor::fromRgba(theme.selectedTextColor(Style::Comment)); 0111 if (!fixedAttrs[CommentAttr]) { 0112 fixedAttrs[CommentAttr] = new KTextEditor::Attribute(); 0113 } 0114 fixedAttrs[CommentAttr]->setForeground(cm); 0115 fixedAttrs[CommentAttr]->setSelectedForeground(cms); 0116 fixedAttrs[CommentAttr]->setFontBold(theme.isBold(Style::Comment)); 0117 fixedAttrs[CommentAttr]->setFontItalic(theme.isItalic(Style::Comment)); 0118 0119 QColor p = QColor::fromRgba(theme.textColor(Style::Preprocessor)); 0120 QColor ps = QColor::fromRgba(theme.selectedTextColor(Style::Preprocessor)); 0121 if (!fixedAttrs[MacroAttr]) { 0122 fixedAttrs[MacroAttr] = new KTextEditor::Attribute(); 0123 } 0124 fixedAttrs[MacroAttr]->setForeground(p); 0125 fixedAttrs[MacroAttr]->setSelectedForeground(ps); 0126 fixedAttrs[MacroAttr]->setFontBold(theme.isBold(Style::Preprocessor)); 0127 fixedAttrs[MacroAttr]->setFontItalic(theme.isItalic(Style::Preprocessor)); 0128 0129 QColor tp = QColor::fromRgba(theme.textColor(Style::DataType)); 0130 QColor tps = QColor::fromRgba(theme.selectedTextColor(Style::DataType)); 0131 if (!fixedAttrs[TypeAttr]) { 0132 fixedAttrs[TypeAttr] = new KTextEditor::Attribute(); 0133 } 0134 fixedAttrs[TypeAttr]->setForeground(tp); 0135 fixedAttrs[TypeAttr]->setSelectedForeground(tps); 0136 fixedAttrs[TypeAttr]->setFontBold(theme.isBold(Style::DataType)); 0137 fixedAttrs[TypeAttr]->setFontItalic(theme.isItalic(Style::DataType)); 0138 } 0139 0140 void SemanticTokensLegend::initialize(const std::vector<QString> &types) 0141 { 0142 std::vector<TokenType> tokenTypes(types.size()); 0143 int i = 0; 0144 for (const auto &type : types) { 0145 if (type == QStringLiteral("type")) 0146 tokenTypes[i] = TokenType::Type; 0147 else if (type == QStringLiteral("class")) 0148 tokenTypes[i] = TokenType::Class; 0149 else if (type == QStringLiteral("enum")) 0150 tokenTypes[i] = TokenType::Enum; 0151 else if (type == QStringLiteral("type")) 0152 tokenTypes[i] = TokenType::Type; 0153 else if (type == QStringLiteral("interface")) 0154 tokenTypes[i] = TokenType::Interface; 0155 else if (type == QStringLiteral("struct")) 0156 tokenTypes[i] = TokenType::Struct; 0157 else if (type == QStringLiteral("typeParameter")) 0158 tokenTypes[i] = TokenType::TypeParameter; 0159 else if (type == QStringLiteral("parameter")) 0160 tokenTypes[i] = TokenType::Parameter; 0161 else if (type == QStringLiteral("variable")) 0162 tokenTypes[i] = TokenType::Variable; 0163 else if (type == QStringLiteral("property")) 0164 tokenTypes[i] = TokenType::Property; 0165 else if (type == QStringLiteral("enumMember")) 0166 tokenTypes[i] = TokenType::EnumMember; 0167 else if (type == QStringLiteral("event")) 0168 tokenTypes[i] = TokenType::Event; 0169 else if (type == QStringLiteral("function")) 0170 tokenTypes[i] = TokenType::Function; 0171 else if (type == QStringLiteral("method")) 0172 tokenTypes[i] = TokenType::Method; 0173 else if (type == QStringLiteral("macro")) 0174 tokenTypes[i] = TokenType::Macro; 0175 else if (type == QStringLiteral("keyword")) 0176 tokenTypes[i] = TokenType::Keyword; 0177 else if (type == QStringLiteral("modifier")) 0178 tokenTypes[i] = TokenType::Modifier; 0179 else if (type == QStringLiteral("comment")) 0180 tokenTypes[i] = TokenType::Comment; // Can mean inactive code 0181 else if (type == QStringLiteral("string")) 0182 tokenTypes[i] = TokenType::String; 0183 else if (type == QStringLiteral("number")) 0184 tokenTypes[i] = TokenType::Number; 0185 else if (type == QStringLiteral("regexp")) 0186 tokenTypes[i] = TokenType::Regexp; 0187 else if (type == QStringLiteral("operator")) 0188 tokenTypes[i] = TokenType::Operator; 0189 else if (type == QStringLiteral("namespace")) 0190 tokenTypes[i] = TokenType::Namespace; 0191 else 0192 tokenTypes[i] = TokenType::Unsupported; 0193 i++; 0194 } 0195 totalTokenTypes = tokenTypes.size(); 0196 refresh(tokenTypes); 0197 } 0198 0199 void SemanticTokensLegend::refresh(const std::vector<TokenType> &tokenTypes) 0200 { 0201 sharedAttrs.resize(tokenTypes.size()); 0202 for (size_t i = 0; i < tokenTypes.size(); ++i) { 0203 switch (tokenTypes.at(i)) { 0204 case Type: 0205 case Class: 0206 case Interface: 0207 case Struct: 0208 case Enum: 0209 sharedAttrs[i] = fixedAttrs[TypeAttr]; 0210 break; 0211 case Namespace: 0212 sharedAttrs[i] = fixedAttrs[KeywordAttr]; 0213 break; 0214 case TypeParameter: 0215 case Parameter: 0216 sharedAttrs[i] = fixedAttrs[VarParamAttr]; 0217 break; 0218 case Macro: 0219 sharedAttrs[i] = fixedAttrs[MacroAttr]; 0220 break; 0221 case Function: 0222 case Method: 0223 sharedAttrs[i] = fixedAttrs[FuncAttr]; 0224 break; 0225 case EnumMember: 0226 sharedAttrs[i] = fixedAttrs[ConstantAttr]; 0227 break; 0228 case Comment: 0229 sharedAttrs[i] = fixedAttrs[CommentAttr]; 0230 break; 0231 // Only these for now 0232 default: 0233 sharedAttrs[i] = {}; 0234 } 0235 } 0236 }