mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-11-06 21:00:07 +01:00
✨ Ensure editor binaries exist or notify user (#67)
This commit is contained in:
@@ -12,6 +12,10 @@ extension String {
|
|||||||
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
|
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func localized(_ args: CVarArg...) -> String {
|
||||||
|
String(format: self.localized, arguments: args)
|
||||||
|
}
|
||||||
|
|
||||||
func countInstances(of stringToFind: String) -> Int {
|
func countInstances(of stringToFind: String) -> Int {
|
||||||
if (stringToFind.isEmpty) {
|
if (stringToFind.isEmpty) {
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -16,74 +16,103 @@ class Editor {
|
|||||||
/// Name of the editor. Used for display purposes.
|
/// Name of the editor. Used for display purposes.
|
||||||
let name: String
|
let name: String
|
||||||
|
|
||||||
/// Path to check whether the application is actually installed.
|
/// Paths to check whether the application is actually installed.
|
||||||
/// This was previously called `path` but the new variable name is a bit more clear.
|
/// If the app finds any of these, the app is considered installed.
|
||||||
/// To be clear, this is *not* the path to the actual binary!
|
let pathsToVerifyInstalled: [String]
|
||||||
let pathToVerifyInstalled: String
|
|
||||||
|
|
||||||
/// Callback that is executed to open a particular folder. Can be different from the installation path or the procedure required to determine whether the application is installed.
|
/// Path to the binary that actually opens the directory.
|
||||||
|
let pathToBinary: String
|
||||||
|
|
||||||
|
/// Instruction that needs to be followed in order to ensure that the app can open with this editor.
|
||||||
|
var missingBinaryInstruction: String? = nil
|
||||||
|
|
||||||
|
/// Callback that is executed to open a particular folder.
|
||||||
|
/// Must open the directory in the requested app, usually by using `pathToBinary`.
|
||||||
@objc let openCallback: (String) -> Void
|
@objc let openCallback: (String) -> Void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
- Parameter name: Name of the editor.
|
- Parameter name: Name of the editor.
|
||||||
- Parameter path: File to verify, if this file exists here the app is considered present on the system.
|
- Parameter installPath: Files to verify, if any file exists here the app is considered present on the system.
|
||||||
|
- Parameter binaryPath: Additional file that is used to open a specific path.
|
||||||
- Parameter open: Callback used to open a specific directory in the editor in question.
|
- Parameter open: Callback used to open a specific directory in the editor in question.
|
||||||
|
- Parameter instruction: Instruction for end user that needs to be followed in order to ensure the `binaryPath exists.
|
||||||
*/
|
*/
|
||||||
init(name: String, path: String, open: @escaping ((String) -> Void)) {
|
init(name: String, installPaths: [String], binaryPath: String, open: @escaping ((String) -> Void), instruction: String? = nil) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.pathToVerifyInstalled = path.replacingOccurrences(of: " ", with: "\\ ")
|
self.pathsToVerifyInstalled = installPaths.map({ path in
|
||||||
|
return path.replacingOccurrences(of: " ", with: "\\ ")
|
||||||
|
})
|
||||||
|
self.pathToBinary = binaryPath.replacingOccurrences(of: " ", with: "\\ ")
|
||||||
self.openCallback = open
|
self.openCallback = open
|
||||||
|
self.missingBinaryInstruction = instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Attempt to open a specific directory in the editor of choice. This will open the editor if it isn't open yet.
|
Attempt to open a specific directory in the editor of choice.
|
||||||
|
This will open the editor if it isn't open yet.
|
||||||
*/
|
*/
|
||||||
@objc public func openDirectory(file: String) {
|
@objc public func openDirectory(file: String) {
|
||||||
self.openCallback(file)
|
self.openCallback(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Checks if the app is installed. */
|
||||||
|
func isInstalled() -> Bool {
|
||||||
|
self.pathsToVerifyInstalled.map({ path in
|
||||||
|
Shell.fileExists(path)
|
||||||
|
}).contains(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the correct binary required to open directories and/or files exists. */
|
||||||
|
func hasBinary() -> Bool {
|
||||||
|
return Shell.fileExists(self.pathToBinary)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Detect which "editors" are available to open a specific directory.
|
Detect which "editors" are available to open a specific directory.
|
||||||
*/
|
*/
|
||||||
static public func detect() -> [Editor] {
|
static public func detectPresetEditors() -> [Editor] {
|
||||||
return [
|
return [
|
||||||
Editor(
|
Editor(
|
||||||
name: "PhpStorm",
|
name: "PhpStorm",
|
||||||
path: "/Applications/PhpStorm.app/Contents/Info.plist",
|
installPaths: [
|
||||||
|
"~/Applications/JetBrains Toolbox/PhpStorm.app/Contents/Info.plist",
|
||||||
|
"/Applications/PhpStorm.app/Contents/Info.plist",
|
||||||
|
"/usr/local/bin/pstorm"
|
||||||
|
],
|
||||||
|
binaryPath: "/usr/local/bin/pstorm",
|
||||||
open: { path in
|
open: { path in
|
||||||
Shell.run("open -a /Applications/PhpStorm.app \(path)")
|
Shell.run("/usr/local/bin/pstorm \(path)")
|
||||||
}
|
},
|
||||||
),
|
instruction: "editors.pstorm_binary_not_linked.desc".localized
|
||||||
Editor(
|
|
||||||
name: "PhpStorm (via Toolbox)",
|
|
||||||
path: "~/Applications/JetBrains Toolbox/PhpStorm.app/Contents/Info.plist",
|
|
||||||
open: { path in
|
|
||||||
Shell.run("open -a ~/Applications/JetBrains\\ Toolbox/PhpStorm.app \(path)")
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
Editor(
|
Editor(
|
||||||
name: "Visual Studio Code",
|
name: "Visual Studio Code",
|
||||||
path: "/usr/local/bin/code",
|
installPaths: [
|
||||||
|
"/Applications/Visual Studio Code.app/Contents/Info.plist",
|
||||||
|
"/usr/local/bin/code"
|
||||||
|
],
|
||||||
|
binaryPath: "/usr/local/bin/code",
|
||||||
open: { path in
|
open: { path in
|
||||||
Shell.run("/usr/local/bin/code \(path)")
|
Shell.run("/usr/local/bin/code \(path)")
|
||||||
}
|
},
|
||||||
|
instruction: "editors.code_binary_not_linked.desc".localized
|
||||||
),
|
),
|
||||||
Editor(
|
Editor(
|
||||||
name: "Sublime Text",
|
name: "Sublime Text",
|
||||||
path: "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl",
|
installPaths: ["/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"],
|
||||||
|
binaryPath: "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl",
|
||||||
open: { path in
|
open: { path in
|
||||||
Shell.run("/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl \(path)")
|
Shell.run("/Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl \(path)")
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
Editor(
|
Editor(
|
||||||
name: "Sublime Merge",
|
name: "Sublime Merge",
|
||||||
path: "/Applications/Sublime Merge.app/Contents/SharedSupport/bin/smerge",
|
installPaths: ["/Applications/Sublime Merge.app/Contents/SharedSupport/bin/smerge"],
|
||||||
|
binaryPath: "/Applications/Sublime Merge.app/Contents/SharedSupport/bin/smerge",
|
||||||
open: { path in
|
open: { path in
|
||||||
Shell.run("/Applications/Sublime\\ Merge.app/Contents/SharedSupport/bin/smerge \(path)")
|
Shell.run("/Applications/Sublime\\ Merge.app/Contents/SharedSupport/bin/smerge \(path)")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
].filter { editor in
|
].filter { return $0.isInstalled() }
|
||||||
Shell.fileExists(editor.pathToVerifyInstalled)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
var sites: [Valet.Site] = []
|
var sites: [Valet.Site] = []
|
||||||
|
|
||||||
/// Array that contains various editors that might open a particular site directory.
|
/// Array that contains various editors that might open a particular site directory.
|
||||||
var editors: [Editor] = Editor.detect()
|
var editors: [Editor] = Editor.detectPresetEditors()
|
||||||
|
|
||||||
/// String that was last searched for. Empty by default.
|
/// String that was last searched for. Empty by default.
|
||||||
var lastSearchedFor = ""
|
var lastSearchedFor = ""
|
||||||
@@ -303,7 +303,25 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func openWithEditor(sender: EditorMenuItem) {
|
@objc func openWithEditor(sender: EditorMenuItem) {
|
||||||
sender.editor?.openDirectory(file: selectedSite!.absolutePath!)
|
guard let editor = sender.editor else { return }
|
||||||
|
|
||||||
|
if editor.hasBinary() {
|
||||||
|
editor.openDirectory(file: selectedSite!.absolutePath!)
|
||||||
|
} else {
|
||||||
|
Alert.confirm(
|
||||||
|
onWindow: self.view.window!,
|
||||||
|
messageText: "editors.binary_missing.title"
|
||||||
|
.localized(
|
||||||
|
editor.pathToBinary
|
||||||
|
),
|
||||||
|
informativeText: editor.missingBinaryInstruction ?? "",
|
||||||
|
buttonTitle: "editors.alert.try_again".localized,
|
||||||
|
secondButtonTitle: "editors.alert.cancel".localized,
|
||||||
|
onFirstButtonPressed: {
|
||||||
|
self.openWithEditor(sender: sender)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Deinitialization
|
// MARK: - Deinitialization
|
||||||
|
|||||||
@@ -73,6 +73,24 @@
|
|||||||
"site_list.open_with_vs_code" = "Open with Visual Studio Code";
|
"site_list.open_with_vs_code" = "Open with Visual Studio Code";
|
||||||
"site_list.open_with_pstorm" = "Open with PhpStorm";
|
"site_list.open_with_pstorm" = "Open with PhpStorm";
|
||||||
|
|
||||||
|
// EDITORS
|
||||||
|
"editors.binary_missing.title" = "`%@` missing";
|
||||||
|
"editors.alert.try_again" = "Try Again";
|
||||||
|
"editors.alert.cancel" = "Cancel";
|
||||||
|
|
||||||
|
"editors.pstorm_binary_not_linked.desc" =
|
||||||
|
"PHP Monitor makes use of PhpStorm’s launcher to open a specific directory.
|
||||||
|
|
||||||
|
The desired launcher does not seem to be found in the usual location. Please set up the launcher by going to 'Tools > Create command-line launcher' in PhpStorm.
|
||||||
|
|
||||||
|
After this is done, PHP Monitor should be able to open the domain’s folder in PhpStorm.";
|
||||||
|
"editors.code_binary_not_linked.desc" =
|
||||||
|
"PHP Monitor makes use of Visual Studio Code‘s helper binary, `code`, but it seems not to exist on your system.
|
||||||
|
|
||||||
|
You can fix this by selecting 'Install `code` command in PATH' in Visual Studio Code’s command palette.
|
||||||
|
|
||||||
|
After this is done, PHP Monitor should be able to open the domain’s folder in PhpStorm.";
|
||||||
|
|
||||||
// PREFERENCES
|
// PREFERENCES
|
||||||
|
|
||||||
"prefs.title" = "PHP Monitor";
|
"prefs.title" = "PHP Monitor";
|
||||||
|
|||||||
Reference in New Issue
Block a user