Take encoding from settings
[idea/community.git] / platform / platform-impl / src / com / intellij / terminal / TerminalExecutionConsole.java
1 /*
2  * Copyright 2000-2016 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.terminal;
17
18 import com.intellij.execution.filters.Filter;
19 import com.intellij.execution.process.ProcessAdapter;
20 import com.intellij.execution.process.ProcessEvent;
21 import com.intellij.execution.process.ProcessHandler;
22 import com.intellij.execution.process.ProcessOutputTypes;
23 import com.intellij.execution.ui.ConsoleViewContentType;
24 import com.intellij.execution.ui.ExecutionConsole;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.util.Key;
27 import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
28 import com.jediterm.terminal.TerminalStarter;
29 import com.jediterm.terminal.TtyConnector;
30 import com.jediterm.terminal.model.HyperlinkFilter;
31 import com.jediterm.terminal.model.JediTerminal;
32 import com.jediterm.terminal.ui.TerminalSession;
33 import com.jediterm.terminal.util.CharUtils;
34 import org.jetbrains.annotations.NotNull;
35
36 import javax.swing.*;
37 import java.awt.*;
38 import java.io.IOException;
39 import java.util.List;
40 import java.util.stream.Collectors;
41
42 /**
43  * @author traff
44  */
45 public class TerminalExecutionConsole implements ExecutionConsole {
46   private JBTerminalWidget myTerminalWidget;
47
48   public TerminalExecutionConsole(@NotNull Project project, @NotNull ProcessHandler processHandler) {
49     final JBTerminalSystemSettingsProviderBase provider = new JBTerminalSystemSettingsProviderBase();
50     AppendableTerminalDataStream dataStream = new AppendableTerminalDataStream();
51
52
53     myTerminalWidget = new JBTerminalWidget(project, 200, 24, provider, this) {
54       @Override
55       protected TerminalStarter createTerminalStarter(JediTerminal terminal, TtyConnector connector) {
56         return new TerminalStarter(terminal, connector, dataStream);
57       }
58     };
59
60     TerminalSession session = myTerminalWidget
61       .createTerminalSession(new ProcessHandlerTtyConnector(processHandler, EncodingProjectManager.getInstance(project).getDefaultCharset()));
62
63     processHandler.addProcessListener(new ProcessAdapter() {
64       @Override
65       public void startNotified(ProcessEvent event) {
66         session.start();
67       }
68
69       @Override
70       public void onTextAvailable(ProcessEvent event, Key outputType) {
71         try {
72           if (outputType != ProcessOutputTypes.STDOUT) {
73             ConsoleViewContentType contentType = ConsoleViewContentType.getConsoleViewType(outputType);
74             dataStream.append(encodeColor(contentType.getAttributes().getForegroundColor()));
75           }
76           dataStream.append(event.getText());
77           if (outputType != ProcessOutputTypes.STDOUT) {
78             dataStream.append((char)CharUtils.ESC + "[39m"); //restore color
79           }
80
81           if (outputType == ProcessOutputTypes.SYSTEM) {
82             dataStream.append('\r');
83           }
84         }
85         catch (IOException e) {
86           // pass
87         }
88       }
89
90       @Override
91       public void processTerminated(ProcessEvent event) {
92         myTerminalWidget.getTerminalPanel().setCursorVisible(false);
93       }
94     });
95   }
96
97   public void addMessageFilter(Project project, Filter filter) {
98     myTerminalWidget.addHyperlinkFilter(new HyperlinkFilter() {
99       @Override
100       public Result apply(String line) {
101         Filter.Result r = filter.applyFilter(line, line.length());
102         if (r != null) {
103           return new Result() {
104
105             @Override
106             public List<ResultItem> getResultItems() {
107               return r.getResultItems().stream().map((item -> new ResultItem() {
108                 @Override
109                 public int getStartOffset() {
110                   return item.getHighlightStartOffset();
111                 }
112
113                 @Override
114                 public int getEndOffset() {
115                   return item.getHighlightEndOffset();
116                 }
117
118                 @Override
119                 public void navigate() {
120                   item.getHyperlinkInfo().navigate(project);
121                 }
122               })).collect(Collectors.toList());
123             }
124           };
125         }
126         else {
127           return null;
128         }
129       }
130     });
131   }
132
133   private static String encodeColor(Color color) {
134     StringBuilder sb = new StringBuilder();
135     sb.append((char)CharUtils.ESC).append("[").append("38;2;").append(color.getRed()).append(";").append(color.getGreen()).append(";")
136       .append(color.getBlue()).append("m");
137     return sb.toString();
138   }
139
140   @Override
141   public JComponent getComponent() {
142     return myTerminalWidget.getComponent();
143   }
144
145   @Override
146   public JComponent getPreferredFocusableComponent() {
147     return myTerminalWidget.getComponent();
148   }
149
150   @Override
151   public void dispose() {
152     myTerminalWidget = null;
153   }
154 }