mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
terminal: initial "Got it" popup shown near highlighted command, fix warnings (IDEA-259451)
GitOrigin-RevId: 4d7d1a8398363e6e25b9bcefdc2832ffd9c79292
This commit is contained in:
committed by
intellij-monorepo-bot
parent
af4bd9a9cd
commit
dbdf4c717e
@@ -41,7 +41,7 @@ settings.terminal.application.settings=Application Settings
|
||||
settings.terminal.shell.executable.path.browseFolder.description=Shell executable path
|
||||
|
||||
smart_command_execution.notification.title=Run Commands using IDE
|
||||
smart_command_execution.notification.text=Press {0} to run the highlighted action using the relevant IDE feature instead of the terminal. Press {1} for debug. Press Enter to run the command in the terminal as usual. You can turn this behavior on/off in {2} | Tools | Terminal. <a href="{3}"/>Got it!</a>
|
||||
smart_command_execution.notification.text=Press {0} to run the highlighted command<br/>using the corresponding IDE feature.<p/>Press {1} to debug a process.<p><a href='Configure'>Configure...</a>
|
||||
settings.terminal.smart.command.handling=Run Commands using IDE
|
||||
|
||||
toolwindow.stripe.Terminal=Terminal
|
||||
|
||||
@@ -69,7 +69,7 @@ public class ShellTerminalWidget extends JBTerminalWidget {
|
||||
}
|
||||
}
|
||||
else {
|
||||
myShellCommandHandlerHelper.processKeyPressed();
|
||||
myShellCommandHandlerHelper.processKeyPressed(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,23 +6,30 @@ import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.ExecutorRegistry;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Experiments;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.terminal.TerminalShellCommandHandler;
|
||||
import com.intellij.ui.GotItMessage;
|
||||
import com.intellij.ui.HyperlinkAdapter;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.PositionTracker;
|
||||
import com.jediterm.terminal.TerminalColor;
|
||||
import com.jediterm.terminal.TextStyle;
|
||||
import com.jediterm.terminal.TtyConnector;
|
||||
@@ -38,6 +45,7 @@ import org.jetbrains.plugins.terminal.shellCommandRunner.TerminalRunSmartCommand
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -47,21 +55,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public final class TerminalShellCommandHandlerHelper {
|
||||
private static final Logger LOG = Logger.getInstance(TerminalShellCommandHandler.class);
|
||||
@NonNls private static final String TERMINAL_CUSTOM_COMMANDS_GOT_IT = "TERMINAL_CUSTOM_COMMANDS_GOT_IT";
|
||||
@NonNls private static final String GOT_IT = "got_it";
|
||||
@NonNls private static final String FEATURE_ID = "terminal.shell.command.handling";
|
||||
|
||||
private static Experiments ourExperiments;
|
||||
private static final NotificationGroup ourToolWindowGroup =
|
||||
NotificationGroup.toolWindowGroup("Terminal", TerminalToolWindowFactory.TOOL_WINDOW_ID);
|
||||
private final ShellTerminalWidget myWidget;
|
||||
private final Alarm myAlarm;
|
||||
private volatile String myWorkingDirectory;
|
||||
private volatile Boolean myHasRunningCommands;
|
||||
private PropertiesComponent myPropertiesComponent;
|
||||
private final SingletonNotificationManager mySingletonNotificationManager =
|
||||
new SingletonNotificationManager(ourToolWindowGroup, NotificationType.INFORMATION, null);
|
||||
private final AtomicBoolean myKeyPressed = new AtomicBoolean(false);
|
||||
private TerminalLineIntervalHighlighting myCurrentHighlighting;
|
||||
private TerminalLineIntervalHighlighting myCommandHighlighting;
|
||||
private Disposable myNotificationDisposable;
|
||||
|
||||
TerminalShellCommandHandlerHelper(@NotNull ShellTerminalWidget widget) {
|
||||
myWidget = widget;
|
||||
@@ -79,10 +83,12 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
Disposer.register(myWidget, () -> widget.getTerminalTextBuffer().removeModelListener(listener));
|
||||
}
|
||||
|
||||
public void processKeyPressed() {
|
||||
public void processKeyPressed(KeyEvent e) {
|
||||
if (isFeatureEnabled()) {
|
||||
myKeyPressed.set(true);
|
||||
scheduleCommandHighlighting();
|
||||
if (e.getKeyCode() == KeyEvent.VK_ESCAPE && e.getModifiersEx() == 0 && hideNotification()) {
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,48 +110,81 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
|
||||
private void highlightMatchedCommand(@NotNull Project project) {
|
||||
if (!isEnabledForProject()) {
|
||||
setHighlighting(null);
|
||||
setCommandHighlighting(null);
|
||||
return;
|
||||
}
|
||||
|
||||
String command = myWidget.getTypedShellCommand().trim();
|
||||
TerminalLineIntervalHighlighting commandHighlighting = null;
|
||||
if (TerminalShellCommandHandler.Companion.matches(project, getWorkingDirectory(), !hasRunningCommands(), command)) {
|
||||
commandHighlighting = doHighlight(command);
|
||||
}
|
||||
setHighlighting(commandHighlighting);
|
||||
TerminalLineIntervalHighlighting commandHighlighting = highlightCommand(project, command);
|
||||
setCommandHighlighting(commandHighlighting);
|
||||
|
||||
//show notification
|
||||
if (getPropertiesComponent().getBoolean(TERMINAL_CUSTOM_COMMANDS_GOT_IT, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandHighlighting != null) {
|
||||
String title = TerminalBundle.message("smart_command_execution.notification.title");
|
||||
String content = TerminalBundle.message("smart_command_execution.notification.text",
|
||||
KeymapUtil.getFirstKeyboardShortcutText(getRunAction()),
|
||||
KeymapUtil.getFirstKeyboardShortcutText(getDebugAction()),
|
||||
ShowSettingsUtil.getSettingsMenuName(),
|
||||
GOT_IT);
|
||||
NotificationListener.Adapter listener = new NotificationListener.Adapter() {
|
||||
@Override
|
||||
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
|
||||
if (GOT_IT.equals(e.getDescription())) {
|
||||
getPropertiesComponent().setValue(TERMINAL_CUSTOM_COMMANDS_GOT_IT, true, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
mySingletonNotificationManager.notify(title, content, project, listener);
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
showOrHideNotification(commandHighlighting);
|
||||
}, ModalityState.stateForComponent(myWidget.getTerminalPanel()));
|
||||
}
|
||||
|
||||
private synchronized void setHighlighting(@Nullable TerminalLineIntervalHighlighting highlighting) {
|
||||
TerminalLineIntervalHighlighting oldHighlighting = myCurrentHighlighting;
|
||||
private synchronized void setCommandHighlighting(@Nullable TerminalLineIntervalHighlighting commandHighlighting) {
|
||||
TerminalLineIntervalHighlighting oldHighlighting = myCommandHighlighting;
|
||||
if (oldHighlighting != null) {
|
||||
oldHighlighting.dispose();
|
||||
myWidget.getTerminalPanel().repaint();
|
||||
}
|
||||
myCurrentHighlighting = highlighting;
|
||||
myCommandHighlighting = commandHighlighting;
|
||||
}
|
||||
|
||||
private boolean hideNotification() {
|
||||
boolean shown = myNotificationDisposable != null && !Disposer.isDisposed(myNotificationDisposable);
|
||||
if (shown) {
|
||||
Disposer.dispose(myNotificationDisposable);
|
||||
}
|
||||
myNotificationDisposable = null;
|
||||
return shown;
|
||||
}
|
||||
|
||||
private void showOrHideNotification(@Nullable TerminalLineIntervalHighlighting commandHighlighting) {
|
||||
if (commandHighlighting == null) {
|
||||
hideNotification();
|
||||
return;
|
||||
}
|
||||
if (myNotificationDisposable != null && !Disposer.isDisposed(myNotificationDisposable)) {
|
||||
return;
|
||||
}
|
||||
String title = TerminalBundle.message("smart_command_execution.notification.title");
|
||||
String content = TerminalBundle.message("smart_command_execution.notification.text",
|
||||
KeymapUtil.getFirstKeyboardShortcutText(getRunAction()),
|
||||
KeymapUtil.getFirstKeyboardShortcutText(getDebugAction()));
|
||||
GotItMessage message = GotItMessage.createMessage(title, content);
|
||||
myNotificationDisposable = Disposer.newDisposable();
|
||||
Disposer.register(myWidget.getTerminalPanel(), myNotificationDisposable);
|
||||
message.setDisposable(myNotificationDisposable);
|
||||
message.setShowCallout(true);
|
||||
message.setHyperlinkListener(new HyperlinkAdapter() {
|
||||
@Override
|
||||
protected void hyperlinkActivated(HyperlinkEvent e) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myWidget.getProject(), TerminalOptionsConfigurable.class);
|
||||
}
|
||||
});
|
||||
message.setCallback(() -> {
|
||||
hideNotification();
|
||||
getPropertiesComponent().setValue(TERMINAL_CUSTOM_COMMANDS_GOT_IT, true);
|
||||
});
|
||||
JComponent component = myWidget.getTerminalPanel();
|
||||
message.show(new PositionTracker<>(component) {
|
||||
@Override
|
||||
public RelativePoint recalculateLocation(@NotNull Balloon balloon) {
|
||||
RelativePoint point = RelativePoint.getNorthWestOf(component);
|
||||
Rectangle bounds = myWidget.getTerminalPanel().getBounds(commandHighlighting);
|
||||
if (bounds != null) {
|
||||
point.getPoint().translate(bounds.x + bounds.width / 2, bounds.y + bounds.height);
|
||||
}
|
||||
return point;
|
||||
}
|
||||
}, Balloon.Position.below);
|
||||
}
|
||||
|
||||
private boolean isEnabledForProject() {
|
||||
@@ -181,8 +220,11 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
return hasRunningCommands;
|
||||
}
|
||||
|
||||
private @Nullable TerminalLineIntervalHighlighting doHighlight(@NotNull String command) {
|
||||
if (command.length() == 0) {
|
||||
private @Nullable TerminalLineIntervalHighlighting highlightCommand(@NotNull Project project, @NotNull String command) {
|
||||
if (command.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (!TerminalShellCommandHandler.Companion.matches(project, getWorkingDirectory(), !hasRunningCommands(), command)) {
|
||||
return null;
|
||||
}
|
||||
return myWidget.processTerminalBuffer(textBuffer -> {
|
||||
@@ -209,6 +251,7 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
onShellCommandExecuted();
|
||||
return false;
|
||||
}
|
||||
myKeyPressed.set(true);
|
||||
String command = myWidget.getTypedShellCommand().trim();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("typed shell command to execute: " + command);
|
||||
@@ -274,7 +317,7 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
final KeyboardShortcut eventShortcut = new KeyboardShortcut(KeyStroke.getKeyStrokeForEvent(e), null);
|
||||
AnAction action = getRunAction();
|
||||
return action instanceof TerminalRunSmartCommandAction
|
||||
&& Arrays.stream(action.getShortcutSet().getShortcuts()).anyMatch(sc -> sc.isKeyboard() && sc.startsWith(eventShortcut))
|
||||
&& ContainerUtil.exists(action.getShortcutSet().getShortcuts(), sc -> sc.isKeyboard() && sc.startsWith(eventShortcut))
|
||||
? ((TerminalRunSmartCommandAction)action)
|
||||
: null;
|
||||
}
|
||||
@@ -283,7 +326,7 @@ public final class TerminalShellCommandHandlerHelper {
|
||||
final KeyboardShortcut eventShortcut = new KeyboardShortcut(KeyStroke.getKeyStrokeForEvent(e), null);
|
||||
AnAction action = getDebugAction();
|
||||
return action instanceof TerminalDebugSmartCommandAction
|
||||
&& Arrays.stream(action.getShortcutSet().getShortcuts()).anyMatch(sc -> sc.isKeyboard() && sc.startsWith(eventShortcut))
|
||||
&& ContainerUtil.exists(action.getShortcutSet().getShortcuts(), sc -> sc.isKeyboard() && sc.startsWith(eventShortcut))
|
||||
? ((TerminalDebugSmartCommandAction)action)
|
||||
: null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user