mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Rework terminal integrations
This commit is contained in:
parent
3293f27e6f
commit
91e1a37cdb
9 changed files with 707 additions and 347 deletions
|
@ -137,10 +137,10 @@ public class AppPrefs {
|
|||
new AboutCategory(),
|
||||
new SystemCategory(),
|
||||
new AppearanceCategory(),
|
||||
new SyncCategory(),
|
||||
new VaultCategory(),
|
||||
new TerminalCategory(),
|
||||
new EditorCategory(),
|
||||
new SyncCategory(),
|
||||
new VaultCategory(),
|
||||
new LocalShellCategory(),
|
||||
new SecurityCategory(),
|
||||
new PasswordManagerCategory(),
|
||||
|
|
|
@ -5,9 +5,12 @@ import io.xpipe.app.core.AppI18n;
|
|||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.impl.ChoiceComp;
|
||||
import io.xpipe.app.fxcomps.impl.HorizontalComp;
|
||||
import io.xpipe.app.fxcomps.impl.StackComp;
|
||||
import io.xpipe.app.fxcomps.impl.TextFieldComp;
|
||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||
import io.xpipe.app.terminal.ExternalTerminalType;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.TerminalLauncher;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
@ -15,6 +18,8 @@ import io.xpipe.core.store.LocalStore;
|
|||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -26,6 +31,57 @@ public class TerminalCategory extends AppPrefsCategory {
|
|||
return "terminal";
|
||||
}
|
||||
|
||||
private Comp<?> terminalChoice() {
|
||||
var prefs = AppPrefs.get();
|
||||
var c = ChoiceComp.ofTranslatable(
|
||||
prefs.terminalType, PrefsChoiceValue.getSupported(ExternalTerminalType.class), false);
|
||||
c.apply(struc -> {
|
||||
struc.get().setCellFactory(param -> {
|
||||
return new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(ExternalTerminalType item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
setText(item.toTranslatedString().getValue());
|
||||
if (item != ExternalTerminalType.CUSTOM) {
|
||||
var graphic = new FontIcon(item.isRecommended() ? "mdi2c-check-decagram" : "mdi2a-alert-circle-check");
|
||||
graphic.setFill(item.isRecommended() ? Color.GREEN : Color.ORANGE);
|
||||
setGraphic(graphic);
|
||||
} else {
|
||||
setGraphic(new FontIcon("mdi2m-minus-circle"));
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
var visit = new ButtonComp(AppI18n.observable("website"), new FontIcon("mdi2w-web"), () -> {
|
||||
var t = prefs.terminalType().getValue();
|
||||
if (t == null || t.getWebsite() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Hyperlinks.open(t.getWebsite());
|
||||
});
|
||||
var visitVisible = BindingsHelper.persist(Bindings.createBooleanBinding(() -> {
|
||||
var t = prefs.terminalType().getValue();
|
||||
if (t == null || t.getWebsite() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, prefs.terminalType()));
|
||||
visit.visible(visitVisible);
|
||||
|
||||
return new HorizontalComp(List.of(c, visit)).apply(struc -> {
|
||||
struc.get().setAlignment(Pos.CENTER_LEFT);
|
||||
struc.get().setSpacing(10);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Comp<?> create() {
|
||||
var prefs = AppPrefs.get();
|
||||
|
@ -46,8 +102,7 @@ public class TerminalCategory extends AppPrefsCategory {
|
|||
.addTitle("terminalConfiguration")
|
||||
.sub(new OptionsBuilder()
|
||||
.nameAndDescription("terminalEmulator")
|
||||
.addComp(ChoiceComp.ofTranslatable(
|
||||
prefs.terminalType, PrefsChoiceValue.getSupported(ExternalTerminalType.class), false))
|
||||
.addComp(terminalChoice(), prefs.terminalType)
|
||||
.nameAndDescription("customTerminalCommand")
|
||||
.addComp(new TextFieldComp(prefs.customTerminalCommand, true)
|
||||
.apply(struc -> struc.get().setPromptText("myterminal -e $CMD"))
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
|
||||
public interface AlacrittyTerminalType extends ExternalTerminalType {
|
||||
|
||||
static class Windows extends SimplePathType implements AlacrittyTerminalType {
|
||||
|
||||
public Windows() {
|
||||
super("app.alacritty", "alacritty", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
var b = CommandBuilder.of();
|
||||
|
||||
// if (configuration.getColor() != null) {
|
||||
// b.add("-o")
|
||||
// .addQuoted("colors.primary.background='%s'"
|
||||
// .formatted(configuration.getColor().toHexString()));
|
||||
// }
|
||||
|
||||
// Alacritty is bugged and will not accept arguments with spaces even if they are correctly passed/escaped
|
||||
// So this will not work when the script file has spaces
|
||||
return b.add("-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.add(configuration.getDialectLaunchCommand());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Linux extends SimplePathType implements AlacrittyTerminalType {
|
||||
|
||||
public Linux() {
|
||||
super("app.alacritty", "alacritty", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
return CommandBuilder.of()
|
||||
.add("-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.addFile(configuration.getScriptFile());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExternalTerminalType ALACRITTY_WINDOWS = new Windows();
|
||||
ExternalTerminalType ALACRITTY_LINUX = new Linux();
|
||||
ExternalTerminalType ALACRITTY_MAC_OS = new MacOs();
|
||||
|
||||
@Override
|
||||
default String getWebsite() {
|
||||
return "https://github.com/alacritty/alacritty";
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
class MacOs extends MacOsType implements AlacrittyTerminalType {
|
||||
|
||||
public MacOs() {
|
||||
super("app.alacritty", "Alacritty");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(CommandBuilder.of()
|
||||
.add("open", "-a")
|
||||
.addQuoted("Alacritty.app")
|
||||
.add("-n", "--args", "-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.addFile(configuration.getScriptFile()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.prefs.ExternalApplicationHelper;
|
||||
import io.xpipe.app.prefs.ExternalApplicationType;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class CustomTerminalType extends ExternalApplicationType implements ExternalTerminalType {
|
||||
|
||||
public CustomTerminalType() {
|
||||
super("app.custom");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
var custom = AppPrefs.get().customTerminalCommand().getValue();
|
||||
if (custom == null || custom.isBlank()) {
|
||||
throw ErrorEvent.expected(new IllegalStateException("No custom terminal command specified"));
|
||||
}
|
||||
|
||||
var format = custom.toLowerCase(Locale.ROOT).contains("$cmd") ? custom : custom + " $CMD";
|
||||
try (var pc = LocalShell.getShell()) {
|
||||
var toExecute = ExternalApplicationHelper.replaceFileArgument(format, "CMD", configuration.getScriptFile().toString());
|
||||
// We can't be sure whether the command is blocking or not, so always make it not blocking
|
||||
if (pc.getOsType().equals(OsType.WINDOWS)) {
|
||||
toExecute = "start \"" + configuration.getCleanTitle() + "\" " + toExecute;
|
||||
} else {
|
||||
toExecute = "nohup " + toExecute + " </dev/null &>/dev/null & disown";
|
||||
}
|
||||
pc.executeSimpleCommand(toExecute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.prefs.ExternalApplicationHelper;
|
||||
import io.xpipe.app.prefs.ExternalApplicationType;
|
||||
import io.xpipe.app.storage.DataStoreColor;
|
||||
import io.xpipe.app.util.*;
|
||||
|
@ -23,6 +20,11 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
|
||||
ExternalTerminalType CMD = new SimplePathType("app.cmd", "cmd.exe", true) {
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
|
@ -45,6 +47,11 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
|
||||
ExternalTerminalType POWERSHELL = new SimplePathType("app.powershell", "powershell", true) {
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
|
@ -80,6 +87,11 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
|
||||
ExternalTerminalType PWSH = new SimplePathType("app.pwsh", "pwsh", true) {
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
|
@ -104,121 +116,17 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
ExternalTerminalType ALACRITTY_WINDOWS = new SimplePathType("app.alacritty", "alacritty", false) {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalTerminalType GNOME_TERMINAL = new PathCheckType("app.gnomeTerminal", "gnome-terminal", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
var b = CommandBuilder.of();
|
||||
if (configuration.getColor() != null) {
|
||||
b.add("-o")
|
||||
.addQuoted("colors.primary.background='%s'"
|
||||
.formatted(configuration.getColor().toHexString()));
|
||||
}
|
||||
|
||||
// Alacritty is bugged and will not accept arguments with spaces even if they are correctly passed/escaped
|
||||
// So this will not work when the script file has spaces
|
||||
return b.add("-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.add(configuration.getDialectLaunchCommand());
|
||||
}
|
||||
};
|
||||
ExternalTerminalType TABBY_WINDOWS = new WindowsType("app.tabby", "Tabby") {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(Path file, LaunchConfiguration configuration) throws Exception {
|
||||
// Tabby has a very weird handling of output, even detaching with start does not prevent it from printing
|
||||
if (configuration.getScriptDialect().equals(ShellDialects.CMD)) {
|
||||
// It also freezes with any other input than .bat files, why?
|
||||
LocalShell.getShell().executeSimpleCommand(CommandBuilder.of()
|
||||
.addFile(file.toString())
|
||||
.add("run")
|
||||
.addFile(configuration.getScriptFile())
|
||||
.discardOutput());
|
||||
}
|
||||
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(CommandBuilder.of()
|
||||
.addFile(file.toString())
|
||||
.add("run")
|
||||
.add(configuration.getDialectLaunchCommand())
|
||||
.discardOutput());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Path> determineInstallation() {
|
||||
var perUser = WindowsRegistry.readString(
|
||||
WindowsRegistry.HKEY_CURRENT_USER,
|
||||
"SOFTWARE\\71445fac-d6ef-5436-9da7-5a323762d7f5",
|
||||
"InstallLocation")
|
||||
.map(p -> p + "\\Tabby.exe")
|
||||
.map(Path::of);
|
||||
if (perUser.isPresent()) {
|
||||
return perUser;
|
||||
}
|
||||
|
||||
var systemWide = WindowsRegistry.readString(
|
||||
WindowsRegistry.HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\71445fac-d6ef-5436-9da7-5a323762d7f5",
|
||||
"InstallLocation")
|
||||
.map(p -> p + "\\Tabby.exe")
|
||||
.map(Path::of);
|
||||
return systemWide;
|
||||
}
|
||||
};
|
||||
ExternalTerminalType WEZ_WINDOWS = new WindowsType("app.wezterm", "wezterm-gui") {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(Path file, LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell().executeSimpleCommand(CommandBuilder.of().addFile(file.toString()).add("start").add(configuration.getDialectLaunchCommand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Path> determineInstallation() {
|
||||
Optional<String> launcherDir;
|
||||
launcherDir = WindowsRegistry.readString(
|
||||
WindowsRegistry.HKEY_LOCAL_MACHINE,
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{BCF6F0DA-5B9A-408D-8562-F680AE6E1EAF}_is1",
|
||||
"InstallLocation")
|
||||
.map(p -> p + "\\wezterm-gui.exe");
|
||||
return launcherDir.map(Path::of);
|
||||
}
|
||||
};
|
||||
ExternalTerminalType WEZ_LINUX = new SimplePathType("app.wezterm", "wezterm-gui", true) {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
return CommandBuilder.of().add("start").addFile(configuration.getScriptFile());
|
||||
}
|
||||
};
|
||||
ExternalTerminalType GNOME_TERMINAL = new PathCheckType("app.gnomeTerminal", "gnome-terminal", true) {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
|
@ -243,6 +151,11 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
};
|
||||
ExternalTerminalType KONSOLE = new SimplePathType("app.konsole", "konsole", true) {
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
|
@ -262,6 +175,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType XFCE = new SimplePathType("app.xfce", "xfce4-terminal", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -278,6 +201,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType ELEMENTARY = new SimplePathType("app.elementaryTerminal", "io.elementary.terminal", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -290,6 +223,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType TILIX = new SimplePathType("app.tilix", "tilix", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -306,6 +249,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType TERMINATOR = new SimplePathType("app.terminator", "terminator", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -323,6 +276,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType TERMINOLOGY = new SimplePathType("app.terminology", "terminology", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -340,6 +303,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType COOL_RETRO_TERM = new SimplePathType("app.coolRetroTerm", "cool-retro-term", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -356,6 +329,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType GUAKE = new SimplePathType("app.guake", "guake", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -372,28 +355,17 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
.addFile(configuration.getScriptFile());
|
||||
}
|
||||
};
|
||||
ExternalTerminalType ALACRITTY_LINUX = new SimplePathType("app.alacritty", "alacritty", true) {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalTerminalType TILDA = new SimplePathType("app.tilda", "tilda", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
return CommandBuilder.of()
|
||||
.add("-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.addFile(configuration.getScriptFile());
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
ExternalTerminalType TILDA = new SimplePathType("app.tilda", "tilda", true) {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -406,6 +378,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType XTERM = new SimplePathType("app.xterm", "xterm", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -422,6 +404,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType DEEPIN_TERMINAL = new SimplePathType("app.deepinTerminal", "deepin-terminal", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -434,6 +426,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType Q_TERMINAL = new SimplePathType("app.qTerminal", "qterminal", true) {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
|
@ -446,6 +448,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType MACOS_TERMINAL = new MacOsType("app.macosTerminal", "Terminal") {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
|
@ -467,6 +479,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
};
|
||||
ExternalTerminalType ITERM2 = new MacOsType("app.iterm2", "iTerm") {
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
|
@ -504,6 +526,16 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
};
|
||||
ExternalTerminalType WARP = new MacOsType("app.warp", "Warp") {
|
||||
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
|
@ -523,79 +555,18 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
.addFile(configuration.getScriptFile()));
|
||||
}
|
||||
};
|
||||
ExternalTerminalType TABBY_MAC_OS = new MacOsType("app.tabby", "Tabby") {
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(CommandBuilder.of()
|
||||
.add("open", "-a")
|
||||
.addQuoted("Tabby.app")
|
||||
.add("-n", "--args", "run")
|
||||
.addFile(configuration.getScriptFile()));
|
||||
}
|
||||
};
|
||||
ExternalTerminalType ALACRITTY_MACOS = new MacOsType("app.alacritty", "Alacritty") {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(CommandBuilder.of()
|
||||
.add("open", "-a")
|
||||
.addQuoted("Alacritty.app")
|
||||
.add("-n", "--args", "-t")
|
||||
.addQuoted(configuration.getCleanTitle())
|
||||
.add("-e")
|
||||
.addFile(configuration.getScriptFile()));
|
||||
}
|
||||
};
|
||||
ExternalTerminalType WEZ_MACOS = new MacOsType("app.wezterm", "WezTerm") {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
var c = CommandBuilder.of()
|
||||
.addFile(getApplicationPath()
|
||||
.orElseThrow()
|
||||
.resolve("Contents")
|
||||
.resolve("MacOS")
|
||||
.resolve("wezterm-gui")
|
||||
.toString())
|
||||
.add("start")
|
||||
.add(configuration.getDialectLaunchCommand());
|
||||
ExternalApplicationHelper.startAsync(c);
|
||||
}
|
||||
};
|
||||
ExternalTerminalType CUSTOM = new CustomType();
|
||||
ExternalTerminalType CUSTOM = new CustomTerminalType();
|
||||
List<ExternalTerminalType> WINDOWS_TERMINALS = List.of(
|
||||
TABBY_WINDOWS,
|
||||
ALACRITTY_WINDOWS,
|
||||
WEZ_WINDOWS,
|
||||
TabbyTerminalType.TABBY_WINDOWS,
|
||||
AlacrittyTerminalType.ALACRITTY_WINDOWS,
|
||||
WezTerminalType.WEZTERM_WINDOWS,
|
||||
WindowsTerminalType.WINDOWS_TERMINAL_PREVIEW,
|
||||
WindowsTerminalType.WINDOWS_TERMINAL,
|
||||
CMD,
|
||||
PWSH,
|
||||
POWERSHELL);
|
||||
List<ExternalTerminalType> LINUX_TERMINALS = List.of(
|
||||
WEZ_LINUX,
|
||||
WezTerminalType.WEZTERM_LINUX,
|
||||
KONSOLE,
|
||||
XFCE,
|
||||
ELEMENTARY,
|
||||
|
@ -606,13 +577,13 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
TERMINOLOGY,
|
||||
COOL_RETRO_TERM,
|
||||
GUAKE,
|
||||
ALACRITTY_LINUX,
|
||||
AlacrittyTerminalType.ALACRITTY_LINUX,
|
||||
TILDA,
|
||||
XTERM,
|
||||
DEEPIN_TERMINAL,
|
||||
Q_TERMINAL);
|
||||
List<ExternalTerminalType> MACOS_TERMINALS =
|
||||
List.of(ITERM2, TABBY_MAC_OS, ALACRITTY_MACOS, KittyTerminalType.KITTY_MACOS, WARP, WEZ_MACOS, MACOS_TERMINAL);
|
||||
List.of(ITERM2, TabbyTerminalType.TABBY_MAC_OS, AlacrittyTerminalType.ALACRITTY_MAC_OS, KittyTerminalType.KITTY_MACOS, WARP, WezTerminalType.WEZTERM_MAC_OS, MACOS_TERMINAL);
|
||||
|
||||
@SuppressWarnings("TrivialFunctionalExpressionUsage")
|
||||
List<ExternalTerminalType> ALL = ((Supplier<List<ExternalTerminalType>>) () -> {
|
||||
|
@ -653,10 +624,14 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
|
||||
boolean supportsTabs();
|
||||
|
||||
default boolean supportsColoredTitle() {
|
||||
return true;
|
||||
default String getWebsite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isRecommended();
|
||||
|
||||
boolean supportsColoredTitle();
|
||||
|
||||
default boolean shouldClear() {
|
||||
return true;
|
||||
}
|
||||
|
@ -709,43 +684,6 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
}
|
||||
}
|
||||
|
||||
class CustomType extends ExternalApplicationType implements ExternalTerminalType {
|
||||
|
||||
public CustomType() {
|
||||
super("app.custom");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
var custom = AppPrefs.get().customTerminalCommand().getValue();
|
||||
if (custom == null || custom.isBlank()) {
|
||||
throw ErrorEvent.expected(new IllegalStateException("No custom terminal command specified"));
|
||||
}
|
||||
|
||||
var format = custom.toLowerCase(Locale.ROOT).contains("$cmd") ? custom : custom + " $CMD";
|
||||
try (var pc = LocalShell.getShell()) {
|
||||
var toExecute = ExternalApplicationHelper.replaceFileArgument(format, "CMD", configuration.getScriptFile().toString());
|
||||
// We can't be sure whether the command is blocking or not, so always make it not blocking
|
||||
if (pc.getOsType().equals(OsType.WINDOWS)) {
|
||||
toExecute = "start \"" + configuration.getCleanTitle() + "\" " + toExecute;
|
||||
} else {
|
||||
toExecute = "nohup " + toExecute + " </dev/null &>/dev/null & disown";
|
||||
}
|
||||
pc.executeSimpleCommand(toExecute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MacOsType extends ExternalApplicationType.MacApplication implements ExternalTerminalType {
|
||||
|
||||
public MacOsType(String id, String applicationName) {
|
||||
|
@ -776,4 +714,5 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
|
|||
|
||||
protected abstract CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,83 +9,32 @@ import io.xpipe.core.process.CommandBuilder;
|
|||
import io.xpipe.core.store.FilePath;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
public class KittyTerminalType {
|
||||
|
||||
public static final ExternalTerminalType KITTY_LINUX = new ExternalTerminalType() {
|
||||
public interface KittyTerminalType extends ExternalTerminalType {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "app.kitty";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
default boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
CommandSupport.isInPathOrThrow(sc, "kitty", "Kitty", null);
|
||||
CommandSupport.isInPathOrThrow(sc, "socat", "socat", null);
|
||||
}
|
||||
|
||||
var toClose = prepare();
|
||||
var socketWrite = CommandBuilder.of().add("socat", "-");
|
||||
open(configuration, socketWrite);
|
||||
if (toClose) {
|
||||
closeInitial(socketWrite);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prepare() throws Exception {
|
||||
var socket = getSocket();
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
if (sc.executeSimpleBooleanCommand("test -w " + sc.getShellDialect().fileArgument(socket))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.executeSimpleCommand(CommandBuilder.of().add("kitty").add("-o", "allow_remote_control=socket-only", "--listen-on", "unix:" + getSocket(), "--detach"));
|
||||
ThreadHelper.sleep(1500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final ExternalTerminalType KITTY_MACOS = new ExternalTerminalType.MacOsType("app.kitty", "kitty") {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
default boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
CommandSupport.isInPathOrThrow(sc, "nc", "Netcat", null);
|
||||
}
|
||||
|
||||
var toClose = prepare();
|
||||
var socketWrite = CommandBuilder.of().add("nc", "-U");
|
||||
open(configuration, socketWrite);
|
||||
if (toClose) {
|
||||
closeInitial(socketWrite);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prepare() throws Exception {
|
||||
var socket = getSocket();
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
if (sc.executeSimpleBooleanCommand("test -w " + sc.getShellDialect().fileArgument(socket))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.executeSimpleCommand(CommandBuilder.of().add("open", "-a", "kitty.app", "--args").add("-o", "allow_remote_control=socket-only", "--listen-on", "unix:" + getSocket()));
|
||||
ThreadHelper.sleep(1000);
|
||||
default boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getWebsite() {
|
||||
return "https://github.com/kovidgoyal/kitty";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final ExternalTerminalType KITTY_LINUX = new Linux();
|
||||
|
||||
public static final ExternalTerminalType KITTY_MACOS = new MacOs();
|
||||
|
||||
private static FilePath getSocket() throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
|
@ -132,4 +81,72 @@ public class KittyTerminalType {
|
|||
sc.executeSimpleCommand(CommandBuilder.of().add("echo", "-en", echoString, "|").add(socketWrite).addFile(getSocket()));
|
||||
}
|
||||
}
|
||||
|
||||
class Linux implements KittyTerminalType {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "app.kitty";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
CommandSupport.isInPathOrThrow(sc, "kitty", "Kitty", null);
|
||||
CommandSupport.isInPathOrThrow(sc, "socat", "socat", null);
|
||||
}
|
||||
|
||||
var toClose = prepare();
|
||||
var socketWrite = CommandBuilder.of().add("socat", "-");
|
||||
open(configuration, socketWrite);
|
||||
if (toClose) {
|
||||
closeInitial(socketWrite);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prepare() throws Exception {
|
||||
var socket = getSocket();
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
if (sc.executeSimpleBooleanCommand("test -w " + sc.getShellDialect().fileArgument(socket))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.executeSimpleCommand(CommandBuilder.of().add("kitty").add("-o", "allow_remote_control=socket-only", "--listen-on", "unix:" + getSocket(), "--detach"));
|
||||
ThreadHelper.sleep(1500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MacOs extends MacOsType implements KittyTerminalType {
|
||||
|
||||
public MacOs() {super("app.kitty", "kitty");}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
CommandSupport.isInPathOrThrow(sc, "nc", "Netcat", null);
|
||||
}
|
||||
|
||||
var toClose = prepare();
|
||||
var socketWrite = CommandBuilder.of().add("nc", "-U");
|
||||
open(configuration, socketWrite);
|
||||
if (toClose) {
|
||||
closeInitial(socketWrite);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean prepare() throws Exception {
|
||||
var socket = getSocket();
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
if (sc.executeSimpleBooleanCommand("test -w " + sc.getShellDialect().fileArgument(socket))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.executeSimpleCommand(CommandBuilder.of().add("open", "-a", "kitty.app", "--args").add("-o", "allow_remote_control=socket-only", "--listen-on", "unix:" + getSocket()));
|
||||
ThreadHelper.sleep(1000);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.app.util.WindowsRegistry;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellDialects;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface TabbyTerminalType extends ExternalTerminalType {
|
||||
|
||||
static class Windows extends ExternalTerminalType.WindowsType implements TabbyTerminalType {
|
||||
|
||||
public Windows() {
|
||||
super("app.tabby", "Tabby.exe");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void execute(Path file, LaunchConfiguration configuration) throws Exception {
|
||||
// Tabby has a very weird handling of output, even detaching with start does not prevent it from printing
|
||||
if (configuration.getScriptDialect().equals(ShellDialects.CMD)) {
|
||||
// It also freezes with any other input than .bat files, why?
|
||||
LocalShell.getShell().executeSimpleCommand(CommandBuilder.of()
|
||||
.addFile(file.toString())
|
||||
.add("run")
|
||||
.addFile(configuration.getScriptFile())
|
||||
.discardOutput());
|
||||
}
|
||||
|
||||
// This is probably not going to work as it does not launch a bat file
|
||||
LocalShell.getShell().executeSimpleCommand(CommandBuilder.of()
|
||||
.addFile(file.toString())
|
||||
.add("run")
|
||||
.add(configuration.getDialectLaunchCommand())
|
||||
.discardOutput());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Path> determineInstallation() {
|
||||
var perUser = WindowsRegistry.readString(WindowsRegistry.HKEY_CURRENT_USER, "SOFTWARE\\71445fac-d6ef-5436-9da7-5a323762d7f5",
|
||||
"InstallLocation").map(p -> p + "\\Tabby.exe").map(Path::of);
|
||||
if (perUser.isPresent()) {
|
||||
return perUser;
|
||||
}
|
||||
|
||||
var systemWide = WindowsRegistry.readString(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\71445fac-d6ef-5436-9da7-5a323762d7f5",
|
||||
"InstallLocation").map(p -> p + "\\Tabby.exe").map(Path::of);
|
||||
return systemWide;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExternalTerminalType TABBY_WINDOWS = new Windows();
|
||||
|
||||
ExternalTerminalType TABBY_MAC_OS = new MacOs();
|
||||
|
||||
@Override
|
||||
default String getWebsite() {
|
||||
return "https://tabby.sh";
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
class MacOs extends MacOsType implements TabbyTerminalType {
|
||||
|
||||
public MacOs() {
|
||||
super("app.tabby", "Tabby");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(CommandBuilder.of()
|
||||
.add("open", "-a")
|
||||
.addQuoted("Tabby.app")
|
||||
.add("-n", "--args", "run")
|
||||
.addFile(configuration.getScriptFile()));
|
||||
}
|
||||
}
|
||||
}
|
94
app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java
Normal file
94
app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.prefs.ExternalApplicationHelper;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.app.util.WindowsRegistry;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface WezTerminalType extends ExternalTerminalType {
|
||||
|
||||
static class Windows extends WindowsType implements WezTerminalType {
|
||||
|
||||
public Windows() {
|
||||
super("app.wezterm", "wezterm-gui");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(Path file, LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell().executeSimpleCommand(CommandBuilder.of().addFile(file.toString()).add("start").add(configuration.getDialectLaunchCommand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Path> determineInstallation() {
|
||||
Optional<String> launcherDir;
|
||||
launcherDir = WindowsRegistry.readString(
|
||||
WindowsRegistry.HKEY_LOCAL_MACHINE,
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{BCF6F0DA-5B9A-408D-8562-F680AE6E1EAF}_is1",
|
||||
"InstallLocation")
|
||||
.map(p -> p + "\\wezterm-gui.exe");
|
||||
return launcherDir.map(Path::of);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Linux extends SimplePathType implements WezTerminalType {
|
||||
|
||||
public Linux() {
|
||||
super("app.wezterm", "wezterm-gui", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
|
||||
return CommandBuilder.of().add("start").addFile(configuration.getScriptFile());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExternalTerminalType WEZTERM_WINDOWS = new Windows();
|
||||
ExternalTerminalType WEZTERM_LINUX = new Linux();
|
||||
ExternalTerminalType WEZTERM_MAC_OS = new MacOs();
|
||||
|
||||
@Override
|
||||
default String getWebsite() {
|
||||
return "https://wezfurlong.org/wezterm/index.html";
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isRecommended() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsTabs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsColoredTitle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
class MacOs extends MacOsType implements WezTerminalType {
|
||||
|
||||
public MacOs() {
|
||||
super("app.wezterm", "WezTerm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
var c = CommandBuilder.of()
|
||||
.addFile(getApplicationPath()
|
||||
.orElseThrow()
|
||||
.resolve("Contents")
|
||||
.resolve("MacOS")
|
||||
.resolve("wezterm-gui")
|
||||
.toString())
|
||||
.add("start")
|
||||
.add(configuration.getDialectLaunchCommand());
|
||||
ExternalApplicationHelper.startAsync(c);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,41 +8,70 @@ import io.xpipe.core.store.FileNames;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class WindowsTerminalType {
|
||||
public interface WindowsTerminalType extends ExternalTerminalType {
|
||||
|
||||
public static final ExternalTerminalType WINDOWS_TERMINAL =
|
||||
new ExternalTerminalType.SimplePathType("app.windowsTerminal", "wt.exe", false) {
|
||||
@Override
|
||||
default boolean isRecommended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final ExternalTerminalType WINDOWS_TERMINAL = new Standard();
|
||||
|
||||
public static final ExternalTerminalType WINDOWS_TERMINAL_PREVIEW = new Preview();
|
||||
|
||||
private static CommandBuilder toCommand(ExternalTerminalType.LaunchConfiguration configuration) throws Exception {
|
||||
// A weird behavior in Windows Terminal causes the trailing
|
||||
// backslash of a filepath to escape the closing quote in the title argument
|
||||
// So just remove that slash
|
||||
var fixedName = FileNames.removeTrailingSlash(configuration.getColoredTitle());
|
||||
|
||||
var toExec = !ShellDialects.isPowershell(LocalShell.getShell())
|
||||
? CommandBuilder.of().addFile(configuration.getScriptFile())
|
||||
: CommandBuilder.of()
|
||||
.add("powershell", "-ExecutionPolicy", "Bypass", "-File")
|
||||
.addFile(configuration.getScriptFile());
|
||||
var cmd = CommandBuilder.of().add("-w", "1", "nt");
|
||||
|
||||
if (configuration.getColor() != null) {
|
||||
cmd.add("--tabColor").addQuoted(configuration.getColor().toHexString());
|
||||
}
|
||||
return cmd.add("--title").addQuoted(fixedName).add(toExec);
|
||||
}
|
||||
|
||||
class Standard extends SimplePathType implements WindowsTerminalType {
|
||||
|
||||
public Standard() {super("app.windowsTerminal", "wt.exe", false);}
|
||||
|
||||
@Override
|
||||
public String getWebsite() {
|
||||
return "https://aka.ms/terminal-preview";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandBuilder toCommand(LaunchConfiguration configuration) throws Exception {
|
||||
return WindowsTerminalType.toCommand(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
class Preview implements WindowsTerminalType {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
public String getWebsite() {
|
||||
return "https://aka.ms/terminal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public static final ExternalTerminalType WINDOWS_TERMINAL_PREVIEW = new ExternalTerminalType() {
|
||||
|
||||
@Override
|
||||
public boolean supportsTabs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsColoredTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(ExternalTerminalType.LaunchConfiguration configuration) throws Exception {
|
||||
public void launch(LaunchConfiguration configuration) throws Exception {
|
||||
LocalShell.getShell()
|
||||
.executeSimpleCommand(
|
||||
CommandBuilder.of().addFile(getPath().toString()).add(toCommand(configuration)));
|
||||
|
@ -63,24 +92,5 @@ public class WindowsTerminalType {
|
|||
public String getId() {
|
||||
return "app.windowsTerminalPreview";
|
||||
}
|
||||
};
|
||||
|
||||
private static CommandBuilder toCommand(ExternalTerminalType.LaunchConfiguration configuration) throws Exception {
|
||||
// A weird behavior in Windows Terminal causes the trailing
|
||||
// backslash of a filepath to escape the closing quote in the title argument
|
||||
// So just remove that slash
|
||||
var fixedName = FileNames.removeTrailingSlash(configuration.getColoredTitle());
|
||||
|
||||
var toExec = !ShellDialects.isPowershell(LocalShell.getShell())
|
||||
? CommandBuilder.of().addFile(configuration.getScriptFile())
|
||||
: CommandBuilder.of()
|
||||
.add("powershell", "-ExecutionPolicy", "Bypass", "-File")
|
||||
.addFile(configuration.getScriptFile());
|
||||
var cmd = CommandBuilder.of().add("-w", "1", "nt");
|
||||
|
||||
if (configuration.getColor() != null) {
|
||||
cmd.add("--tabColor").addQuoted(configuration.getColor().toHexString());
|
||||
}
|
||||
return cmd.add("--title").addQuoted(fixedName).add(toExec);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue