Small shell changes and move some comps to extension module

This commit is contained in:
Christopher Schnick 2022-12-03 15:39:11 +01:00
parent 0d65db95f9
commit 40df1a3233
11 changed files with 245 additions and 17 deletions

View file

@ -125,6 +125,17 @@ public class BeaconClient implements AutoCloseable {
var command = control.command("xpipe beacon --raw").start();
command.discardErr();
return new BeaconClient(command, command.getStdout(), command.getStdin()) {
// {
// new Thread(() -> {
// while (true) {
// if (!control.isRunning()) {
// close();
// }
// }
// })
// }
@Override
public <T extends ResponseMessage> T receiveResponse()
throws ConnectorException, ClientException, ServerException {

View file

@ -5,15 +5,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.stream.Collectors;
public interface ProcessControl extends Closeable, AutoCloseable {
static String join(List<String> command) {
return command.stream().map(s -> s.contains(" ") ? "\"" + s + "\"" : s).collect(Collectors.joining(" "));
}
void closeStdin() throws IOException;
boolean isStdinClosed();

View file

@ -71,18 +71,17 @@ public interface ShellProcessControl extends ProcessControl {
ShellProcessControl start() throws Exception;
default CommandProcessControl commandListFunction(Function<ShellProcessControl, List<String>> command) {
return commandFunction(shellProcessControl -> command.apply(shellProcessControl).stream()
.map(s -> s.contains(" ") ? "\"" + s + "\"" : s)
.collect(Collectors.joining(" ")));
return commandFunction(shellProcessControl -> shellProcessControl.getShellType().flatten(command.apply(shellProcessControl)));
}
CommandProcessControl commandFunction(Function<ShellProcessControl, String> command);
CommandProcessControl command(String command);
default CommandProcessControl command(String command){
return commandFunction(shellProcessControl -> command);
}
default CommandProcessControl command(List<String> command) {
return command(
command.stream().map(s -> s.contains(" ") ? "\"" + s + "\"" : s).collect(Collectors.joining(" ")));
return commandFunction(shellProcessControl -> shellProcessControl.getShellType().flatten(command));
}
void exitAndWait() throws IOException;

View file

@ -5,10 +5,16 @@ import io.xpipe.core.charsetter.NewLine;
import java.nio.charset.Charset;
import java.util.List;
import java.util.stream.Collectors;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public interface ShellType {
default String flatten(List<String> command) {
return command.stream().map(s -> s.contains(" ") ? "\"" + s + "\"" : s).collect(Collectors.joining(" "));
}
default String joinCommands(String... s) {
return String.join(getConcatenationOperator(), s);
}

View file

@ -4,8 +4,11 @@ import io.xpipe.core.impl.FileNames;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.CommandProcessControl;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ProcessOutputException;
import io.xpipe.core.process.ShellProcessControl;
import java.util.List;
public class XPipeInstallation {
public static String getInstallationBasePathForCLI(ShellProcessControl p, String cliExecutable) throws Exception {
@ -22,8 +25,10 @@ public class XPipeInstallation {
}
public static String queryInstallationVersion(ShellProcessControl p, String exec) throws Exception {
try (CommandProcessControl c = p.command(exec + " version").start()) {
try (CommandProcessControl c = p.command(List.of(exec, "version")).start()) {
return c.readOrThrow();
} catch (ProcessOutputException ex) {
return "?";
}
}
@ -34,7 +39,7 @@ public class XPipeInstallation {
return false;
}
try (CommandProcessControl c = p.command(executable + " version").start()) {
try (CommandProcessControl c = p.command(List.of(executable, "version")).start()) {
return c.readOrThrow().equals(version);
}
}

View file

@ -28,6 +28,25 @@ public abstract class EventHandler {
}
};
public static final EventHandler OMIT = new EventHandler() {
@Override
public List<TrackEvent> snapshotEvents() {
return List.of();
}
@Override
public void handle(TrackEvent te) {
}
@Override
public void handle(ErrorEvent ee) {
}
};
public static void set(EventHandler handler) {
INSTANCE = handler;
}
private static EventHandler INSTANCE;
private static void init() {

View file

@ -0,0 +1,77 @@
package io.xpipe.extension.fxcomps.impl;
import io.xpipe.core.impl.FileStore;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.MachineStore;
import io.xpipe.extension.I18n;
import io.xpipe.extension.fxcomps.SimpleComp;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.stage.FileChooser;
import java.io.File;
import java.util.List;
public class FileStoreChoiceComp extends SimpleComp {
private final List<MachineStore> availableFileSystems;
private final Property<FileStore> selected;
public FileStoreChoiceComp(List<MachineStore> availableFileSystems, Property<FileStore> selected) {
this.availableFileSystems = availableFileSystems;
this.selected = selected;
}
private void setSelected(FileSystemStore fileSystemStore, String file) {
selected.setValue(fileSystemStore != null && file != null ? new FileStore(fileSystemStore, file) : null);
}
@Override
protected Region createSimple() {
var fileProperty = new SimpleStringProperty(
selected.getValue() != null ? selected.getValue().getFile() : null);
var fileSystemProperty = new SimpleObjectProperty<>(
selected.getValue() != null ? selected.getValue().getFileSystem() : availableFileSystems.get(0));
fileProperty.addListener((observable, oldValue, newValue) -> {
setSelected(fileSystemProperty.get(), fileProperty.get());
});
fileSystemProperty.addListener((observable, oldValue, newValue) -> {
setSelected(fileSystemProperty.get(), fileProperty.get());
});
var fileSystemChoiceComp = new FileSystemStoreChoiceComp(fileSystemProperty);
if (availableFileSystems.size() == 1) {
fileSystemChoiceComp.hide(new SimpleBooleanProperty(true));
}
var fileNameComp = new TextFieldComp(fileProperty).apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS));
var fileBrowseButton = new IconButtonComp("mdi2f-folder-open-outline", () -> {
if (fileSystemProperty.get() != null && fileSystemProperty.get() instanceof LocalStore) {
var fileChooser = createChooser();
File file = fileChooser.showOpenDialog(null);
if (file != null && file.exists()) {
fileProperty.setValue(file.toString());
}
}
})
.hide(fileSystemProperty.isNotEqualTo(new LocalStore()));
var layout = new HorizontalComp(List.of(fileSystemChoiceComp, fileNameComp, fileBrowseButton));
return layout.createRegion();
}
private FileChooser createChooser() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(I18n.get("browseFileTitle"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(I18n.get("anyFile"), "*"));
return fileChooser;
}
}

View file

@ -0,0 +1,53 @@
package io.xpipe.extension.fxcomps.impl;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.extension.DataStoreProviders;
import io.xpipe.extension.I18n;
import io.xpipe.extension.fxcomps.SimpleComp;
import io.xpipe.extension.util.CustomComboBoxBuilder;
import io.xpipe.extension.util.XPipeDaemon;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Node;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.Region;
public class FileSystemStoreChoiceComp extends SimpleComp {
private final Property<FileSystemStore> selected;
public FileSystemStoreChoiceComp(Property<FileSystemStore> selected) {
this.selected = selected;
}
private static String getName(FileSystemStore store) {
var name = XPipeDaemon.getInstance().getNamedStores().stream()
.filter(e -> e.equals(store))
.findAny()
.map(e -> XPipeDaemon.getInstance().getStoreName(e).orElse("?"))
.orElse(I18n.get("localMachine"));
return name;
}
private Region createGraphic(FileSystemStore s) {
var provider = DataStoreProviders.byStore(s);
var img = new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName()), 16, 16);
return new Label(getName(s), img.createRegion());
}
@Override
protected Region createSimple() {
var comboBox = new CustomComboBoxBuilder<>(selected, this::createGraphic, null, v -> true);
comboBox.addFilter((v, s) -> getName(v).toLowerCase().contains(s));
comboBox.add(new LocalStore());
XPipeDaemon.getInstance().getNamedStores().stream()
.filter(e -> e instanceof FileSystemStore)
.map(e -> (FileSystemStore) e)
.forEach(comboBox::add);
ComboBox<Node> cb = comboBox.build();
cb.getStyleClass().add("choice-comp");
return cb;
}
}

View file

@ -0,0 +1,54 @@
package io.xpipe.extension.fxcomps.impl;
import com.jfoenix.controls.JFXButton;
import io.xpipe.extension.fxcomps.Comp;
import io.xpipe.extension.fxcomps.CompStructure;
import io.xpipe.extension.fxcomps.SimpleCompStructure;
import io.xpipe.extension.fxcomps.util.PlatformThread;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.css.Size;
import javafx.css.SizeUnits;
import org.kordamp.ikonli.javafx.FontIcon;
public class IconButtonComp extends Comp<CompStructure<JFXButton>> {
private final ObservableValue<String> icon;
private final Runnable listener;
public IconButtonComp(String defaultVal) {
this(new SimpleObjectProperty<>(defaultVal), null);
}
public IconButtonComp(String defaultVal, Runnable listener) {
this(new SimpleObjectProperty<>(defaultVal), listener);
}
public IconButtonComp(ObservableValue<String> icon, Runnable listener) {
this.icon = PlatformThread.sync(icon);
this.listener = listener;
}
@Override
public CompStructure<JFXButton> createBase() {
var button = new JFXButton();
var fi = new FontIcon(icon.getValue());
icon.addListener((c, o, n) -> {
fi.setIconLiteral(n);
});
fi.setIconSize((int) new Size(fi.getFont().getSize(), SizeUnits.PT).pixels());
button.fontProperty().addListener((c, o, n) -> {
fi.setIconSize((int) new Size(n.getSize(), SizeUnits.PT).pixels());
});
fi.iconColorProperty().bind(button.textFillProperty());
button.setGraphic(fi);
button.setOnAction(e -> {
if (listener != null) {
listener.run();
}
});
button.getStyleClass().add("icon-button-comp");
return new SimpleCompStructure<>(button);
}
}

View file

@ -15,7 +15,7 @@ public class DaemonExtensionTest extends ExtensionTest {
}
public static DataSource getSource(String type, String file) {
return DataSource.create(null, type, getResource(file));
return DataSource.create(null, type, getResourceStore(file));
}
public static DataSource getSource(io.xpipe.core.source.DataSource<?> source) {

View file

@ -9,8 +9,18 @@ import java.nio.file.Path;
public class ExtensionTest {
@SneakyThrows
public static DataStore getResource(String name) {
var url = DaemonExtensionTest.class.getClassLoader().getResource(name);
public static Path getResourcePath(Class<?> c, String name) {
var url = c.getResource(name);
if (url == null) {
throw new IllegalArgumentException(String.format("File %s does not exist", name));
}
var file = Path.of(url.toURI());
return file;
}
@SneakyThrows
public static DataStore getResourceStore(String name) {
var url = ExtensionTest.class.getClassLoader().getResource(name);
if (url == null) {
throw new IllegalArgumentException(String.format("File %s does not exist", name));
}