Determine multiplexer automatically

This commit is contained in:
crschnick
2026-04-16 21:44:00 +00:00
parent 7be3a3712a
commit 24203a1005
7 changed files with 62 additions and 15 deletions
@@ -6,12 +6,10 @@ import io.xpipe.app.comp.base.ScrollComp;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.app.platform.PlatformState;
import io.xpipe.app.prefs.EditorCategory;
import io.xpipe.app.prefs.PasswordManagerCategory;
import io.xpipe.app.prefs.PersonalizationCategory;
import io.xpipe.app.prefs.TerminalCategory;
import io.xpipe.app.prefs.*;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.core.OsType;
import javafx.application.Platform;
import javafx.scene.layout.Region;
@@ -32,14 +30,20 @@ public class AppConfigurationDialog {
var options = new OptionsBuilder()
.sub(PersonalizationCategory.languageChoice())
.sub(PersonalizationCategory.themeChoice())
.sub(TerminalCategory.terminalChoice(false))
.sub(TerminalCategory.terminalChoice(false));
if (OsType.ofLocal() != OsType.WINDOWS && AppPrefs.get().terminalMultiplexer().getValue() != null) {
options.sub(TerminalCategory.terminalMultiplexerChoice());
}
var optionsComp = options
.sub(EditorCategory.editorChoice())
.sub(PasswordManagerCategory.passwordManagerChoice())
.buildComp();
options.style("initial-setup");
options.style("prefs-container");
optionsComp.style("initial-setup");
optionsComp.style("prefs-container");
var scroll = new ScrollComp(options);
var scroll = new ScrollComp(optionsComp);
scroll.apply(struc -> {
struc.prefHeightProperty().bind(((Region) struc.getContent()).heightProperty());
});
@@ -849,6 +849,7 @@ public final class AppPrefs {
spiceClient.setValue(ExternalSpiceClient.determineDefault(spiceClient.getValue()));
vncClient.setValue(ExternalVncClient.determineDefault(vncClient.getValue()));
passwordManager.setValue(PasswordManager.determineDefault(passwordManager.getValue()));
terminalMultiplexer.setValue(TerminalMultiplexer.determineDefault(terminalMultiplexer.getValue()));
PrefsProvider.getAll().forEach(prov -> prov.initDefaultValues());
}
@@ -168,7 +168,7 @@ public class TerminalCategory extends AppPrefsCategory {
.sub(terminalChoice(true))
.sub(terminalPrompt())
.sub(terminalProxy())
.sub(terminalMultiplexer())
.sub(terminalMultiplexerChoice())
// .sub(terminalInitScript())
.title("sessionLogging")
.sub(new OptionsBuilder()
@@ -281,7 +281,7 @@ public class TerminalCategory extends AppPrefsCategory {
prefs.terminalInitScript);
}
private OptionsBuilder terminalMultiplexer() {
public static OptionsBuilder terminalMultiplexerChoice() {
var prefs = AppPrefs.get();
var choiceBuilder = OptionsChoiceBuilder.builder()
.property(prefs.terminalMultiplexer)
@@ -310,7 +310,7 @@ public class TerminalCategory extends AppPrefsCategory {
})
.build();
var choice = choiceBuilder.build().buildComp();
choice.maxWidth(getCompWidth());
choice.maxWidth(600);
var options = new OptionsBuilder()
.name("terminalMultiplexer")
.description(
@@ -1,9 +1,6 @@
package io.xpipe.app.terminal;
import io.xpipe.app.process.CommandSupport;
import io.xpipe.app.process.ScriptHelper;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellScript;
import io.xpipe.app.process.*;
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.Builder;
@@ -26,6 +23,11 @@ public class ScreenTerminalMultiplexer implements TerminalMultiplexer {
return "https://www.gnu.org/software/screen/manual/screen.html";
}
@Override
public boolean shouldSelect() throws Exception {
return false;
}
@Override
public void checkSupported(ShellControl sc) throws Exception {
CommandSupport.isInPathOrThrow(sc, "screen");
@@ -1,9 +1,13 @@
package io.xpipe.app.terminal;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellScript;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.xpipe.core.OsType;
import java.util.ArrayList;
import java.util.List;
@@ -19,10 +23,35 @@ public interface TerminalMultiplexer {
return l;
}
static TerminalMultiplexer determineDefault(TerminalMultiplexer existing) {
if (OsType.ofLocal() == OsType.WINDOWS) {
return existing;
}
try {
if (existing != null && existing.shouldSelect()) {
return existing;
}
var all = List.of(new TmuxTerminalMultiplexer(), new ZellijTerminalMultiplexer(), new ScreenTerminalMultiplexer());
for (TerminalMultiplexer terminalMultiplexer : all) {
if (terminalMultiplexer.shouldSelect()) {
return terminalMultiplexer;
}
}
} catch (Exception e) {
ErrorEventFactory.fromThrowable(e).handle();
}
return null;
}
boolean supportsSplitView();
String getDocsLink();
boolean shouldSelect() throws Exception;
void checkSupported(ShellControl sc) throws Exception;
ShellScript launchForExistingSession(ShellControl control, TerminalLaunchConfiguration config);
@@ -2,6 +2,7 @@ package io.xpipe.app.terminal;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.process.CommandSupport;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellScript;
@@ -27,6 +28,11 @@ public class TmuxTerminalMultiplexer implements TerminalMultiplexer {
return "https://github.com/tmux/tmux/wiki/Getting-Started";
}
@Override
public boolean shouldSelect() throws Exception {
return LocalShell.getShell().view().findProgram("tmux").isPresent();
}
@Override
public void checkSupported(ShellControl sc) throws Exception {
CommandSupport.isInPathOrThrow(sc, "tmux");
@@ -29,6 +29,11 @@ public class ZellijTerminalMultiplexer implements TerminalMultiplexer {
return "https://zellij.dev/";
}
@Override
public boolean shouldSelect() throws Exception {
return LocalShell.getShell().view().findProgram("zellij").isPresent();
}
@Override
public void checkSupported(ShellControl sc) throws Exception {
CommandSupport.isInPathOrThrow(sc, "zellij");