1 // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.jetbrains.python.highlighting;
4 import com.google.common.collect.ImmutableMap;
5 import com.intellij.application.options.colors.InspectionColorSettingsPage;
6 import com.intellij.codeHighlighting.RainbowHighlighter;
7 import com.intellij.lang.Language;
8 import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
9 import com.intellij.openapi.editor.colors.TextAttributesKey;
10 import com.intellij.openapi.fileTypes.SyntaxHighlighter;
11 import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
12 import com.intellij.openapi.options.colors.AttributesDescriptor;
13 import com.intellij.openapi.options.colors.ColorDescriptor;
14 import com.intellij.openapi.options.colors.RainbowColorSettingsPage;
15 import com.intellij.psi.codeStyle.DisplayPriority;
16 import com.intellij.psi.codeStyle.DisplayPrioritySortable;
17 import com.intellij.util.PlatformUtils;
18 import com.jetbrains.python.PyBundle;
19 import com.jetbrains.python.PythonFileType;
20 import com.jetbrains.python.PythonLanguage;
21 import com.jetbrains.python.psi.LanguageLevel;
22 import org.jetbrains.annotations.NonNls;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
32 public class PythonColorsPage implements RainbowColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable {
33 private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] {
34 new AttributesDescriptor(PyBundle.message("python.colors.number"), PyHighlighter.PY_NUMBER),
35 new AttributesDescriptor(PyBundle.message("python.colors.keyword"), PyHighlighter.PY_KEYWORD),
36 new AttributesDescriptor(PyBundle.message("python.colors.line.comment"), PyHighlighter.PY_LINE_COMMENT),
38 new AttributesDescriptor(PyBundle.message("python.colors.string.binary.bytes"), PyHighlighter.PY_BYTE_STRING),
39 new AttributesDescriptor(PyBundle.message("python.colors.string.text.unicode"), PyHighlighter.PY_UNICODE_STRING),
40 new AttributesDescriptor(PyBundle.message("python.colors.string.escape.sequence.valid"), PyHighlighter.PY_VALID_STRING_ESCAPE),
41 new AttributesDescriptor(PyBundle.message("python.colors.string.escape.sequence.invalid"), PyHighlighter.PY_INVALID_STRING_ESCAPE),
42 new AttributesDescriptor(PyBundle.message("python.colors.string.f.string.expression.braces"), PyHighlighter.PY_FSTRING_FRAGMENT_BRACES),
43 new AttributesDescriptor(PyBundle.message("python.colors.string.f.string.type.conversion"), PyHighlighter.PY_FSTRING_FRAGMENT_TYPE_CONVERSION),
44 new AttributesDescriptor(PyBundle.message("python.colors.string.f.string.format.specifier.start"), PyHighlighter.PY_FSTRING_FRAGMENT_COLON),
46 new AttributesDescriptor(PyBundle.message("python.colors.docstring.text"), PyHighlighter.PY_DOC_COMMENT),
47 new AttributesDescriptor(PyBundle.message("python.colors.docstring.tag"), PyHighlighter.PY_DOC_COMMENT_TAG),
49 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.operation.sign"), PyHighlighter.PY_OPERATION_SIGN),
50 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.parentheses"), PyHighlighter.PY_PARENTHS),
51 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.brackets"), PyHighlighter.PY_BRACKETS),
52 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.braces"), PyHighlighter.PY_BRACES),
53 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.comma"), PyHighlighter.PY_COMMA),
54 new AttributesDescriptor(PyBundle.message("python.colors.braces.and.operators.dot"), PyHighlighter.PY_DOT),
56 new AttributesDescriptor(PyBundle.message("python.colors.functions.function.definition"), PyHighlighter.PY_FUNC_DEFINITION),
57 new AttributesDescriptor(PyBundle.message("python.colors.functions.nested.function.definition"), PyHighlighter.PY_NESTED_FUNC_DEFINITION),
58 new AttributesDescriptor(PyBundle.message("python.colors.functions.function.call"), PyHighlighter.PY_FUNCTION_CALL),
59 new AttributesDescriptor(PyBundle.message("python.colors.functions.method.call"), PyHighlighter.PY_METHOD_CALL),
61 new AttributesDescriptor(PyBundle.message("python.colors.parameters.parameter"), PyHighlighter.PY_PARAMETER),
62 new AttributesDescriptor(PyBundle.message("python.colors.parameters.self.parameter"), PyHighlighter.PY_SELF_PARAMETER),
64 new AttributesDescriptor(PyBundle.message("python.colors.keyword.argument"), PyHighlighter.PY_KEYWORD_ARGUMENT),
66 new AttributesDescriptor(PyBundle.message("python.colors.special.names.definition"), PyHighlighter.PY_PREDEFINED_DEFINITION),
67 new AttributesDescriptor(PyBundle.message("python.colors.special.names.usage"), PyHighlighter.PY_PREDEFINED_USAGE),
69 new AttributesDescriptor(PyBundle.message("python.colors.built.in.name"), PyHighlighter.PY_BUILTIN_NAME),
70 new AttributesDescriptor(PyBundle.message("python.colors.decorator"), PyHighlighter.PY_DECORATOR),
71 new AttributesDescriptor(PyBundle.message("python.colors.class.definition"), PyHighlighter.PY_CLASS_DEFINITION),
72 new AttributesDescriptor(PyBundle.message("python.colors.type.annotation"), PyHighlighter.PY_ANNOTATION),
75 @NonNls private static final Map<String,TextAttributesKey> ourTagToDescriptorMap = ImmutableMap.<String, TextAttributesKey>builder()
76 .put("docComment", PyHighlighter.PY_DOC_COMMENT)
77 .put("docCommentTag", PyHighlighter.PY_DOC_COMMENT_TAG)
78 .put("decorator", PyHighlighter.PY_DECORATOR)
79 .put("predefined", PyHighlighter.PY_PREDEFINED_DEFINITION)
80 .put("predefinedUsage", PyHighlighter.PY_PREDEFINED_USAGE)
81 .put("funcDef", PyHighlighter.PY_FUNC_DEFINITION)
82 .put("nestedFuncDef", PyHighlighter.PY_NESTED_FUNC_DEFINITION)
83 .put("classDef", PyHighlighter.PY_CLASS_DEFINITION)
84 .put("builtin", PyHighlighter.PY_BUILTIN_NAME)
85 .put("self", PyHighlighter.PY_SELF_PARAMETER)
86 .put("param", PyHighlighter.PY_PARAMETER)
87 .put("kwarg", PyHighlighter.PY_KEYWORD_ARGUMENT)
88 .put("call", PyHighlighter.PY_FUNCTION_CALL)
89 .put("mcall", PyHighlighter.PY_METHOD_CALL)
90 .put("annotation", PyHighlighter.PY_ANNOTATION)
91 .put("localVar", DefaultLanguageHighlighterColors.LOCAL_VARIABLE)
92 .putAll(RainbowHighlighter.createRainbowHLM())
97 public String getDisplayName() {
98 return PyBundle.message("python.colors.python");
102 public Icon getIcon() {
103 return PythonFileType.INSTANCE.getIcon();
107 public AttributesDescriptor @NotNull [] getAttributeDescriptors() {
112 public ColorDescriptor @NotNull [] getColorDescriptors() {
113 return ColorDescriptor.EMPTY_ARRAY;
118 public SyntaxHighlighter getHighlighter() {
119 final SyntaxHighlighterFactory factory = SyntaxHighlighterFactory.LANGUAGE_FACTORY.forLanguage(PythonLanguage.getInstance());
120 if (factory instanceof PySyntaxHighlighterFactory) {
121 return ((PySyntaxHighlighterFactory)factory).getSyntaxHighlighterForLanguageLevel(LanguageLevel.getLatest());
123 return factory.getSyntaxHighlighter(null, null);
128 public String getDemoText() {
130 "@<decorator>decorator</decorator>(<kwarg>param</kwarg>=1)\n" +
131 "def f(<param>x</param>):\n" +
132 " <docComment>\"\"\" Syntax Highlighting Demo\n" +
133 " <docCommentTag>@param</docCommentTag> x Parameter\n" +
135 RainbowHighlighter.generatePaletteExample("\n ") + "\n" +
136 " \"\"\"</docComment>\n" +
137 " def <nestedFuncDef>nested_func</nestedFuncDef>(<param>y</param>):\n" +
138 " <call>print</call>(<param>y</param> + 1)\n" +
139 " <localVar>s</localVar> = (\"Test\", 2+3, {'a': 'b'}, f'{<param>x</param>!s:{\"^10\"}}') # Comment\n" +
140 " <call>f</call>(<localVar>s</localVar>[0].<mcall>lower()</mcall>)\n" +
141 " <call>nested_func(42)</call>" +
143 "class <classDef>Foo</classDef>:\n" +
144 " tags: <annotation>List[<builtin>str</builtin>]</annotation>\n" +
145 " def <predefined>__init__</predefined>(<self>self</self>: <annotation>Foo</annotation>):\n" +
146 " <localVar>byte_string</localVar>: <annotation><builtin>bytes</builtin></annotation> = b'newline:\\n also newline:\\x0a'\n" +
147 " <localVar>text_string</localVar> = u\"Cyrillic Я is \\u042f. Oops: \\u042g\"\n" +
148 " <self>self</self>.<mcall>make_sense</mcall>(<kwarg>whatever</kwarg>=1)\n" +
150 " def <funcDef>make_sense</funcDef>(<self>self</self>, <param>whatever</param>):\n" +
151 " <self>self</self>.sense = <param>whatever</param>\n" +
153 "<localVar>x</localVar> = <builtin>len</builtin>('abc')\n" +
154 "print(f.<predefinedUsage>__doc__</predefinedUsage>)"
159 public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
160 return ourTagToDescriptorMap;
164 public DisplayPriority getPriority() {
165 return PlatformUtils.isPyCharm() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS;
169 public boolean isRainbowType(TextAttributesKey type) {
170 return PyRainbowVisitor.Holder.getHIGHLIGHTING_KEYS().contains(type);
175 public Language getLanguage() {
176 return PythonLanguage.INSTANCE;