mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
More shell rework
This commit is contained in:
parent
11667d7876
commit
4bb7627488
21 changed files with 79 additions and 99 deletions
|
@ -136,7 +136,7 @@ run {
|
|||
systemProperty 'io.xpipe.app.writeLogs', "true"
|
||||
systemProperty 'io.xpipe.app.writeSysOut', "true"
|
||||
systemProperty 'io.xpipe.app.developerMode', "true"
|
||||
systemProperty 'io.xpipe.app.logLevel', "debug"
|
||||
systemProperty 'io.xpipe.app.logLevel', "trace"
|
||||
systemProperty 'io.xpipe.app.fullVersion', rootProject.fullVersion
|
||||
// systemProperty "io.xpipe.beacon.port", "21724"
|
||||
// systemProperty "io.xpipe.beacon.printMessages", "true"
|
||||
|
|
|
@ -209,7 +209,7 @@ public class FileBrowserComp extends SimpleComp {
|
|||
? DataStorage.get()
|
||||
.getStoreEntry(model.getStore().getValue())
|
||||
.getProvider()
|
||||
.getDisplayIconFileName()
|
||||
.getDisplayIconFileName(model.getStore().getValue())
|
||||
: null;
|
||||
},
|
||||
model.getStore());
|
||||
|
|
|
@ -204,9 +204,9 @@ final class FileListComp extends AnchorPane {
|
|||
}
|
||||
newItems.addAll(newValue);
|
||||
table.getItems().setAll(newItems);
|
||||
if (newValue.size() > 0) {
|
||||
table.scrollTo(0);
|
||||
}
|
||||
// if (newValue.size() > 0) {
|
||||
// table.scrollTo(0);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.xpipe.app.issue.ErrorEvent;
|
|||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.store.ConnectionFileSystem;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
|
||||
import java.nio.file.Files;
|
||||
|
@ -13,7 +14,25 @@ import java.util.List;
|
|||
|
||||
public class FileSystemHelper {
|
||||
|
||||
public static String normalizeDirectoryPath(OpenFileSystemModel model, String path) {
|
||||
public static String getStartDirectory(OpenFileSystemModel model) throws Exception {
|
||||
// Handle special case when file system creation has failed
|
||||
if (model.getFileSystem() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ConnectionFileSystem fileSystem = (ConnectionFileSystem) model.getFileSystem();
|
||||
var current = !(model.getStore().getValue() instanceof LocalStore)
|
||||
? fileSystem
|
||||
.getShellControl()
|
||||
.executeStringSimpleCommand(fileSystem
|
||||
.getShellControl()
|
||||
.getShellDialect()
|
||||
.getPrintWorkingDirectoryCommand())
|
||||
: fileSystem.getShell().get().getOsType().getHomeDirectory(fileSystem.getShell().get());
|
||||
return FileSystemHelper.normalizeDirectoryPath(model, current);
|
||||
}
|
||||
|
||||
public static String normalizeDirectoryPath(OpenFileSystemModel model, String path) throws Exception {
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -37,7 +56,11 @@ public class FileSystemHelper {
|
|||
return path + "\\";
|
||||
}
|
||||
|
||||
return FileNames.toDirectory(path);
|
||||
var normalized = shell.get()
|
||||
.getShellDialect()
|
||||
.normalizeDirectory(shell.get(), path)
|
||||
.readOrThrow();
|
||||
return FileNames.toDirectory(normalized);
|
||||
}
|
||||
|
||||
public static FileSystem.FileEntry getLocal(Path file) throws Exception {
|
||||
|
|
|
@ -7,7 +7,6 @@ import io.xpipe.app.util.BusyProperty;
|
|||
import io.xpipe.app.util.TerminalHelper;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.store.ConnectionFileSystem;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
import io.xpipe.core.store.FileSystemStore;
|
||||
|
@ -76,7 +75,14 @@ final class OpenFileSystemModel {
|
|||
}
|
||||
|
||||
public Optional<String> cd(String path) {
|
||||
var newPath = FileSystemHelper.normalizeDirectoryPath(this, path);
|
||||
String newPath = null;
|
||||
try {
|
||||
newPath = FileSystemHelper.normalizeDirectoryPath(this, path);
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
return Optional.of(currentPath.get());
|
||||
}
|
||||
|
||||
if (!Objects.equals(path, newPath)) {
|
||||
return Optional.of(newPath);
|
||||
}
|
||||
|
@ -96,7 +102,8 @@ final class OpenFileSystemModel {
|
|||
this.fileSystem = fs;
|
||||
}
|
||||
|
||||
path = FileSystemHelper.normalizeDirectoryPath(this, path);
|
||||
// Assumed that the path is normalized to improve performance!
|
||||
// path = FileSystemHelper.normalizeDirectoryPath(this, path);
|
||||
|
||||
navigateToSync(path);
|
||||
filter.setValue(null);
|
||||
|
@ -218,14 +225,7 @@ final class OpenFileSystemModel {
|
|||
fs.open();
|
||||
this.fileSystem = fs;
|
||||
|
||||
var current = !(fileSystem instanceof LocalStore) && fs instanceof ConnectionFileSystem connectionFileSystem
|
||||
? connectionFileSystem
|
||||
.getShellControl()
|
||||
.executeStringSimpleCommand(connectionFileSystem
|
||||
.getShellControl()
|
||||
.getShellDialect()
|
||||
.getPrintWorkingDirectoryCommand())
|
||||
: null;
|
||||
var current = FileSystemHelper.getStartDirectory(this);
|
||||
cdSync(current);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public class DataStoreSelectorComp extends Comp<CompStructure<Button>> {
|
|||
? DataStoreProviders.byStoreClass(chosenStore.getValue().getClass())
|
||||
.orElse(null)
|
||||
: null;
|
||||
var graphic = provider != null ? provider.getDisplayIconFileName() : "file_icon.png";
|
||||
var graphic = provider != null ? provider.getDisplayIconFileName(chosenStore.getValue()) : "file_icon.png";
|
||||
if (chosenStore.getValue() == null || !(chosenStore.getValue() instanceof FileStore f)) {
|
||||
return JfxHelper.createNamedEntry(
|
||||
AppI18n.get("selectStreamStore"), AppI18n.get("openStreamStoreWizard"), graphic);
|
||||
|
|
|
@ -43,7 +43,7 @@ public class DsStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>
|
|||
return createDefaultNode();
|
||||
}
|
||||
|
||||
var graphic = provider.getDisplayIconFileName();
|
||||
var graphic = provider.getDisplayIconFileName(null);
|
||||
return JfxHelper.createNamedEntry(provider.getDisplayName(), provider.getDisplayDescription(), graphic);
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ public class NamedStoreChoiceComp extends SimpleComp implements Validatable {
|
|||
|
||||
var view = new ListViewComp<>(shown, list, prop, (DataStoreEntry e) -> {
|
||||
var provider = e.getProvider();
|
||||
var graphic = provider.getDisplayIconFileName();
|
||||
var graphic = provider.getDisplayIconFileName(e.getStore());
|
||||
var top = String.format("%s (%s)", e.getName(), provider.getDisplayName());
|
||||
var bottom = provider.toSummaryString(e.getStore(), 50);
|
||||
var el = JfxHelper.createNamedEntry(top, bottom, graphic);
|
||||
|
|
|
@ -98,7 +98,7 @@ public class StoreEntryComp extends SimpleComp {
|
|||
private Node createIcon() {
|
||||
var img = entry.isDisabled()
|
||||
? "disabled_icon.png"
|
||||
: entry.getEntry().getProvider().getDisplayIconFileName();
|
||||
: entry.getEntry().getProvider().getDisplayIconFileName(entry.getEntry().getStore());
|
||||
var imageComp = new PrettyImageComp(new SimpleStringProperty(img), 55, 45);
|
||||
var storeIcon = imageComp.createRegion();
|
||||
storeIcon.getStyleClass().add("icon");
|
||||
|
|
|
@ -41,7 +41,9 @@ public class StoreEntryFlatMiniSection extends SimpleComp {
|
|||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var image = entry.getState() == DataStoreEntry.State.LOAD_FAILED ? "disabled_icon.png" : entry.getProvider().getDisplayIconFileName();
|
||||
var image = entry.getState() == DataStoreEntry.State.LOAD_FAILED
|
||||
? "disabled_icon.png"
|
||||
: entry.getProvider().getDisplayIconFileName(entry.getStore());
|
||||
var label = new Label(entry.getName(), new PrettyImageComp(new SimpleStringProperty(image), 20, 20).createRegion());
|
||||
var spacer = new Spacer(depth * 10, Orientation.HORIZONTAL);
|
||||
var box = new HBox(spacer, label);
|
||||
|
|
|
@ -100,7 +100,7 @@ public interface DataStoreProvider {
|
|||
return i != -1 ? n.substring(i + 1) : n;
|
||||
}
|
||||
|
||||
default String getDisplayIconFileName() {
|
||||
default String getDisplayIconFileName(DataStore store) {
|
||||
return getModuleName() + ":" + getId() + "_icon.png";
|
||||
}
|
||||
|
||||
|
|
|
@ -34,13 +34,13 @@ public class FileSystemStoreChoiceComp extends SimpleComp {
|
|||
|
||||
private Region createGraphic(FileSystemStore s) {
|
||||
var provider = DataStoreProviders.byStore(s);
|
||||
var img = new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName()), 16, 16);
|
||||
var img = new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName(s)), 16, 16);
|
||||
return new Label(getName(s), img.createRegion());
|
||||
}
|
||||
|
||||
private Region createDisplayGraphic(FileSystemStore s) {
|
||||
var provider = DataStoreProviders.byStore(s);
|
||||
var img = new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName()), 16, 16);
|
||||
var img = new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName(s)), 16, 16);
|
||||
return new Label(null, img.createRegion());
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ShellStoreChoiceComp<T extends ShellStore> extends SimpleComp {
|
|||
protected Region createGraphic(T s) {
|
||||
var provider = DataStoreProviders.byStore(s);
|
||||
var imgView =
|
||||
new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName()), 16, 16).createRegion();
|
||||
new PrettyImageComp(new SimpleStringProperty(provider.getDisplayIconFileName(s)), 16, 16).createRegion();
|
||||
|
||||
var name = DataStorage.get().getUsableStores().stream()
|
||||
.filter(e -> e.equals(s))
|
||||
|
|
|
@ -3,6 +3,9 @@ package io.xpipe.core.charsetter;
|
|||
import io.xpipe.core.util.Identifiers;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
@ -117,6 +120,17 @@ public class StreamCharset {
|
|||
byte[] byteOrderMark;
|
||||
List<String> names;
|
||||
|
||||
public Reader reader(InputStream stream) throws Exception {
|
||||
if (hasByteOrderMark()) {
|
||||
var bom = stream.readNBytes(getByteOrderMark().length);
|
||||
if (bom.length != 0 && !Arrays.equals(bom, getByteOrderMark())) {
|
||||
throw new IllegalStateException("Charset does not match: " + charset.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return new InputStreamReader(stream, charset);
|
||||
}
|
||||
|
||||
public static StreamCharset get(Charset charset, boolean byteOrderMark) {
|
||||
return ALL.stream()
|
||||
.filter(streamCharset ->
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.util.concurrent.ExecutorService;
|
|||
|
||||
public interface ProcessControl extends Closeable, AutoCloseable {
|
||||
|
||||
void resetData();
|
||||
|
||||
ExecutorService getStdoutReader();
|
||||
|
||||
ExecutorService getStderrReader();
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.core.process;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import io.xpipe.core.charsetter.StreamCharset;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
@ -13,6 +14,12 @@ import java.util.stream.Stream;
|
|||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public interface ShellDialect {
|
||||
|
||||
default StreamCharset getTextFileCharset(ShellControl sc) {
|
||||
return StreamCharset.get(sc.getCharset(), false);
|
||||
}
|
||||
|
||||
CommandControl normalizeDirectory(ShellControl shellControl, String directory);
|
||||
|
||||
String fileArgument(String s);
|
||||
|
||||
default String applyRcFileCommand() {
|
||||
|
@ -91,6 +98,10 @@ public interface ShellDialect {
|
|||
|
||||
String prepareInitFileOpenCommand(ShellControl parent, String file);
|
||||
|
||||
String runScript(String file);
|
||||
|
||||
String sourceScript(String file);
|
||||
|
||||
String executeCommandWithShell(String cmd);
|
||||
|
||||
String getMkdirsCommand(String dirs);
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
package io.xpipe.ext.base;
|
||||
|
||||
import io.xpipe.app.ext.DataStoreProvider;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.StorageElement;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LocalStoreProvider implements DataStoreProvider {
|
||||
|
||||
@Override
|
||||
public String queryInformationString(DataStore store, int length) throws Exception {
|
||||
try (var pc = LocalStore.getShell().start()) {
|
||||
return OsType.getLocal().determineOperatingSystemName(pc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSummaryString(DataStore store, int length) {
|
||||
return "localhost";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storageInit() throws Exception {
|
||||
var hasLocal = DataStorage.get().getUsableStores().stream()
|
||||
.anyMatch(dataStore -> dataStore instanceof LocalStore);
|
||||
if (hasLocal) {
|
||||
return;
|
||||
}
|
||||
|
||||
var e = DataStoreEntry.createNew(UUID.randomUUID(), "Local Machine", new LocalStore());
|
||||
DataStorage.get().addStoreEntry(e);
|
||||
e.setConfiguration(StorageElement.Configuration.builder()
|
||||
.deletable(false)
|
||||
.editable(false)
|
||||
.refreshable(true)
|
||||
.renameable(false)
|
||||
.build());
|
||||
e.refresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStore defaultStore() {
|
||||
return new LocalStore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossibleNames() {
|
||||
return List.of("local", "localhost");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<?>> getStoreClasses() {
|
||||
return List.of(LocalStore.class);
|
||||
}
|
||||
}
|
|
@ -44,7 +44,6 @@ open module io.xpipe.ext.base {
|
|||
provides DataStoreProvider with
|
||||
SinkDrainStoreProvider,
|
||||
HttpStoreProvider,
|
||||
LocalStoreProvider,
|
||||
InternalStreamProvider,
|
||||
FileStoreProvider,
|
||||
InMemoryStoreProvider;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
Loading…
Reference in a new issue