mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-02 10:41:40 +12:00
Rework external application handling
This commit is contained in:
parent
6b80d4cda3
commit
c0abdf968a
3 changed files with 196 additions and 118 deletions
|
@ -0,0 +1,100 @@
|
||||||
|
package io.xpipe.app.prefs;
|
||||||
|
|
||||||
|
import io.xpipe.core.process.OsType;
|
||||||
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
|
import io.xpipe.core.store.ShellStore;
|
||||||
|
import io.xpipe.extension.event.ErrorEvent;
|
||||||
|
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class ExternalApplicationType implements PrefsChoiceValue {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public ExternalApplicationType(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean isSelectable();
|
||||||
|
|
||||||
|
public abstract boolean isAvailable();
|
||||||
|
|
||||||
|
public static class MacApplication extends ExternalApplicationType {
|
||||||
|
|
||||||
|
protected final String applicationName;
|
||||||
|
|
||||||
|
public MacApplication(String id, String applicationName) {
|
||||||
|
super(id);
|
||||||
|
this.applicationName = applicationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelectable() {
|
||||||
|
return OsType.getLocal().equals(OsType.MAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
try {
|
||||||
|
return ShellStore.local()
|
||||||
|
.create()
|
||||||
|
.executeBooleanSimpleCommand(String.format("mdfind -name '%s.app'", applicationName));
|
||||||
|
} catch (Exception e) {
|
||||||
|
ErrorEvent.fromThrowable(e).omit().handle();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LinuxPathApplication extends ExternalApplicationType {
|
||||||
|
|
||||||
|
protected final String command;
|
||||||
|
|
||||||
|
public LinuxPathApplication(String id, String command) {
|
||||||
|
super(id);
|
||||||
|
this.command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAvailable() {
|
||||||
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
|
return pc.executeBooleanSimpleCommand(pc.getShellType().getWhichCommand(command));
|
||||||
|
} catch (Exception e) {
|
||||||
|
ErrorEvent.fromThrowable(e).omit().handle();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelectable() {
|
||||||
|
return OsType.getLocal().equals(OsType.LINUX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class WindowsFullPathType extends ExternalApplicationType {
|
||||||
|
|
||||||
|
public WindowsFullPathType(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Optional<Path> determinePath();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelectable() {
|
||||||
|
return OsType.getLocal().equals(OsType.WINDOWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
var path = determinePath();
|
||||||
|
return path.isPresent() && Files.exists(path.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,20 @@
|
||||||
package io.xpipe.app.prefs;
|
package io.xpipe.app.prefs;
|
||||||
|
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
|
||||||
import io.xpipe.core.process.ShellTypes;
|
import io.xpipe.core.process.ShellTypes;
|
||||||
import io.xpipe.core.store.ShellStore;
|
|
||||||
import io.xpipe.extension.event.ErrorEvent;
|
|
||||||
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
||||||
import io.xpipe.extension.util.ApplicationHelper;
|
import io.xpipe.extension.util.ApplicationHelper;
|
||||||
import io.xpipe.extension.util.WindowsRegistry;
|
import io.xpipe.extension.util.WindowsRegistry;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.apache.commons.lang3.SystemUtils;
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Getter
|
public interface ExternalEditorType extends PrefsChoiceValue {
|
||||||
@AllArgsConstructor
|
|
||||||
public abstract class ExternalEditorType implements PrefsChoiceValue {
|
|
||||||
|
|
||||||
public static final ExternalEditorType NOTEPAD = new WindowsFullPathType("app.notepad") {
|
public static final ExternalEditorType NOTEPAD = new WindowsFullPathType("app.notepad") {
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,49 +49,39 @@ public abstract class ExternalEditorType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final PathType NOTEPADPLUSPLUS_LINUX = new PathType("app.notepad++", "notepad++");
|
public static final LinuxPathType NOTEPADPLUSPLUS_LINUX = new LinuxPathType("app.notepad++", "notepad++");
|
||||||
|
|
||||||
public static final PathType VSCODE_LINUX = new PathType("app.vscode", "code");
|
public static final LinuxPathType VSCODE_LINUX = new LinuxPathType("app.vscode", "code");
|
||||||
|
|
||||||
public static final PathType KATE = new PathType("app.kate", "kate");
|
public static final LinuxPathType KATE = new LinuxPathType("app.kate", "kate");
|
||||||
|
|
||||||
public static final PathType GEDIT = new PathType("app.gedit", "gedit");
|
public static final LinuxPathType GEDIT = new LinuxPathType("app.gedit", "gedit");
|
||||||
|
|
||||||
public static final PathType LEAFPAD = new PathType("app.leafpad", "leafpad");
|
public static final LinuxPathType LEAFPAD = new LinuxPathType("app.leafpad", "leafpad");
|
||||||
|
|
||||||
public static final PathType MOUSEPAD = new PathType("app.mousepad", "mousepad");
|
public static final LinuxPathType MOUSEPAD = new LinuxPathType("app.mousepad", "mousepad");
|
||||||
|
|
||||||
public static final PathType PLUMA = new PathType("app.pluma", "pluma");
|
public static final LinuxPathType PLUMA = new LinuxPathType("app.pluma", "pluma");
|
||||||
|
|
||||||
public static final ExternalEditorType TEXT_EDIT = new MacOsFullPathType("app.textEdit") {
|
class MacOsEditor extends ExternalApplicationType.MacApplication implements ExternalEditorType {
|
||||||
@Override
|
|
||||||
protected Path determinePath() {
|
public MacOsEditor(String id, String applicationName) {
|
||||||
return Path.of("/System/Applications/TextEdit.app");
|
super(id, applicationName);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public static final ExternalEditorType NOTEPADPP_MACOS = new MacOsFullPathType("app.notepad++") {
|
|
||||||
@Override
|
@Override
|
||||||
protected Path determinePath() {
|
public void launch(Path file) throws Exception {
|
||||||
return Path.of("/Applications/Notepad++.app");
|
ApplicationHelper.executeLocalApplication(List.of("open", "-a", applicationName, file.toString()));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public static final ExternalEditorType SUBLIME_MACOS = new MacOsFullPathType("app.sublime") {
|
|
||||||
@Override
|
|
||||||
protected Path determinePath() {
|
|
||||||
return Path.of("/Applications/Sublime.app");
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public static final ExternalEditorType VSCODE_MACOS = new MacOsFullPathType("app.vscode") {
|
public static final ExternalEditorType TEXT_EDIT = new MacOsEditor("app.textEdit", "TextEdit");
|
||||||
@Override
|
|
||||||
protected Path determinePath() {
|
|
||||||
return Path.of("/Applications/VSCode.app");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final ExternalEditorType CUSTOM = new ExternalEditorType("app.custom") {
|
public static final ExternalEditorType SUBLIME_MACOS = new MacOsEditor("app.sublime", "Sublime Text");
|
||||||
|
|
||||||
|
public static final ExternalEditorType VSCODE_MACOS = new MacOsEditor("app.vscode", "VSCode");
|
||||||
|
|
||||||
|
public static final ExternalEditorType CUSTOM = new ExternalEditorType() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(Path file) throws Exception {
|
public void launch(Path file) throws Exception {
|
||||||
|
@ -116,21 +99,20 @@ public abstract class ExternalEditorType implements PrefsChoiceValue {
|
||||||
public boolean isSelectable() {
|
public boolean isSelectable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "app.custom";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private String id;
|
public void launch(Path file) throws Exception;
|
||||||
|
|
||||||
public abstract void launch(Path file) throws Exception;
|
|
||||||
|
|
||||||
public abstract boolean isSelectable();
|
public static class LinuxPathType extends ExternalApplicationType.LinuxPathApplication implements ExternalEditorType {
|
||||||
|
|
||||||
public static class PathType extends ExternalEditorType {
|
public LinuxPathType(String id, String command) {
|
||||||
|
super(id, command);
|
||||||
private final String command;
|
|
||||||
|
|
||||||
public PathType(String id, String command) {
|
|
||||||
super(id);
|
|
||||||
this.command = command;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -138,30 +120,14 @@ public abstract class ExternalEditorType implements PrefsChoiceValue {
|
||||||
var list = ShellTypes.getPlatformDefault().executeCommandListWithShell(command + " \"" + file + "\"");
|
var list = ShellTypes.getPlatformDefault().executeCommandListWithShell(command + " \"" + file + "\"");
|
||||||
new ProcessBuilder(list).start();
|
new ProcessBuilder(list).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAvailable() {
|
|
||||||
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
|
||||||
return pc.executeBooleanSimpleCommand(pc.getShellType().getWhichCommand(command));
|
|
||||||
} catch (Exception e) {
|
|
||||||
ErrorEvent.fromThrowable(e).omit().handle();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public abstract static class WindowsFullPathType extends ExternalApplicationType.WindowsFullPathType implements ExternalEditorType {
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.LINUX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class WindowsFullPathType extends ExternalEditorType {
|
|
||||||
|
|
||||||
public WindowsFullPathType(String id) {
|
public WindowsFullPathType(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Optional<Path> determinePath();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(Path file) throws Exception {
|
public void launch(Path file) throws Exception {
|
||||||
var path = determinePath();
|
var path = determinePath();
|
||||||
|
@ -171,64 +137,28 @@ public abstract class ExternalEditorType implements PrefsChoiceValue {
|
||||||
|
|
||||||
ApplicationHelper.executeLocalApplication(List.of(path.get().toString(), file.toString()));
|
ApplicationHelper.executeLocalApplication(List.of(path.get().toString(), file.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.WINDOWS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
var path = determinePath();
|
|
||||||
return path.isPresent() && Files.exists(path.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class MacOsFullPathType extends ExternalEditorType {
|
|
||||||
|
|
||||||
public MacOsFullPathType(String id) {
|
|
||||||
super(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Path determinePath();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void launch(Path file) throws Exception {
|
|
||||||
var path = determinePath();
|
|
||||||
ApplicationHelper.executeLocalApplication(List.of("open", path.toString(), file.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.MAC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
var path = determinePath();
|
|
||||||
return Files.exists(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final List<ExternalEditorType> WINDOWS_EDITORS = List.of(VSCODE, NOTEPADPLUSPLUS_WINDOWS, NOTEPAD);
|
public static final List<ExternalEditorType> WINDOWS_EDITORS = List.of(VSCODE, NOTEPADPLUSPLUS_WINDOWS, NOTEPAD);
|
||||||
public static final List<PathType> LINUX_EDITORS =
|
public static final List<LinuxPathType> LINUX_EDITORS =
|
||||||
List.of(VSCODE_LINUX, NOTEPADPLUSPLUS_LINUX, KATE, GEDIT, PLUMA, LEAFPAD, MOUSEPAD);
|
List.of(VSCODE_LINUX, NOTEPADPLUSPLUS_LINUX, KATE, GEDIT, PLUMA, LEAFPAD, MOUSEPAD);
|
||||||
public static final List<ExternalEditorType> MACOS_EDITORS =
|
public static final List<ExternalEditorType> MACOS_EDITORS =
|
||||||
List.of(VSCODE_MACOS, SUBLIME_MACOS, NOTEPADPP_MACOS, TEXT_EDIT);
|
List.of(VSCODE_MACOS, SUBLIME_MACOS, TEXT_EDIT);
|
||||||
|
|
||||||
public static final List<ExternalEditorType> ALL = new ArrayList<>();
|
public static final List<ExternalEditorType> ALL = ((Supplier<List<ExternalEditorType>>) () -> {
|
||||||
static {
|
var all = new ArrayList<ExternalEditorType>();
|
||||||
if (OsType.getLocal().equals(OsType.WINDOWS)) {
|
if (OsType.getLocal().equals(OsType.WINDOWS)) {
|
||||||
ALL.addAll(WINDOWS_EDITORS);
|
all.addAll(WINDOWS_EDITORS);
|
||||||
}
|
}
|
||||||
if (OsType.getLocal().equals(OsType.LINUX)) {
|
if (OsType.getLocal().equals(OsType.LINUX)) {
|
||||||
ALL.addAll(LINUX_EDITORS);
|
all.addAll(LINUX_EDITORS);
|
||||||
}
|
}
|
||||||
if (OsType.getLocal().equals(OsType.MAC)) {
|
if (OsType.getLocal().equals(OsType.MAC)) {
|
||||||
ALL.addAll(MACOS_EDITORS);
|
all.addAll(MACOS_EDITORS);
|
||||||
}
|
|
||||||
ALL.add(CUSTOM);
|
|
||||||
}
|
}
|
||||||
|
all.add(CUSTOM);
|
||||||
|
return all;
|
||||||
|
}).get();
|
||||||
|
|
||||||
public static void detectDefault() {
|
public static void detectDefault() {
|
||||||
var typeProperty = AppPrefs.get().externalEditor;
|
var typeProperty = AppPrefs.get().externalEditor;
|
||||||
|
|
|
@ -102,7 +102,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
|
|
||||||
public static final TerminalType ITERM2 = new ITerm2Type();
|
public static final TerminalType ITERM2 = new ITerm2Type();
|
||||||
|
|
||||||
public static final TerminalType WARP = new MacType("proc.warp", "Warp");
|
public static final TerminalType WARP = new WarpType();
|
||||||
|
|
||||||
public static final TerminalType CUSTOM = new TerminalType("app.custom") {
|
public static final TerminalType CUSTOM = new TerminalType("app.custom") {
|
||||||
|
|
||||||
|
@ -130,9 +130,15 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final List<TerminalType> ALL = List.of(
|
public static final List<TerminalType> ALL = List.of(
|
||||||
WINDOWS_TERMINAL, POWERSHELL, CMD,
|
WINDOWS_TERMINAL,
|
||||||
KONSOLE, XFCE, GNOME_TERMINAL,
|
POWERSHELL,
|
||||||
WARP, ITERM2, MACOS_TERMINAL,
|
CMD,
|
||||||
|
KONSOLE,
|
||||||
|
XFCE,
|
||||||
|
GNOME_TERMINAL,
|
||||||
|
WARP,
|
||||||
|
ITERM2,
|
||||||
|
MACOS_TERMINAL,
|
||||||
CUSTOM)
|
CUSTOM)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(terminalType -> terminalType.isSelectable())
|
.filter(terminalType -> terminalType.isSelectable())
|
||||||
|
@ -140,7 +146,9 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
|
|
||||||
public static TerminalType getDefault() {
|
public static TerminalType getDefault() {
|
||||||
return ALL.stream()
|
return ALL.stream()
|
||||||
.filter(terminalType -> terminalType.isAvailable()).findFirst().orElse(null);
|
.filter(terminalType -> terminalType.isAvailable())
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
@ -189,7 +197,8 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
@Override
|
@Override
|
||||||
public void launch(String name, String command) throws Exception {
|
public void launch(String name, String command) throws Exception {
|
||||||
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
var cmd = String.format("""
|
var cmd = String.format(
|
||||||
|
"""
|
||||||
osascript - "$@" <<EOF
|
osascript - "$@" <<EOF
|
||||||
on run argv
|
on run argv
|
||||||
tell application "iTerm"
|
tell application "iTerm"
|
||||||
|
@ -197,7 +206,46 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
set new_term to (create window with profile "Default" command "%s")
|
set new_term to (create window with profile "Default" command "%s")
|
||||||
end tell
|
end tell
|
||||||
end run
|
end run
|
||||||
EOF""", command);
|
EOF""",
|
||||||
|
command);
|
||||||
|
pc.executeSimpleCommand(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelectable() {
|
||||||
|
return OsType.getLocal().equals(OsType.MAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return Files.exists(Path.of("/Applications/iTerm2.app"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class WarpType extends TerminalType {
|
||||||
|
|
||||||
|
public WarpType() {
|
||||||
|
super("proc.warp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void launch(String name, String command) throws Exception {
|
||||||
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
|
var cmd = String.format(
|
||||||
|
"""
|
||||||
|
osascript - "$@" <<EOF
|
||||||
|
tell application "Warp" to activate'
|
||||||
|
sudo osascript -e 'tell application "System Events" to tell process "Warp" to keystroke "t" using command down'
|
||||||
|
sleep 1
|
||||||
|
sudo osascript -e 'tell application "System Events"
|
||||||
|
tell process "Warp"
|
||||||
|
keystroke "%s"
|
||||||
|
key code 36
|
||||||
|
end tell
|
||||||
|
end tell
|
||||||
|
EOF""",
|
||||||
|
command);
|
||||||
pc.executeSimpleCommand(cmd);
|
pc.executeSimpleCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue