mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-04 03:31:08 +12:00
Migrate all actions, fix various bugs
This commit is contained in:
parent
a712c75fc8
commit
3f9f552078
36 changed files with 412 additions and 261 deletions
|
@ -171,13 +171,18 @@ public class StoreEntryComp extends SimpleComp {
|
||||||
var button = new IconButtonComp(
|
var button = new IconButtonComp(
|
||||||
actionProvider.getIcon(entry.getEntry().getStore().asNeeded()), () -> {
|
actionProvider.getIcon(entry.getEntry().getStore().asNeeded()), () -> {
|
||||||
ThreadHelper.runFailableAsync(() -> {
|
ThreadHelper.runFailableAsync(() -> {
|
||||||
var action = actionProvider.createAction(entry.getEntry().getStore().asNeeded());
|
var action = actionProvider.createAction(
|
||||||
|
entry.getEntry().getStore().asNeeded());
|
||||||
action.execute();
|
action.execute();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
button.apply(new FancyTooltipAugment<>(
|
button.apply(new FancyTooltipAugment<>(
|
||||||
actionProvider.getName(entry.getEntry().getStore().asNeeded())));
|
actionProvider.getName(entry.getEntry().getStore().asNeeded())));
|
||||||
|
if (!actionProvider.showIfDisabled()) {
|
||||||
|
button.hide(Bindings.not(p.getValue()));
|
||||||
|
} else {
|
||||||
button.disable(Bindings.not(p.getValue()));
|
button.disable(Bindings.not(p.getValue()));
|
||||||
|
}
|
||||||
list.add(button);
|
list.add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +232,8 @@ public class StoreEntryComp extends SimpleComp {
|
||||||
var item = new MenuItem(null, new FontIcon(icon));
|
var item = new MenuItem(null, new FontIcon(icon));
|
||||||
item.setOnAction(event -> {
|
item.setOnAction(event -> {
|
||||||
ThreadHelper.runFailableAsync(() -> {
|
ThreadHelper.runFailableAsync(() -> {
|
||||||
var action = actionProvider.createAction(entry.getEntry().getStore().asNeeded());
|
var action = actionProvider.createAction(
|
||||||
|
entry.getEntry().getStore().asNeeded());
|
||||||
action.execute();
|
action.execute();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -245,7 +251,8 @@ public class StoreEntryComp extends SimpleComp {
|
||||||
|
|
||||||
if (AppPrefs.get().developerMode().getValue()) {
|
if (AppPrefs.get().developerMode().getValue()) {
|
||||||
var browse = new MenuItem(I18n.get("browse"), new FontIcon("mdi2f-folder-open-outline"));
|
var browse = new MenuItem(I18n.get("browse"), new FontIcon("mdi2f-folder-open-outline"));
|
||||||
browse.setOnAction(event -> DesktopHelper.browsePath(entry.getEntry().getDirectory()));
|
browse.setOnAction(
|
||||||
|
event -> DesktopHelper.browsePath(entry.getEntry().getDirectory()));
|
||||||
contextMenu.getItems().add(browse);
|
contextMenu.getItems().add(browse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ public class DataStateProviderImpl extends DataStateProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putState(DataStore store, String key, Object value) {
|
public void putState(DataStore store, String key, Object value) {
|
||||||
|
if (DataStorage.get() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var entry = DataStorage.get().getEntryByStore(store);
|
var entry = DataStorage.get().getEntryByStore(store);
|
||||||
if (entry.isEmpty()) {
|
if (entry.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -22,6 +26,10 @@ public class DataStateProviderImpl extends DataStateProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T getState(DataStore store, String key, Class<T> c, Supplier<T> def) {
|
public <T> T getState(DataStore store, String key, Class<T> c, Supplier<T> def) {
|
||||||
|
if (DataStorage.get() == null) {
|
||||||
|
return def.get();
|
||||||
|
}
|
||||||
|
|
||||||
var entry = DataStorage.get().getEntryByStore(store);
|
var entry = DataStorage.get().getEntryByStore(store);
|
||||||
if (entry.isEmpty()) {
|
if (entry.isEmpty()) {
|
||||||
return def.get();
|
return def.get();
|
||||||
|
|
|
@ -74,10 +74,6 @@ public abstract class DataStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataStorage get() {
|
public static DataStorage get() {
|
||||||
if (INSTANCE == null) {
|
|
||||||
throw new IllegalStateException("Not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +171,10 @@ public abstract class DataStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<DataSourceCollection> getCollectionForName(String name) {
|
public Optional<DataSourceCollection> getCollectionForName(String name) {
|
||||||
|
if (name == null) {
|
||||||
|
return Optional.ofNullable(getInternalCollection());
|
||||||
|
}
|
||||||
|
|
||||||
return sourceCollections.stream()
|
return sourceCollections.stream()
|
||||||
.filter(c -> name.equalsIgnoreCase(c.getName()))
|
.filter(c -> name.equalsIgnoreCase(c.getName()))
|
||||||
.findAny();
|
.findAny();
|
||||||
|
|
|
@ -13,7 +13,7 @@ public abstract class TerminalProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ModuleLayer layer) {
|
public void init(ModuleLayer layer) {
|
||||||
ServiceLoader.load(layer, TerminalProvider.class).findFirst().orElseThrow();
|
INSTANCE = ServiceLoader.load(layer, TerminalProvider.class).findFirst().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,12 +7,14 @@ import io.xpipe.app.exchange.cli.*;
|
||||||
import io.xpipe.app.issue.EventHandlerImpl;
|
import io.xpipe.app.issue.EventHandlerImpl;
|
||||||
import io.xpipe.app.storage.DataStateProviderImpl;
|
import io.xpipe.app.storage.DataStateProviderImpl;
|
||||||
import io.xpipe.app.util.ProxyManagerProviderImpl;
|
import io.xpipe.app.util.ProxyManagerProviderImpl;
|
||||||
|
import io.xpipe.app.util.TerminalProvider;
|
||||||
import io.xpipe.app.util.XPipeDaemonProvider;
|
import io.xpipe.app.util.XPipeDaemonProvider;
|
||||||
import io.xpipe.core.util.DataStateProvider;
|
import io.xpipe.core.util.DataStateProvider;
|
||||||
import io.xpipe.core.util.ProxyManagerProvider;
|
import io.xpipe.core.util.ProxyManagerProvider;
|
||||||
import io.xpipe.extension.Cache;
|
import io.xpipe.extension.Cache;
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
import io.xpipe.extension.event.EventHandler;
|
import io.xpipe.extension.event.EventHandler;
|
||||||
|
import io.xpipe.extension.util.ModuleLayerLoader;
|
||||||
import io.xpipe.extension.util.XPipeDaemon;
|
import io.xpipe.extension.util.XPipeDaemon;
|
||||||
import org.slf4j.spi.SLF4JServiceProvider;
|
import org.slf4j.spi.SLF4JServiceProvider;
|
||||||
|
|
||||||
|
@ -99,6 +101,7 @@ open module io.xpipe.app {
|
||||||
uses MessageExchangeImpl;
|
uses MessageExchangeImpl;
|
||||||
uses io.xpipe.app.util.TerminalProvider;
|
uses io.xpipe.app.util.TerminalProvider;
|
||||||
|
|
||||||
|
provides ModuleLayerLoader with TerminalProvider.Loader;
|
||||||
provides DataStateProvider with
|
provides DataStateProvider with
|
||||||
DataStateProviderImpl;
|
DataStateProviderImpl;
|
||||||
provides ProxyManagerProvider with
|
provides ProxyManagerProvider with
|
||||||
|
|
|
@ -41,7 +41,7 @@ public interface OsType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTempDirectory(ShellProcessControl pc) throws Exception {
|
public String getTempDirectory(ShellProcessControl pc) throws Exception {
|
||||||
return pc.executeStringSimpleCommand(ShellTypes.CMD, ShellTypes.CMD.getPrintVariableCommand("TEMP"));
|
return pc.executeStringSimpleCommand(pc.getShellType().getPrintEnvironmentVariableCommand("TEMP"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,7 +52,7 @@ public interface OsType {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getProperties(ShellProcessControl pc) throws Exception {
|
public Map<String, String> getProperties(ShellProcessControl pc) throws Exception {
|
||||||
try (CommandProcessControl c =
|
try (CommandProcessControl c =
|
||||||
pc.subShell(ShellTypes.CMD).command("systeminfo").start()) {
|
pc.command("systeminfo").start()) {
|
||||||
var text = c.readOrThrow();
|
var text = c.readOrThrow();
|
||||||
return PropertiesFormatsParser.parse(text, ":");
|
return PropertiesFormatsParser.parse(text, ":");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package io.xpipe.core.process;
|
package io.xpipe.core.process;
|
||||||
|
|
||||||
|
import io.xpipe.core.util.FailableBiFunction;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public abstract class ProcessControlProvider {
|
public abstract class ProcessControlProvider {
|
||||||
|
|
||||||
|
@ -18,21 +18,22 @@ public abstract class ProcessControlProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShellProcessControl createLocal() {
|
public static ShellProcessControl createLocal() {
|
||||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).findFirst().orElseThrow();
|
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).filter(
|
||||||
|
Objects::nonNull).findFirst().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShellProcessControl createSub(
|
public static ShellProcessControl createSub(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> commandFunction,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> commandFunction,
|
||||||
BiFunction<ShellProcessControl, String, String> terminalCommand) {
|
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand) {
|
||||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.sub(parent, commandFunction, terminalCommand)).filter(
|
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.sub(parent, commandFunction, terminalCommand)).filter(
|
||||||
Objects::nonNull).findFirst().orElseThrow();
|
Objects::nonNull).findFirst().orElseThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandProcessControl createCommand(
|
public static CommandProcessControl createCommand(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
Function<ShellProcessControl, String> terminalCommand) {
|
FailableFunction<ShellProcessControl, String, Exception> terminalCommand) {
|
||||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.command(parent, command, terminalCommand)).filter(
|
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.command(parent, command, terminalCommand)).filter(
|
||||||
Objects::nonNull).findFirst().orElseThrow();
|
Objects::nonNull).findFirst().orElseThrow();
|
||||||
}
|
}
|
||||||
|
@ -44,13 +45,13 @@ public abstract class ProcessControlProvider {
|
||||||
|
|
||||||
public abstract ShellProcessControl sub(
|
public abstract ShellProcessControl sub(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> commandFunction,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> commandFunction,
|
||||||
BiFunction<ShellProcessControl, String, String> terminalCommand);
|
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand);
|
||||||
|
|
||||||
public abstract CommandProcessControl command(
|
public abstract CommandProcessControl command(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
Function<ShellProcessControl, String> terminalCommand);
|
FailableFunction<ShellProcessControl, String, Exception> terminalCommand);
|
||||||
|
|
||||||
public abstract ShellProcessControl createLocalProcessControl();
|
public abstract ShellProcessControl createLocalProcessControl();
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package io.xpipe.core.process;
|
package io.xpipe.core.process;
|
||||||
|
|
||||||
|
import io.xpipe.core.util.FailableBiFunction;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import io.xpipe.core.util.SecretValue;
|
import io.xpipe.core.util.SecretValue;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public interface ShellProcessControl extends ProcessControl {
|
public interface ShellProcessControl extends ProcessControl {
|
||||||
|
@ -87,18 +87,18 @@ public interface ShellProcessControl extends ProcessControl {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellProcessControl subShell(
|
ShellProcessControl subShell(
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
BiFunction<ShellProcessControl, String, String> terminalCommand);
|
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand);
|
||||||
|
|
||||||
void executeLine(String command) throws Exception;
|
void executeLine(String command) throws Exception;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ShellProcessControl start() throws Exception;
|
ShellProcessControl start() throws Exception;
|
||||||
|
|
||||||
CommandProcessControl command(Function<ShellProcessControl, String> command);
|
CommandProcessControl command(FailableFunction<ShellProcessControl, String, Exception> command);
|
||||||
|
|
||||||
CommandProcessControl command(
|
CommandProcessControl command(
|
||||||
Function<ShellProcessControl, String> command, Function<ShellProcessControl, String> terminalCommand);
|
FailableFunction<ShellProcessControl, String, Exception> command, FailableFunction<ShellProcessControl, String, Exception> terminalCommand);
|
||||||
|
|
||||||
default CommandProcessControl command(String command) {
|
default CommandProcessControl command(String command) {
|
||||||
return command(shellProcessControl -> command);
|
return command(shellProcessControl -> command);
|
||||||
|
|
|
@ -60,11 +60,9 @@ public interface ShellType {
|
||||||
String getEchoCommand(String s, boolean toErrorStream);
|
String getEchoCommand(String s, boolean toErrorStream);
|
||||||
|
|
||||||
|
|
||||||
default String getPrintVariableCommand(String name) {
|
String getPrintVariableCommand(String name);
|
||||||
return getPrintVariableCommand("", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
String getPrintVariableCommand(String prefix, String name);
|
String getPrintExitCodeCommand(String prefix);
|
||||||
|
|
||||||
default String getPrintEnvironmentVariableCommand(String name) {
|
default String getPrintEnvironmentVariableCommand(String name) {
|
||||||
return getPrintVariableCommand(name);
|
return getPrintVariableCommand(name);
|
||||||
|
|
|
@ -59,12 +59,17 @@ public class ShellTypes {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSetEnvironmentVariableCommand(String variableName, String value) {
|
public String getSetEnvironmentVariableCommand(String variableName, String value) {
|
||||||
return ("set \"" + variableName + "=" + value.replaceAll("\"", "^$0") + "\"");
|
return ("set \"" + variableName + "=" + value.replaceAll("[&^|<>\"]", "^$0") + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrintVariableCommand(String prefix, String name) {
|
public String getPrintExitCodeCommand(String prefix) {
|
||||||
return "call echo " + prefix + "^%" + name + "^%";
|
return "call echo " + prefix + "^%" + getExitCodeVariable() + "^%";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrintVariableCommand(String name) {
|
||||||
|
return "call echo ^%" + name + "^%";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -276,8 +281,13 @@ public class ShellTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrintVariableCommand(String prefix, String name) {
|
public String getPrintExitCodeCommand(String prefix) {
|
||||||
return "echo \"" + escapeStringValue(prefix) + "$" + escapeStringValue(name) + "\"";
|
return "echo \"" + prefix + "$(If ($?) {0} Else {1})\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrintVariableCommand(String name) {
|
||||||
|
return "echo \"" + "$" + escapeStringValue(name) + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,7 +438,7 @@ public class ShellTypes {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> executeCommandListWithShell(List<String> cmd) {
|
public List<String> executeCommandListWithShell(List<String> cmd) {
|
||||||
return List.of(getExecutable(), "-c", flatten(cmd));
|
return List.of(getName(), "-c", flatten(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -448,7 +458,7 @@ public class ShellTypes {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> executeCommandListWithShell(String cmd) {
|
public List<String> executeCommandListWithShell(String cmd) {
|
||||||
return List.of(getExecutable(), "-c", cmd);
|
return List.of(getName(), "-c", cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getScriptEchoCommand(String s) {
|
public String getScriptEchoCommand(String s) {
|
||||||
|
@ -494,12 +504,17 @@ public class ShellTypes {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String prepareScriptContent(String content) {
|
public String prepareScriptContent(String content) {
|
||||||
return content;
|
return "#!" + getExecutable() + "\n" + content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrintVariableCommand(String prefix, String name) {
|
public String getPrintExitCodeCommand(String prefix) {
|
||||||
return "echo " + prefix + "$" + name;
|
return "echo " + prefix + "$" + getExitCodeVariable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrintVariableCommand(String name) {
|
||||||
|
return "echo \"$" + name + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package io.xpipe.core.util;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableBiFunction<T1, T2, R, E extends Throwable> {
|
||||||
|
|
||||||
|
R apply(T1 var1, T2 var2) throws E;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package io.xpipe.core.util;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableFunction<T, R, E extends Throwable> {
|
||||||
|
|
||||||
|
R apply(T var1) throws E;
|
||||||
|
}
|
|
@ -2,15 +2,41 @@ package io.xpipe.ext.base.actions;
|
||||||
|
|
||||||
import io.xpipe.core.impl.FileStore;
|
import io.xpipe.core.impl.FileStore;
|
||||||
import io.xpipe.core.impl.LocalStore;
|
import io.xpipe.core.impl.LocalStore;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
import io.xpipe.extension.util.DesktopHelper;
|
import io.xpipe.extension.util.DesktopHelper;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class FileBrowseAction implements DataStoreActionProvider<FileStore> {
|
public class FileBrowseAction implements ActionProvider {
|
||||||
|
|
||||||
|
@Value
|
||||||
|
static class Action implements ActionProvider.Action {
|
||||||
|
|
||||||
|
FileStore store;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresPlatform() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
DesktopHelper.browseFileInDirectory(Path.of(store.getFile()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||||
|
return new DataStoreCallSite<FileStore>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionProvider.Action createAction(FileStore store) {
|
||||||
|
return new Action(store);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<FileStore> getApplicableClass() {
|
public Class<FileStore> getApplicableClass() {
|
||||||
|
@ -31,9 +57,6 @@ public class FileBrowseAction implements DataStoreActionProvider<FileStore> {
|
||||||
public String getIcon(FileStore store) {
|
public String getIcon(FileStore store) {
|
||||||
return "mdi2f-folder-open-outline";
|
return "mdi2f-folder-open-outline";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public void execute(FileStore store) throws Exception {
|
|
||||||
DesktopHelper.browseFileInDirectory(Path.of(store.getFile()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,42 @@ import io.xpipe.app.util.ExternalEditor;
|
||||||
import io.xpipe.core.impl.FileStore;
|
import io.xpipe.core.impl.FileStore;
|
||||||
import io.xpipe.core.impl.LocalStore;
|
import io.xpipe.core.impl.LocalStore;
|
||||||
import io.xpipe.core.store.DataFlow;
|
import io.xpipe.core.store.DataFlow;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
public class FileEditAction implements DataStoreActionProvider<FileStore> {
|
public class FileEditAction implements ActionProvider {
|
||||||
|
|
||||||
|
@Value
|
||||||
|
static class Action implements ActionProvider.Action {
|
||||||
|
|
||||||
|
FileStore store;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresPlatform() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
if (store.getFileSystem().equals(new LocalStore())) {
|
||||||
|
ExternalEditor.get().openInEditor(store.getFile());
|
||||||
|
} else {
|
||||||
|
ExternalEditor.get()
|
||||||
|
.startEditing(store.getFileName(), store.getFileExtension(), store, () -> store.openInput(), () -> store.openOutput());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||||
|
return new DataStoreCallSite<FileStore>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionProvider.Action createAction(FileStore store) {
|
||||||
|
return new Action(store);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<FileStore> getApplicableClass() {
|
public Class<FileStore> getApplicableClass() {
|
||||||
|
@ -29,14 +60,6 @@ public class FileEditAction implements DataStoreActionProvider<FileStore> {
|
||||||
public String getIcon(FileStore store) {
|
public String getIcon(FileStore store) {
|
||||||
return "mdal-edit";
|
return "mdal-edit";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public void execute(FileStore store) throws Exception {
|
|
||||||
if (store.getFileSystem().equals(new LocalStore())) {
|
|
||||||
ExternalEditor.get().openInEditor(store.getFile());
|
|
||||||
} else {
|
|
||||||
ExternalEditor.get()
|
|
||||||
.startEditing(store.getFileName(), store.getFileExtension(), store, () -> store.openInput(), () -> store.openOutput());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,57 @@ package io.xpipe.ext.base.actions;
|
||||||
import io.xpipe.app.core.AppActionLinkDetector;
|
import io.xpipe.app.core.AppActionLinkDetector;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import io.xpipe.core.util.SecretValue;
|
import io.xpipe.core.util.SecretValue;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.DataStoreProviders;
|
import io.xpipe.extension.DataStoreProviders;
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.datatransfer.Clipboard;
|
import java.awt.datatransfer.Clipboard;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
|
|
||||||
public class ShareStoreAction implements DataStoreActionProvider<DataStore> {
|
public class ShareStoreAction implements ActionProvider {
|
||||||
|
|
||||||
|
@Value
|
||||||
|
static class Action implements ActionProvider.Action {
|
||||||
|
|
||||||
|
DataStore store;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requiresPlatform() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String create(DataStore store) {
|
||||||
|
return "xpipe://add/store/" + SecretValue.encrypt(store.toString()).getEncryptedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
var string = create(store);
|
||||||
|
var selection = new StringSelection(string);
|
||||||
|
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||||
|
AppActionLinkDetector.setLastDetectedAction(string);
|
||||||
|
clipboard.setContents(selection, selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||||
|
return new DataStoreCallSite<DataStore>() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean showIfDisabled() {
|
public boolean showIfDisabled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionProvider.Action createAction(DataStore store) {
|
||||||
|
return new Action(store);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<DataStore> getApplicableClass() {
|
public Class<DataStore> getApplicableClass() {
|
||||||
return DataStore.class;
|
return DataStore.class;
|
||||||
|
@ -38,17 +73,6 @@ public class ShareStoreAction implements DataStoreActionProvider<DataStore> {
|
||||||
public String getIcon(DataStore store) {
|
public String getIcon(DataStore store) {
|
||||||
return "mdi2c-clipboard-list-outline";
|
return "mdi2c-clipboard-list-outline";
|
||||||
}
|
}
|
||||||
|
};
|
||||||
public static String create(DataStore store) {
|
|
||||||
return "xpipe://add/store/" + SecretValue.encrypt(store.toString()).getEncryptedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(DataStore store) throws Exception {
|
|
||||||
var string = create(store);
|
|
||||||
var selection = new StringSelection(string);
|
|
||||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
|
||||||
AppActionLinkDetector.setLastDetectedAction(string);
|
|
||||||
clipboard.setContents(selection, selection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,33 @@
|
||||||
package io.xpipe.ext.base.actions;
|
package io.xpipe.ext.base.actions;
|
||||||
|
|
||||||
import io.xpipe.core.store.StreamDataStore;
|
import io.xpipe.core.store.StreamDataStore;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.I18n;
|
import io.xpipe.extension.I18n;
|
||||||
import io.xpipe.extension.event.ErrorEvent;
|
import io.xpipe.extension.event.ErrorEvent;
|
||||||
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
import io.xpipe.extension.util.DesktopHelper;
|
import io.xpipe.extension.util.DesktopHelper;
|
||||||
import io.xpipe.extension.util.ThreadHelper;
|
import io.xpipe.extension.util.ThreadHelper;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
||||||
public class StreamExportAction implements DataStoreActionProvider<StreamDataStore> {
|
public class StreamExportAction implements ActionProvider {
|
||||||
|
|
||||||
|
@Value
|
||||||
|
static class Action implements ActionProvider.Action {
|
||||||
|
|
||||||
|
StreamDataStore store;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<StreamDataStore> getApplicableClass() {
|
public boolean requiresPlatform() {
|
||||||
return StreamDataStore.class;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable(StreamDataStore o) throws Exception {
|
public void execute() throws Exception {
|
||||||
return o.getFlow() != null && o.getFlow().hasInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObservableValue<String> getName(StreamDataStore store) {
|
|
||||||
return I18n.observable("base.exportStream");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIcon(StreamDataStore store) {
|
|
||||||
return "mdi2f-file-export-outline";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(StreamDataStore store) throws Exception {
|
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
fileChooser.setTitle(I18n.get("browseFileTitle"));
|
fileChooser.setTitle(I18n.get("browseFileTitle"));
|
||||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(I18n.get("anyFile"), "."));
|
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(I18n.get("anyFile"), "."));
|
||||||
|
@ -56,3 +48,37 @@ public class StreamExportAction implements DataStoreActionProvider<StreamDataSto
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||||
|
return new DataStoreCallSite<StreamDataStore>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action createAction(StreamDataStore store) {
|
||||||
|
return new Action(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isApplicable(StreamDataStore o) throws Exception {
|
||||||
|
return o.getFlow() != null && o.getFlow().hasInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<StreamDataStore> getApplicableClass() {
|
||||||
|
return StreamDataStore.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObservableValue<String> getName(StreamDataStore store) {
|
||||||
|
return I18n.observable("base.exportStream");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIcon(StreamDataStore store) {
|
||||||
|
return "mdi2f-file-export-outline";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import io.xpipe.ext.base.*;
|
||||||
import io.xpipe.ext.base.actions.*;
|
import io.xpipe.ext.base.actions.*;
|
||||||
import io.xpipe.ext.base.apps.*;
|
import io.xpipe.ext.base.apps.*;
|
||||||
import io.xpipe.extension.DataSourceProvider;
|
import io.xpipe.extension.DataSourceProvider;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.DataStoreProvider;
|
import io.xpipe.extension.DataStoreProvider;
|
||||||
import io.xpipe.extension.DataSourceTarget;
|
import io.xpipe.extension.DataSourceTarget;
|
||||||
import io.xpipe.extension.util.ActionProvider;
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
|
@ -22,8 +21,7 @@ open module io.xpipe.ext.base {
|
||||||
requires static net.synedra.validatorfx;
|
requires static net.synedra.validatorfx;
|
||||||
requires static io.xpipe.app;
|
requires static io.xpipe.app;
|
||||||
|
|
||||||
provides ActionProvider with AddStoreAction;
|
provides ActionProvider with AddStoreAction,
|
||||||
provides DataStoreActionProvider with
|
|
||||||
StreamExportAction,
|
StreamExportAction,
|
||||||
ShareStoreAction,
|
ShareStoreAction,
|
||||||
FileBrowseAction,
|
FileBrowseAction,
|
||||||
|
|
|
@ -24,6 +24,7 @@ configurations {
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly project(':app')
|
compileOnly project(':app')
|
||||||
testImplementation project(':app')
|
testImplementation project(':app')
|
||||||
|
testImplementation project(':procx')
|
||||||
testImplementation 'org.apache.commons:commons-lang3:3.12.0'
|
testImplementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
implementation 'org.apache.commons:commons-exec:1.3'
|
implementation 'org.apache.commons:commons-exec:1.3'
|
||||||
compileOnly group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '11.15.0'
|
compileOnly group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '11.15.0'
|
||||||
|
|
|
@ -4,6 +4,7 @@ import io.xpipe.core.process.CommandProcessControl;
|
||||||
import io.xpipe.core.process.ProcessOutputException;
|
import io.xpipe.core.process.ProcessOutputException;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
import io.xpipe.core.process.ShellType;
|
import io.xpipe.core.process.ShellType;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import io.xpipe.extension.event.TrackEvent;
|
import io.xpipe.extension.event.TrackEvent;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
@ -16,7 +17,6 @@ import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public abstract class CommandControlImpl extends ProcessControlImpl implements CommandProcessControl {
|
public abstract class CommandControlImpl extends ProcessControlImpl implements CommandProcessControl {
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ public abstract class CommandControlImpl extends ProcessControlImpl implements C
|
||||||
|
|
||||||
protected final ShellProcessControl parent;
|
protected final ShellProcessControl parent;
|
||||||
@NonNull
|
@NonNull
|
||||||
protected final Function<ShellProcessControl, String> command;
|
protected final FailableFunction<ShellProcessControl, String, Exception> command;
|
||||||
protected final Function<ShellProcessControl, String> terminalCommand;
|
protected final FailableFunction<ShellProcessControl, String, Exception> terminalCommand;
|
||||||
protected boolean elevated;
|
protected boolean elevated;
|
||||||
protected int exitCode = -1;
|
protected int exitCode = -1;
|
||||||
protected String timedOutError;
|
protected String timedOutError;
|
||||||
|
@ -50,8 +50,8 @@ public abstract class CommandControlImpl extends ProcessControlImpl implements C
|
||||||
|
|
||||||
public CommandControlImpl(
|
public CommandControlImpl(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
Function<ShellProcessControl, String> terminalCommand) {
|
FailableFunction<ShellProcessControl, String, Exception> terminalCommand) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.terminalCommand = terminalCommand;
|
this.terminalCommand = terminalCommand;
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.ext.proc;
|
||||||
|
|
||||||
import io.xpipe.core.process.CommandProcessControl;
|
import io.xpipe.core.process.CommandProcessControl;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import io.xpipe.extension.util.ScriptHelper;
|
import io.xpipe.extension.util.ScriptHelper;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
@ -17,8 +18,8 @@ public class LocalCommandControlImpl extends CommandControlImpl {
|
||||||
|
|
||||||
public LocalCommandControlImpl(
|
public LocalCommandControlImpl(
|
||||||
ShellProcessControl parent,
|
ShellProcessControl parent,
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
Function<ShellProcessControl, String> terminalCommand
|
FailableFunction<ShellProcessControl, String, Exception> terminalCommand
|
||||||
) {
|
) {
|
||||||
super(parent, command, terminalCommand);
|
super(parent, command, terminalCommand);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.ext.proc;
|
||||||
|
|
||||||
import io.xpipe.core.process.ProcessControlProvider;
|
import io.xpipe.core.process.ProcessControlProvider;
|
||||||
import io.xpipe.core.process.*;
|
import io.xpipe.core.process.*;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import io.xpipe.extension.event.TrackEvent;
|
import io.xpipe.extension.event.TrackEvent;
|
||||||
import io.xpipe.extension.prefs.PrefsProvider;
|
import io.xpipe.extension.prefs.PrefsProvider;
|
||||||
import io.xpipe.extension.util.ScriptHelper;
|
import io.xpipe.extension.util.ScriptHelper;
|
||||||
|
@ -14,7 +15,6 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class LocalShellControlImpl extends ShellControlImpl {
|
public class LocalShellControlImpl extends ShellControlImpl {
|
||||||
|
@ -25,7 +25,7 @@ public class LocalShellControlImpl extends ShellControlImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessControl command(
|
public CommandProcessControl command(
|
||||||
Function<ShellProcessControl, String> command, Function<ShellProcessControl, String> terminalCommand) {
|
FailableFunction<ShellProcessControl, String, Exception> command, FailableFunction<ShellProcessControl, String, Exception> terminalCommand) {
|
||||||
var control = ProcessControlProvider.createCommand(this, command, terminalCommand);
|
var control = ProcessControlProvider.createCommand(this, command, terminalCommand);
|
||||||
if (control != null) {
|
if (control != null) {
|
||||||
return control;
|
return control;
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
package io.xpipe.ext.proc;
|
package io.xpipe.ext.proc;
|
||||||
|
|
||||||
import io.xpipe.core.process.ProcessControlProvider;
|
|
||||||
import io.xpipe.core.process.CommandProcessControl;
|
import io.xpipe.core.process.CommandProcessControl;
|
||||||
|
import io.xpipe.core.process.ProcessControlProvider;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
import io.xpipe.core.util.FailableBiFunction;
|
||||||
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class ProcProvider extends ProcessControlProvider {
|
public class ProcProvider extends ProcessControlProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShellProcessControl sub(
|
public ShellProcessControl sub(
|
||||||
ShellProcessControl parent, @NonNull Function<ShellProcessControl, String> commandFunction,
|
ShellProcessControl parent, @NonNull FailableFunction<ShellProcessControl, String, Exception> commandFunction,
|
||||||
BiFunction<ShellProcessControl, String, String> terminalCommand
|
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessControl command(
|
public CommandProcessControl command(
|
||||||
ShellProcessControl parent, @NonNull Function<ShellProcessControl, String> command,
|
ShellProcessControl parent, @NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
Function<ShellProcessControl, String> terminalCommand
|
FailableFunction<ShellProcessControl, String, Exception> terminalCommand
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
package io.xpipe.ext.proc;
|
package io.xpipe.ext.proc;
|
||||||
|
|
||||||
import io.xpipe.core.process.ProcessControlProvider;
|
import io.xpipe.core.process.*;
|
||||||
import io.xpipe.core.process.CommandProcessControl;
|
import io.xpipe.core.util.FailableBiFunction;
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.util.FailableFunction;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
|
||||||
import io.xpipe.core.process.ShellType;
|
|
||||||
import io.xpipe.core.util.SecretValue;
|
import io.xpipe.core.util.SecretValue;
|
||||||
import io.xpipe.core.util.XPipeTempDirectory;
|
import io.xpipe.core.util.XPipeTempDirectory;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public abstract class ShellControlImpl extends ProcessControlImpl implements ShellProcessControl {
|
public abstract class ShellControlImpl extends ProcessControlImpl implements ShellProcessControl {
|
||||||
|
|
||||||
|
@ -78,19 +73,19 @@ public abstract class ShellControlImpl extends ProcessControlImpl implements She
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShellProcessControl subShell(
|
public ShellProcessControl subShell(
|
||||||
@NonNull Function<ShellProcessControl, String> command,
|
FailableFunction<ShellProcessControl, String, Exception> command,
|
||||||
BiFunction<ShellProcessControl, String, String> terminalCommand) {
|
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand) {
|
||||||
return ProcessControlProvider.createSub(this, command, terminalCommand);
|
return ProcessControlProvider.createSub(this, command, terminalCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessControl command(Function<ShellProcessControl, String> command) {
|
public CommandProcessControl command(FailableFunction<ShellProcessControl, String, Exception> command) {
|
||||||
return command(command, command);
|
return command(command, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessControl command(
|
public CommandProcessControl command(
|
||||||
Function<ShellProcessControl, String> command, Function<ShellProcessControl, String> terminalCommand) {
|
FailableFunction<ShellProcessControl, String, Exception> command, FailableFunction<ShellProcessControl, String, Exception> terminalCommand) {
|
||||||
var control = ProcessControlProvider.createCommand(this, command, terminalCommand);
|
var control = ProcessControlProvider.createCommand(this, command, terminalCommand);
|
||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,11 @@ public class LaunchAction implements ActionProvider {
|
||||||
public DataStoreCallSite<?> getDataStoreCallSite() {
|
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||||
return new DataStoreCallSite<DataStore>() {
|
return new DataStoreCallSite<DataStore>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showIfDisabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable(DataStore o) throws Exception {
|
public boolean isApplicable(DataStore o) throws Exception {
|
||||||
return o instanceof ShellStore;
|
return o instanceof ShellStore;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.ext.proc.augment;
|
package io.xpipe.ext.proc.augment;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CmdCommandAugmentation extends CommandAugmentation {
|
public class CmdCommandAugmentation extends CommandAugmentation {
|
||||||
|
@ -9,7 +11,7 @@ public class CmdCommandAugmentation extends CommandAugmentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareBaseCommand(List<String> baseCommand) {
|
protected void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) {
|
||||||
remove(baseCommand, "/C");
|
remove(baseCommand, "/C");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,18 @@ public abstract class CommandAugmentation {
|
||||||
|
|
||||||
private static final Set<CommandAugmentation> ALL = new HashSet<>();
|
private static final Set<CommandAugmentation> ALL = new HashSet<>();
|
||||||
|
|
||||||
|
public static String unquote(String input) {
|
||||||
|
if (input.startsWith("\"") && input.endsWith("\"")) {
|
||||||
|
return input.substring(1, input.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startsWith("'") && input.endsWith("'")) {
|
||||||
|
return input.substring(1, input.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
public static CommandAugmentation get(String cmd) {
|
public static CommandAugmentation get(String cmd) {
|
||||||
var parsed = CommandLine.parse(cmd);
|
var parsed = CommandLine.parse(cmd);
|
||||||
var executable = parsed.getExecutable().toLowerCase(Locale.ROOT).replaceAll("\\.exe$", "");
|
var executable = parsed.getExecutable().toLowerCase(Locale.ROOT).replaceAll("\\.exe$", "");
|
||||||
|
@ -36,6 +48,16 @@ public abstract class CommandAugmentation {
|
||||||
|
|
||||||
public abstract boolean matches(String executable);
|
public abstract boolean matches(String executable);
|
||||||
|
|
||||||
|
protected Optional<String> getParameter(List<String> baseCommand, String... args) {
|
||||||
|
for (String arg : args) {
|
||||||
|
var index = baseCommand.indexOf(arg);
|
||||||
|
if (index != -1) {
|
||||||
|
return Optional.of(unquote(baseCommand.get(index + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
protected void addIfNeeded(List<String> baseCommand, String arg) {
|
protected void addIfNeeded(List<String> baseCommand, String arg) {
|
||||||
if (!baseCommand.contains(arg)) {
|
if (!baseCommand.contains(arg)) {
|
||||||
baseCommand.add(1, arg);
|
baseCommand.add(1, arg);
|
||||||
|
@ -48,21 +70,21 @@ public abstract class CommandAugmentation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String prepareTerminalCommand(ShellProcessControl proc, String cmd, String subCommand) {
|
public String prepareTerminalCommand(ShellProcessControl proc, String cmd, String subCommand) throws Exception {
|
||||||
var split = split(cmd);
|
var split = split(cmd);
|
||||||
prepareBaseCommand(split);
|
prepareBaseCommand(proc, split);
|
||||||
modifyTerminalCommand(split, subCommand != null);
|
modifyTerminalCommand(split, subCommand != null);
|
||||||
return proc.getShellType().flatten(split) + (subCommand != null ? " " + subCommand : "");
|
return proc.getShellType().flatten(split) + (subCommand != null ? " " + subCommand : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String prepareNonTerminalCommand(ShellProcessControl proc, String cmd) {
|
public String prepareNonTerminalCommand(ShellProcessControl proc, String cmd) throws Exception {
|
||||||
var split = split(cmd);
|
var split = split(cmd);
|
||||||
prepareBaseCommand(split);
|
prepareBaseCommand(proc, split);
|
||||||
modifyNonTerminalCommand(split);
|
modifyNonTerminalCommand(split);
|
||||||
return proc.getShellType().flatten(split);
|
return proc.getShellType().flatten(split);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void prepareBaseCommand(List<String> baseCommand);
|
protected abstract void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) throws Exception;
|
||||||
|
|
||||||
protected abstract void modifyTerminalCommand(List<String> baseCommand, boolean hasSubCommand);
|
protected abstract void modifyTerminalCommand(List<String> baseCommand, boolean hasSubCommand);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.ext.proc.augment;
|
package io.xpipe.ext.proc.augment;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NoCommandAugmentation extends CommandAugmentation {
|
public class NoCommandAugmentation extends CommandAugmentation {
|
||||||
|
@ -10,7 +12,7 @@ public class NoCommandAugmentation extends CommandAugmentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareBaseCommand(List<String> baseCommand) {}
|
protected void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void modifyTerminalCommand(List<String> baseCommand, boolean hasSubCommand) {}
|
protected void modifyTerminalCommand(List<String> baseCommand, boolean hasSubCommand) {}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.ext.proc.augment;
|
package io.xpipe.ext.proc.augment;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PosixShellCommandAugmentation extends CommandAugmentation {
|
public class PosixShellCommandAugmentation extends CommandAugmentation {
|
||||||
|
@ -9,7 +11,7 @@ public class PosixShellCommandAugmentation extends CommandAugmentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareBaseCommand(List<String> baseCommand) {
|
protected void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) {
|
||||||
remove(baseCommand, "-l", "--login");
|
remove(baseCommand, "-l", "--login");
|
||||||
remove(baseCommand, "-i");
|
remove(baseCommand, "-i");
|
||||||
remove(baseCommand, "-c");
|
remove(baseCommand, "-c");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.xpipe.ext.proc.augment;
|
package io.xpipe.ext.proc.augment;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PowershellCommandAugmentation extends CommandAugmentation {
|
public class PowershellCommandAugmentation extends CommandAugmentation {
|
||||||
|
@ -9,7 +11,7 @@ public class PowershellCommandAugmentation extends CommandAugmentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareBaseCommand(List<String> baseCommand) {
|
protected void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) {
|
||||||
remove(baseCommand, "-Command");
|
remove(baseCommand, "-Command");
|
||||||
remove(baseCommand, "-NonInteractive");
|
remove(baseCommand, "-NonInteractive");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package io.xpipe.ext.proc.augment;
|
package io.xpipe.ext.proc.augment;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.OsType;
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SshCommandAugmentation extends CommandAugmentation {
|
public class SshCommandAugmentation extends CommandAugmentation {
|
||||||
|
@ -10,7 +13,7 @@ public class SshCommandAugmentation extends CommandAugmentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareBaseCommand(List<String> baseCommand) {
|
protected void prepareBaseCommand(ShellProcessControl processControl, List<String> baseCommand) throws Exception {
|
||||||
baseCommand.removeIf(s -> s.equals("-T"));
|
baseCommand.removeIf(s -> s.equals("-T"));
|
||||||
baseCommand.removeIf(s -> s.equals("-t"));
|
baseCommand.removeIf(s -> s.equals("-t"));
|
||||||
baseCommand.removeIf(s -> s.equals("-tt"));
|
baseCommand.removeIf(s -> s.equals("-tt"));
|
||||||
|
@ -18,6 +21,17 @@ public class SshCommandAugmentation extends CommandAugmentation {
|
||||||
|
|
||||||
addIfNeeded(baseCommand, "-oStrictHostKeyChecking=no");
|
addIfNeeded(baseCommand, "-oStrictHostKeyChecking=no");
|
||||||
// addIfNeeded(baseCommand,"-oPasswordAuthentication=no");
|
// addIfNeeded(baseCommand,"-oPasswordAuthentication=no");
|
||||||
|
|
||||||
|
// Ensure proper permissions for keys
|
||||||
|
var key = getParameter(baseCommand, "-i");
|
||||||
|
if (key.isPresent() && (processControl.getOsType().equals(OsType.LINUX) || processControl.getOsType().equals(OsType.MACOS)) ){
|
||||||
|
processControl.executeSimpleCommand("chmod 400 \"" + key.get() + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start agent on windows
|
||||||
|
if (processControl.getOsType().equals(OsType.WINDOWS)) {
|
||||||
|
processControl.executeBooleanSimpleCommand("ssh-agent start");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import io.xpipe.app.util.TerminalProvider;
|
||||||
import io.xpipe.core.process.ProcessControlProvider;
|
import io.xpipe.core.process.ProcessControlProvider;
|
||||||
import io.xpipe.ext.proc.*;
|
import io.xpipe.ext.proc.*;
|
||||||
import io.xpipe.ext.proc.action.InstallConnectorAction;
|
import io.xpipe.ext.proc.action.InstallConnectorAction;
|
||||||
|
@ -21,12 +22,12 @@ open module io.xpipe.ext.proc {
|
||||||
requires static javafx.controls;
|
requires static javafx.controls;
|
||||||
requires io.xpipe.core;
|
requires io.xpipe.core;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
requires static com.jcraft.jsch;
|
|
||||||
requires static io.xpipe.extension;
|
requires static io.xpipe.extension;
|
||||||
requires static io.xpipe.app;
|
requires static io.xpipe.app;
|
||||||
requires static commons.exec;
|
requires static commons.exec;
|
||||||
requires static com.dlsc.preferencesfx;
|
requires static com.dlsc.preferencesfx;
|
||||||
|
|
||||||
|
provides TerminalProvider with TerminalProviderImpl;
|
||||||
provides PrefsProvider with
|
provides PrefsProvider with
|
||||||
ProcPrefs;
|
ProcPrefs;
|
||||||
provides CommandAugmentation with
|
provides CommandAugmentation with
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class CommandStoreTest extends LocalExtensionTest {
|
||||||
.elevation(SecretValue.encrypt("123"))
|
.elevation(SecretValue.encrypt("123"))
|
||||||
.start()) {
|
.start()) {
|
||||||
try (var command = pc.command(List.of("echo", "hi")).elevated().start()) {
|
try (var command = pc.command(List.of("echo", "hi")).elevated().start()) {
|
||||||
var read = command.readOnlyStdout();
|
var read = command.readOrThrow();
|
||||||
Assertions.assertEquals("hi", read);
|
Assertions.assertEquals("hi", read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package test.item;
|
||||||
|
|
||||||
import io.xpipe.core.impl.FileNames;
|
import io.xpipe.core.impl.FileNames;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
import io.xpipe.ext.proc.util.ShellHelper;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.commons.lang3.function.FailableConsumer;
|
import org.apache.commons.lang3.function.FailableConsumer;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
@ -13,7 +12,7 @@ import java.util.UUID;
|
||||||
@Getter
|
@Getter
|
||||||
public enum ShellCheckTestItem {
|
public enum ShellCheckTestItem {
|
||||||
OS_NAME(shellProcessControl -> {
|
OS_NAME(shellProcessControl -> {
|
||||||
var os = ShellHelper.determineOsType(shellProcessControl);
|
var os = shellProcessControl.getOsType();
|
||||||
os.determineOperatingSystemName(shellProcessControl);
|
os.determineOperatingSystemName(shellProcessControl);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ public enum ShellCheckTestItem {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
ECHO(shellProcessControl -> {
|
ECHO(shellProcessControl -> {
|
||||||
ShellHelper.determineOsType(shellProcessControl);
|
shellProcessControl.executeSimpleCommand(shellProcessControl.getShellType().getEchoCommand("test", false));
|
||||||
});
|
});
|
||||||
|
|
||||||
private final FailableConsumer<ShellProcessControl, Exception> shellCheck;
|
private final FailableConsumer<ShellProcessControl, Exception> shellCheck;
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package io.xpipe.extension;
|
|
||||||
|
|
||||||
import io.xpipe.core.store.DataStore;
|
|
||||||
import io.xpipe.extension.event.ErrorEvent;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
|
|
||||||
public interface DataStoreActionProvider<T extends DataStore> {
|
|
||||||
|
|
||||||
static List<DataStoreActionProvider<?>> ALL = new ArrayList<>();
|
|
||||||
|
|
||||||
public static void init(ModuleLayer layer) {
|
|
||||||
if (ALL.size() == 0) {
|
|
||||||
ALL.addAll(ServiceLoader.load(layer, DataStoreActionProvider.class).stream()
|
|
||||||
.map(p -> (DataStoreActionProvider<?>) p.get())
|
|
||||||
.filter(provider -> {
|
|
||||||
try {
|
|
||||||
return provider.isActive();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
ErrorEvent.fromThrowable(e).handle();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<T> getApplicableClass();
|
|
||||||
|
|
||||||
default boolean isMajor() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean isActive() throws Exception {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean isApplicable(T o) throws Exception {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void applyToRegion(T store, Region region) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ObservableValue<String> getName(T store);
|
|
||||||
|
|
||||||
String getIcon(T store);
|
|
||||||
|
|
||||||
default void execute(T store) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean showIfDisabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@ import io.xpipe.core.util.SecretValue;
|
||||||
import io.xpipe.extension.event.TrackEvent;
|
import io.xpipe.extension.event.TrackEvent;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -91,6 +92,18 @@ public class ScriptHelper {
|
||||||
} "$@"
|
} "$@"
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
public static String unquote(String input) {
|
||||||
|
if (input.startsWith("\"") && input.endsWith("\"")) {
|
||||||
|
return input.substring(1, input.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.startsWith("'") && input.endsWith("'")) {
|
||||||
|
return input.substring(1, input.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
public static String constructOpenWithInitScriptCommand(
|
public static String constructOpenWithInitScriptCommand(
|
||||||
ShellProcessControl processControl, List<String> init, String toExecuteInShell) {
|
ShellProcessControl processControl, List<String> init, String toExecuteInShell) {
|
||||||
ShellType t = processControl.getShellType();
|
ShellType t = processControl.getShellType();
|
||||||
|
@ -98,6 +111,20 @@ public class ScriptHelper {
|
||||||
return t.getNormalOpenCommand();
|
return t.getNormalOpenCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (init.size() == 0) {
|
||||||
|
var cmd = unquote(toExecuteInShell);
|
||||||
|
|
||||||
|
// Check for special case of the command to be executed just being another shell script
|
||||||
|
if (cmd.endsWith(".sh") || cmd.endsWith(".bat")) {
|
||||||
|
return t.executeCommandWithShell(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for special case of the command being a shell command
|
||||||
|
if (Arrays.stream(ShellTypes.getAllShellTypes()).anyMatch(shellType -> cmd.equals(shellType.getNormalOpenCommand()))) {
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String nl = t.getNewLine().getNewLineString();
|
String nl = t.getNewLine().getNewLineString();
|
||||||
var content = String.join(nl, init) + nl;
|
var content = String.join(nl, init) + nl;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import io.xpipe.core.util.ProxyFunction;
|
import io.xpipe.core.util.ProxyFunction;
|
||||||
import io.xpipe.extension.DataSourceProvider;
|
import io.xpipe.extension.DataSourceProvider;
|
||||||
import io.xpipe.extension.DataStoreActionProvider;
|
|
||||||
import io.xpipe.extension.DataSourceTarget;
|
import io.xpipe.extension.DataSourceTarget;
|
||||||
import io.xpipe.extension.prefs.PrefsProvider;
|
import io.xpipe.extension.prefs.PrefsProvider;
|
||||||
import io.xpipe.extension.util.ActionProvider;
|
import io.xpipe.extension.util.ActionProvider;
|
||||||
|
@ -45,7 +44,6 @@ open module io.xpipe.extension {
|
||||||
|
|
||||||
uses DataSourceProvider;
|
uses DataSourceProvider;
|
||||||
uses DataSourceTarget;
|
uses DataSourceTarget;
|
||||||
uses DataStoreActionProvider;
|
|
||||||
uses io.xpipe.extension.I18n;
|
uses io.xpipe.extension.I18n;
|
||||||
uses io.xpipe.extension.event.EventHandler;
|
uses io.xpipe.extension.event.EventHandler;
|
||||||
uses io.xpipe.extension.prefs.PrefsProvider;
|
uses io.xpipe.extension.prefs.PrefsProvider;
|
||||||
|
|
Loading…
Reference in a new issue