-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
terminal: provide a quick way to open installed shells or WSLs (IDEA-…
…268890) GitOrigin-RevId: 92d6408d22b36cabb14dc2f26db63b9cc9477f31
- Loading branch information
1 parent
d64f96b
commit f073431
Showing
3 changed files
with
197 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalNewPredefinedSessionAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. | ||
package org.jetbrains.plugins.terminal; | ||
|
||
import com.intellij.execution.configurations.PathEnvironmentVariableUtil; | ||
import com.intellij.execution.wsl.WSLDistribution; | ||
import com.intellij.execution.wsl.WslDistributionManager; | ||
import com.intellij.icons.AllIcons; | ||
import com.intellij.ide.IdeBundle; | ||
import com.intellij.openapi.actionSystem.*; | ||
import com.intellij.openapi.application.ApplicationManager; | ||
import com.intellij.openapi.options.ShowSettingsUtil; | ||
import com.intellij.openapi.project.DumbAwareAction; | ||
import com.intellij.openapi.project.Project; | ||
import com.intellij.openapi.ui.popup.JBPopup; | ||
import com.intellij.openapi.ui.popup.JBPopupFactory; | ||
import com.intellij.openapi.ui.popup.ListPopup; | ||
import com.intellij.openapi.util.NlsActions; | ||
import com.intellij.openapi.util.NlsSafe; | ||
import com.intellij.openapi.util.SystemInfo; | ||
import com.intellij.openapi.util.text.StringUtil; | ||
import com.intellij.ui.awt.RelativePoint; | ||
import com.intellij.ui.popup.PopupState; | ||
import com.intellij.util.EnvironmentUtil; | ||
import com.intellij.util.containers.ContainerUtil; | ||
import com.intellij.util.ui.JBUI; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.awt.event.InputEvent; | ||
import java.awt.event.MouseEvent; | ||
import java.io.File; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.function.Supplier; | ||
|
||
public class TerminalNewPredefinedSessionAction extends DumbAwareAction { | ||
|
||
private final PopupState<JBPopup> myPopupState = PopupState.forPopup(); | ||
|
||
public TerminalNewPredefinedSessionAction() { | ||
super(TerminalBundle.messagePointer("action.NewPredefinedSession.label")); | ||
getTemplatePresentation().setIcon(AllIcons.Toolbar.Expand); | ||
} | ||
|
||
@Override | ||
public void actionPerformed(@NotNull AnActionEvent e) { | ||
Project project = e.getProject(); | ||
if (project == null || myPopupState.isRecentlyHidden()) return; | ||
RelativePoint popupPoint = getPreferredPopupPoint(e); | ||
ApplicationManager.getApplication().executeOnPooledThread(() -> { | ||
List<OpenShellAction> shells = detectShells(); | ||
List<OpenShellAction> wsl = listOpenWslShellActions(); | ||
ApplicationManager.getApplication().invokeLater(() -> { | ||
ListPopup popup = createPopup(shells, wsl, e.getDataContext()); | ||
if (popupPoint != null) { | ||
popup.show(popupPoint); | ||
} | ||
else { | ||
popup.showInFocusCenter(); | ||
} | ||
myPopupState.prepareToShow(popup); | ||
}); | ||
}); | ||
} | ||
|
||
private static @Nullable RelativePoint getPreferredPopupPoint(@NotNull AnActionEvent e) { | ||
InputEvent inputEvent = e.getInputEvent(); | ||
if (inputEvent instanceof MouseEvent) { | ||
Component comp = inputEvent.getComponent(); | ||
if (comp instanceof AnActionHolder) { | ||
return new RelativePoint(comp.getParent(), new Point(comp.getX() + JBUI.scale(3), comp.getY() + comp.getHeight() + JBUI.scale(3))); | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private static @NotNull ListPopup createPopup(@NotNull List<OpenShellAction> shells, | ||
@NotNull List<OpenShellAction> wsl, | ||
@NotNull DataContext dataContext) { | ||
DefaultActionGroup group = new DefaultActionGroup(); | ||
group.addAll(shells); | ||
group.addAll(wsl); | ||
if (!wsl.isEmpty()) { | ||
group.addSeparator(); | ||
} | ||
group.add(new TerminalSettingsAction()); | ||
return JBPopupFactory.getInstance().createActionGroupPopup(null, group, dataContext, | ||
false, true, true, null, -1, null); | ||
} | ||
|
||
private static @NotNull List<OpenShellAction> listOpenWslShellActions() { | ||
if (WSLDistribution.findWslExe() == null) return List.of(); | ||
List<WSLDistribution> distributions = WslDistributionManager.getInstance().getInstalledDistributions(); | ||
return ContainerUtil.map(distributions, (d) -> { | ||
return new OpenShellAction(() -> d.getMsId(), List.of("wsl.exe", "-d", d.getMsId()), AllIcons.RunConfigurations.Wsl); | ||
}); | ||
} | ||
|
||
private static @NotNull List<OpenShellAction> detectShells() { | ||
List<OpenShellAction> actions = new ArrayList<>(); | ||
if (SystemInfo.isUnix) { | ||
ContainerUtil.addIfNotNull(actions, create("/bin/bash", List.of(), "Bash")); | ||
if (Files.exists(Path.of("/usr/local/bin/zsh"))) { | ||
ContainerUtil.addIfNotNull(actions, create("/usr/local/bin/zsh", List.of(), "Zsh")); | ||
} | ||
else { | ||
ContainerUtil.addIfNotNull(actions, create("/usr/bin/zsh", List.of(), "Zsh")); | ||
} | ||
ContainerUtil.addIfNotNull(actions, create("/usr/bin/fish", List.of(), "Fish")); | ||
} | ||
else if (SystemInfo.isWindows) { | ||
File powershell = PathEnvironmentVariableUtil.findInPath("powershell.exe"); | ||
if (powershell != null && StringUtil.startsWithIgnoreCase(powershell.getAbsolutePath(), "C:\\Windows\\System32\\WindowsPowerShell\\")) { | ||
ContainerUtil.addIfNotNull(actions, create(powershell.getAbsolutePath(), List.of(), "Windows PowerShell")); | ||
} | ||
File cmd = PathEnvironmentVariableUtil.findInPath("cmd.exe"); | ||
if (cmd != null && StringUtil.startsWithIgnoreCase(cmd.getAbsolutePath(), "C:\\Windows\\System32\\")) { | ||
ContainerUtil.addIfNotNull(actions, create(cmd.getAbsolutePath(), List.of(), "Command Prompt")); | ||
} | ||
File pwsh = PathEnvironmentVariableUtil.findInPath("pwsh.exe"); | ||
if (pwsh != null && StringUtil.startsWithIgnoreCase(pwsh.getAbsolutePath(), "C:\\Program Files\\PowerShell\\")) { | ||
ContainerUtil.addIfNotNull(actions, create(pwsh.getAbsolutePath(), List.of(), "PowerShell")); | ||
} | ||
File gitBash = new File("C:\\Program Files\\Git\\bin\\bash.exe"); | ||
if (gitBash.isFile()) { | ||
ContainerUtil.addIfNotNull(actions, create(gitBash.getAbsolutePath(), List.of(), "Git Bash")); | ||
} | ||
String cmderRoot = EnvironmentUtil.getValue("CMDER_ROOT"); | ||
if (cmderRoot != null && cmd != null && StringUtil.startsWithIgnoreCase(cmd.getAbsolutePath(), "C:\\Windows\\System32\\")) { | ||
File cmderInitBat = new File(cmderRoot, "vendor\\init.bat"); | ||
if (cmderInitBat.isFile()) { | ||
ContainerUtil.addIfNotNull(actions, create(cmd.getAbsolutePath(), List.of("/k", cmderInitBat.getAbsolutePath()), "Cmder")); | ||
} | ||
} | ||
} | ||
return actions; | ||
} | ||
|
||
private static @Nullable OpenShellAction create(@NotNull String shellPath, @NotNull List<String> shellOptions, @NlsSafe String presentableName) { | ||
if (Files.exists(Path.of(shellPath))) { | ||
return new OpenShellAction(() -> presentableName, ContainerUtil.concat(List.of(shellPath), shellOptions), null); | ||
} | ||
return null; | ||
} | ||
|
||
private static class TerminalSettingsAction extends DumbAwareAction { | ||
|
||
private TerminalSettingsAction() { | ||
super(IdeBundle.message("action.text.settings"), null, AllIcons.General.Settings); | ||
} | ||
|
||
@Override | ||
public void actionPerformed(@NotNull AnActionEvent e) { | ||
Project project = e.getProject(); | ||
if (project != null) { | ||
ShowSettingsUtil.getInstance().showSettingsDialog(project, TerminalOptionsConfigurable.class); | ||
} | ||
} | ||
} | ||
|
||
private static class OpenShellAction extends DumbAwareAction { | ||
|
||
private final List<String> myCommand; | ||
private final Supplier<@NlsActions.ActionText String> myPresentableName; | ||
|
||
private OpenShellAction(@NotNull Supplier<@NlsActions.ActionText String> presentableName, @NotNull List<String> command, @Nullable Icon icon) { | ||
super(presentableName, icon); | ||
myPresentableName = presentableName; | ||
myCommand = command; | ||
} | ||
|
||
@Override | ||
public void actionPerformed(@NotNull AnActionEvent e) { | ||
Project project = e.getProject(); | ||
if (project != null) { | ||
LocalTerminalDirectRunner runner = new LocalTerminalDirectRunner(project) { | ||
@Override | ||
public @NotNull List<String> getInitialCommand(@NotNull Map<String, String> envs) { | ||
return myCommand; | ||
} | ||
}; | ||
TerminalTabState tabState = new TerminalTabState(); | ||
tabState.myTabName = myPresentableName.get(); | ||
TerminalView.getInstance(project).createNewSession(runner, tabState); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters