mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Update readme
This commit is contained in:
parent
1bde4c8909
commit
d5a7e2fb64
17 changed files with 91 additions and 47 deletions
10
README.md
10
README.md
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue