support underline effect with default foreground (IDEA-149450)
[idea/community.git] / platform / platform-api / src / com / intellij / execution / process / ColoredOutputTypeRegistry.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.execution.process;
17
18 import com.intellij.execution.ui.ConsoleViewContentType;
19 import com.intellij.openapi.components.ServiceManager;
20 import com.intellij.openapi.editor.colors.EditorColorsManager;
21 import com.intellij.openapi.editor.colors.EditorColorsScheme;
22 import com.intellij.openapi.editor.colors.TextAttributesKey;
23 import com.intellij.openapi.editor.markup.EffectType;
24 import com.intellij.openapi.editor.markup.TextAttributes;
25 import com.intellij.openapi.util.Key;
26 import com.intellij.openapi.util.text.StringUtil;
27 import org.jetbrains.annotations.NonNls;
28 import org.jetbrains.annotations.NotNull;
29
30 import java.awt.*;
31
32 /**
33  * @author yole
34  */
35 public class ColoredOutputTypeRegistry {
36   public static ColoredOutputTypeRegistry getInstance() {
37     return ServiceManager.getService(ColoredOutputTypeRegistry.class);
38   }
39
40   private static final TextAttributesKey[] myAnsiColorKeys = new TextAttributesKey[]{
41     ConsoleHighlighter.BLACK,
42     ConsoleHighlighter.RED,
43     ConsoleHighlighter.GREEN,
44     ConsoleHighlighter.YELLOW,
45     ConsoleHighlighter.BLUE,
46     ConsoleHighlighter.MAGENTA,
47     ConsoleHighlighter.CYAN,
48     ConsoleHighlighter.GRAY,
49
50     ConsoleHighlighter.DARKGRAY,
51     ConsoleHighlighter.RED_BRIGHT,
52     ConsoleHighlighter.GREEN_BRIGHT,
53     ConsoleHighlighter.YELLOW_BRIGHT,
54     ConsoleHighlighter.BLUE_BRIGHT,
55     ConsoleHighlighter.MAGENTA_BRIGHT,
56     ConsoleHighlighter.CYAN_BRIGHT,
57     ConsoleHighlighter.WHITE,
58   };
59
60   /*
61     Description
62      0  Cancel all attributes except foreground/background color
63      1  Bright (bold)
64      2  Normal (not bold)
65      4  Underline
66      5  Blink
67      7  Reverse video
68      8  Concealed (don't display characters)
69      30 Make foreground (the characters) black
70      31 Make foreground red
71      32 Make foreground green
72      33 Make foreground yellow
73      34 Make foreground blue
74      35 Make foreground magenta
75      36 Make foreground cyan
76      37 Make foreground white
77
78      40 Make background (around the characters) black
79      41 Make background red
80      42 Make background green
81      43 Make background yellow
82      44 Make background blue
83      45 Make background magenta
84      46 Make background cyan
85      47 Make background white (you may need 0 instead, or in addition)
86
87      see full doc at http://en.wikipedia.org/wiki/ANSI_escape_code
88   */
89
90   @NotNull
91   public Key getOutputKey(@NonNls String attribute) {
92     final String completeAttribute = attribute;
93     if (attribute.startsWith("\u001B[")) {
94       attribute = attribute.substring(2);
95     }
96     else {
97       attribute = StringUtil.trimStart(attribute, "[");
98     }
99     attribute = StringUtil.trimEnd(attribute, "m");
100     if (attribute.equals("0")) {
101       return ProcessOutputTypes.STDOUT;
102     }
103     TextAttributes attrs = new TextAttributes();
104     final String[] strings = attribute.split(";");
105     for (String string : strings) {
106       int value;
107       try {
108         value = Integer.parseInt(string);
109       }
110       catch (NumberFormatException e) {
111         continue;
112       }
113       if (value == 1) {
114         attrs.setFontType(Font.BOLD);
115       }
116       else if (value == 4) {
117         attrs.setEffectType(EffectType.LINE_UNDERSCORE);
118       }
119       else if (value == 22) {
120         attrs.setFontType(Font.PLAIN);
121       }
122       else if (value == 24) {  //not underlined
123         attrs.setEffectType(null);
124       }
125       else if (value >= 30 && value <= 37) {
126         attrs.setForegroundColor(getAnsiColor(value - 30));
127       }
128       else if (value == 38) {
129         //TODO: 256 colors foreground
130       }
131       else if (value == 39) {
132         attrs.setForegroundColor(getDefaultForegroundColor());
133       }
134       else if (value >= 40 && value <= 47) {
135         attrs.setBackgroundColor(getAnsiColor(value - 40));
136       }
137       else if (value == 48) {
138         //TODO: 256 colors background
139       }
140       else if (value == 49) {
141         attrs.setBackgroundColor(getDefaultBackgroundColor());
142       }
143       else if (value >= 90 && value <= 97) {
144         attrs.setForegroundColor(
145           getAnsiColor(value - 82));
146       }
147       else if (value >= 100 && value <= 107) {
148         attrs.setBackgroundColor(
149           getAnsiColor(value - 92));
150       }
151     }
152     if (attrs.getEffectType() == EffectType.LINE_UNDERSCORE) {
153       Color foregroundColor = attrs.getForegroundColor();
154       if (foregroundColor == null) {
155         foregroundColor = getDefaultForegroundColor();
156       }
157       attrs.setEffectColor(foregroundColor);
158     }
159     Key newKey = new Key(completeAttribute);
160     ConsoleViewContentType contentType = new ConsoleViewContentType(completeAttribute, attrs);
161     ConsoleViewContentType.registerNewConsoleViewType(newKey, contentType);
162     return newKey;
163   }
164
165   private static Color getAnsiColor(final int value) {
166     return getColorByKey(getAnsiColorKey(value));
167   }
168
169   private static Color getColorByKey(TextAttributesKey colorKey) {
170     return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(colorKey).getForegroundColor();
171   }
172
173   @NotNull
174   private static Color getDefaultForegroundColor() {
175     EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
176     TextAttributes attr = scheme.getAttributes(ConsoleViewContentType.NORMAL_OUTPUT_KEY);
177     Color color = attr != null ? attr.getForegroundColor() : null;
178     if (color == null) {
179       color = scheme.getDefaultForeground();
180     }
181     return color;
182   }
183
184   @NotNull
185   private static Color getDefaultBackgroundColor() {
186     EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
187     Color color = scheme.getColor(ConsoleViewContentType.CONSOLE_BACKGROUND_KEY);
188     if (color == null) {
189       color = scheme.getDefaultBackground();
190     }
191     return color;
192   }
193
194   public static TextAttributesKey getAnsiColorKey(int value) {
195     if (value >= 16) {
196       return ConsoleViewContentType.NORMAL_OUTPUT_KEY;
197     }
198     return myAnsiColorKeys[value];
199   }
200 }