Update readme

This commit is contained in:
crschnick
2023-02-28 14:22:49 +00:00
parent 1bde4c8909
commit d5a7e2fb64
17 changed files with 91 additions and 47 deletions
+5 -5
View File
@@ -1,12 +1,12 @@
<img src="https://user-images.githubusercontent.com/72509152/213873342-7638e830-8a95-4b5d-ad3e-5a9a0b4bf538.png" alt="drawing" width="300"/>
### Next level remote data workflows for everyone
### A smart connection manager and remote file explorer
X-Pipe is a connection manager, remote file explorer, and more in an early alpha.
The core approach is to utilize and integrate well with other tools and workflows,
X-Pipe takes a fresh spin on the established concept of connection managers.
The central idea is to utilize and integrate well with your existing tools and workflows,
focusing on augmenting them rather than replacing them.
X-Pipe is built around existing tools and tries to outsource tasks to them,
such that you can always use your favorite tools to work with X-Pipe, e.g.
X-Pipe outsources as many tasks as possible such
that you can always use your favorite tools to work with X-Pipe, e.g.
text/code editors, terminals, shells, command-line tools and more.
The X-Pipe platform is open source and designed to be extensible, allowing anyone
to implement custom functionality through custom extensions.
@@ -39,7 +39,8 @@ public class OpenFileSystemComp extends SimpleComp {
var path = new SimpleStringProperty(model.getCurrentPath().get());
var pathBar = new TextFieldComp(path, true).createRegion();
path.addListener((observable, oldValue, newValue) -> {
model.cd(newValue);
var changed = model.cd(newValue);
changed.ifPresent(path::set);
});
model.getCurrentPath().addListener((observable, oldValue, newValue) -> {
path.set(newValue);
@@ -6,6 +6,7 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.BusyProperty;
import io.xpipe.app.util.TerminalHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.store.ConnectionFileSystem;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.FileSystemStore;
@@ -18,6 +19,7 @@ import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Getter
@@ -51,25 +53,27 @@ final class OpenFileSystemModel {
return new FileSystem.FileEntry(fileSystem, currentPath.get(), Instant.now(), true, false, false, 0);
}
public void cd(String path) {
public Optional<String> cd(String path) {
var newPath = FileSystemHelper.normalizeDirectoryPath(this, path);
if (!path.equals(newPath)) {
return Optional.of(newPath);
}
ThreadHelper.runFailableAsync(() -> {
try (var ignored = new BusyProperty(busy)) {
cdSync(path);
}
});
return Optional.empty();
}
private boolean cdSync(String path) {
private void cdSync(String path) {
path = FileSystemHelper.normalizeDirectoryPath(this, path);
if (!navigateToSync(path)) {
return false;
}
navigateToSync(path);
filter.setValue(null);
currentPath.set(path);
history.cd(path);
return true;
}
private boolean navigateToSync(String dir) {
@@ -85,6 +89,7 @@ final class OpenFileSystemModel {
fileList.setAll(newList);
return true;
} catch (Exception e) {
fileList.setAll(List.of());
ErrorEvent.fromThrowable(e).handle();
return false;
}
@@ -171,7 +176,7 @@ final class OpenFileSystemModel {
fs.open();
this.fileSystem = fs;
var current = fs instanceof ConnectionFileSystem connectionFileSystem
var current = !(fileSystem instanceof LocalStore) && fs instanceof ConnectionFileSystem connectionFileSystem
? connectionFileSystem
.getShellProcessControl()
.executeStringSimpleCommand(connectionFileSystem
@@ -66,7 +66,8 @@ public class AppGreetings {
}
public static void showIfNeeded() {
if (!AppProperties.get().isImage()) {
//TODO
if (!AppProperties.get().isImage() || true) {
return;
}
@@ -66,7 +66,11 @@ public class SentryErrorHandler {
s.setTag("terminal", Boolean.toString(ee.isTerminal()));
s.setTag("omitted", Boolean.toString(ee.isOmitted()));
ee.getTrackEvents().forEach(t -> s.addBreadcrumb(toBreadcrumb(t)));
/*
TODO: Ignore breadcrumbs for now
*/
// ee.getTrackEvents().forEach(t -> s.addBreadcrumb(toBreadcrumb(t)));
if (ee.getThrowable() != null) {
if (ee.getDescription() != null
@@ -5,7 +5,6 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.ShellStore;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -38,7 +37,7 @@ public abstract class ExternalApplicationType implements PrefsChoiceValue {
}
protected Optional<Path> getApplicationPath() {
try (ShellProcessControl pc = ShellStore.createLocal().create().start()) {
try (ShellProcessControl pc = LocalStore.getShell().start()) {
try (var c = pc.command(String.format(
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister "
+ "-dump | grep -o \"/.*%s.app\" | grep -v -E \"Caches|TimeMachine|Temporary|/Volumes/%s\" | uniq",
@@ -2,7 +2,6 @@ package io.xpipe.app.util;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.util.XPipeInstallation;
import java.nio.file.Files;
@@ -21,7 +20,7 @@ public class DesktopShortcuts {
%%PWS%% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut('%%SHORTCUT%%'); $S.IconLocation='%s'; $S.TargetPath = '%%TARGET%%'; $S.Save()"
""",
target, name, icon.toString());
ShellStore.createLocal().create().executeSimpleCommand(content);
LocalStore.getShell().executeSimpleCommand(content);
}
private static void createLinuxShortcut(String target, String name) throws Exception {
@@ -3,9 +3,9 @@ package io.xpipe.app.util;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.impl.FileNames;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.ShellStore;
import org.apache.commons.io.FilenameUtils;
import java.nio.file.Path;
@@ -65,7 +65,7 @@ public class FileOpener {
}
public static void openInDefaultApplication(String file) {
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
if (pc.getOsType().equals(OsType.WINDOWS)) {
pc.executeSimpleCommand("\"" + file + "\"");
} else if (pc.getOsType().equals(OsType.LINUX)) {
@@ -2,7 +2,7 @@ package io.xpipe.app.util;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppWindowHelper;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.impl.LocalStore;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Alert;
@@ -14,7 +14,7 @@ public class MacOsPermissions {
public static boolean waitForAccessibilityPermissions() throws Exception {
AtomicReference<Alert> alert = new AtomicReference<>();
var state = new SimpleBooleanProperty(true);
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
while (state.get()) {
var success = pc.executeBooleanSimpleCommand(
"osascript -e 'tell application \"System Events\" to keystroke \"t\"'");
@@ -2,11 +2,11 @@ package io.xpipe.app.util;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.core.impl.FileNames;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.process.ShellDialect;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.util.SecretValue;
import lombok.SneakyThrows;
@@ -42,7 +42,7 @@ public class ScriptHelper {
@SneakyThrows
public static String createLocalExecScript(String content) {
try (var l = ShellStore.createLocal().create().start()) {
try (var l = LocalStore.getShell().start()) {
return createExecScript(l, content);
}
}
@@ -167,6 +167,19 @@ public class ScriptHelper {
return t.getInitFileOpenCommand(initFile);
}
@SneakyThrows
public static String getExecScriptFile(ShellProcessControl processControl) {
return getExecScriptFile(processControl, processControl.getShellDialect().getScriptFileEnding());
}
@SneakyThrows
public static String getExecScriptFile(ShellProcessControl processControl, String fileEnding) {
var fileName = "exec-" + getScriptId();
var temp = processControl.getTemporaryDirectory();
var file = FileNames.join(temp, fileName + "." + fileEnding);
return file;
}
@SneakyThrows
public static String createExecScript(ShellProcessControl processControl, String content) {
var fileName = "exec-" + getScriptId();
@@ -18,11 +18,19 @@ public class FileNames {
}
public static String getFileName(String file) {
if (file.isEmpty()) {
return "";
}
var split = file.split("[\\\\/]");
if (split.length == 0) {
return "";
}
var components = Arrays.stream(split).filter(s -> !s.isEmpty()).toList();
if (components.size() == 0) {
return "";
}
return components.get(components.size() - 1);
}
@@ -4,12 +4,12 @@ import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.*;
import io.xpipe.core.store.ConnectionFileSystem;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.util.JacksonizedValue;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
@JsonTypeName("local")
@@ -43,17 +43,6 @@ public class LocalStore extends JacksonizedValue implements ShellStore {
return LocalStore.this;
}
@Override
public InputStream openInput(String file) throws Exception {
var p = wrap(file);
return Files.newInputStream(p);
}
@Override
public OutputStream openOutput(String file) throws Exception {
var p = wrap(file);
return Files.newOutputStream(p);
}
private Path wrap(String file) {
for (var e : System.getenv().entrySet()) {
@@ -49,10 +49,16 @@ public interface CommandProcessControl extends ProcessControl {
public String readOrThrow() throws Exception;
public default boolean discardAndCheckExit() {
public default boolean discardAndCheckExit() throws ProcessOutputException {
try {
discardOrThrow();
return true;
} catch (ProcessOutputException ex) {
if (ex.isTimeOut()) {
throw ex;
}
return false;
} catch (Exception ex) {
return false;
}
@@ -25,4 +25,8 @@ public class ProcessOutputException extends Exception {
this.exitCode = exitCode;
this.output = output;
}
public boolean isTimeOut() {
return exitCode == -1;
}
}
@@ -17,6 +17,14 @@ public interface ShellDialect {
return "cd \"" + directory + "\"";
}
default String getPushdCommand(String directory){
return "pushd \"" + directory + "\"";
}
default String getPopdCommand(){
return "popd";
}
String getScriptFileEnding();
String addInlineVariablesToCommand(Map<String, String> variables, String command);
@@ -39,8 +47,6 @@ public interface ShellDialect {
.collect(Collectors.joining(" "));
}
void disableHistory(ShellProcessControl pc) throws Exception;
default String getExitCommand() {
return "exit";
}
@@ -0,0 +1,10 @@
package io.xpipe.core.process;
import lombok.Value;
@Value
public class ShellProperties {
ShellDialect dialect;
boolean tty;
}
@@ -8,7 +8,6 @@ import io.xpipe.app.util.XPipeDaemon;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.ShellStore;
import java.util.List;
import java.util.UUID;
@@ -17,7 +16,7 @@ public class LocalStoreProvider implements DataStoreProvider {
@Override
public String queryInformationString(DataStore store, int length) throws Exception {
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
return OsType.getLocal().determineOperatingSystemName(pc);
}
}