Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bottle Terminal button #843

Merged
merged 5 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions Whisky/Extensions/Bottle+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,40 @@
import Foundation
import AppKit
import WhiskyKit
import os.log

extension Bottle {
func openCDrive() {
NSWorkspace.shared.open(url.appending(path: "drive_c"))
}

func openTerminal() {
let whiskyCmdURL = Bundle.main.url(forResource: "WhiskyCmd", withExtension: nil)
if let whiskyCmdURL = whiskyCmdURL {
let whiskyCmd = whiskyCmdURL.path(percentEncoded: false)
let cmd = "eval \\\"$(\\\"\(whiskyCmd)\\\" shellenv \\\"\(settings.name)\\\")\\\""

let script = """
tell application "Terminal"
activate
do script "\(cmd)"
end tell
"""

Task.detached(priority: .userInitiated) {
var error: NSDictionary?
guard let appleScript = NSAppleScript(source: script) else { return }
appleScript.executeAndReturnError(&error)

if let error = error {
Logger.wineKit.error("Failed to run terminal script \(error)")
guard let description = error["NSAppleScriptErrorMessage"] as? String else { return }
await self.showRunError(message: String(describing: description))
}
}
}
}

@discardableResult
func getStartMenuPrograms() -> [Program] {
let globalStartMenu = url
Expand Down Expand Up @@ -174,4 +202,15 @@ extension Bottle {
func rename(newName: String) {
settings.name = newName
}

@MainActor private func showRunError(message: String) {
let alert = NSAlert()
alert.messageText = String(localized: "alert.message")
alert.informativeText = String(localized: "alert.info")
+ " \(self.url.lastPathComponent): "
+ message
alert.alertStyle = .critical
alert.addButton(withTitle: String(localized: "button.ok"))
alert.runModal()
}
}
13 changes: 12 additions & 1 deletion Whisky/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -2327,6 +2327,17 @@
}
}
},
"button.terminal" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terminal"
}
}
}
},
"button.unpin" : {
"localizations" : {
"da" : {
Expand Down Expand Up @@ -16655,4 +16666,4 @@
}
},
"version" : "1.0"
}
}
3 changes: 3 additions & 0 deletions Whisky/Views/Bottle/BottleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ struct BottleView: View {
Button("button.cDrive") {
bottle.openCDrive()
}
Button("button.terminal") {
bottle.openTerminal()
}
Button("button.winetricks") {
showWinetricksSheet.toggle()
}
Expand Down
22 changes: 21 additions & 1 deletion WhiskyCmd/Main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ struct Whisky: ParsableCommand {
// Export.self,
Delete.self,
Remove.self,
Run.self
Run.self,
Shellenv.self
/*Install.self,
Uninstall.self*/])
}
Expand Down Expand Up @@ -178,6 +179,25 @@ extension Whisky {
}
}

struct Shellenv: ParsableCommand {
static var configuration = CommandConfiguration(abstract: "Prints export statements for a Bottle for eval.")

@Argument var bottleName: String

mutating func run() throws {
var bottlesList = BottleData()
let bottles = bottlesList.loadBottles()

guard let bottle = bottles.first(where: { $0.settings.name == bottleName }) else {
throw ValidationError("A bottle with that name doesn't exist.")
}

let envCmd = Wine.generateTerminalEnvironmentCommand(bottle: bottle)
print(envCmd)

}
}

struct Install: ParsableCommand {
static var configuration = CommandConfiguration(abstract: "Install Whisky dependencies.")

Expand Down
26 changes: 25 additions & 1 deletion WhiskyKit/Sources/WhiskyKit/Wine/Wine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,36 @@ public class Wine {
var wineCmd = "\(wineBinary.esc) start /unix \(url.path(percentEncoded: false)) \(args)"
let env = constructWineEnvironment(for: bottle, environment: environment)
for environment in env {
wineCmd = "\(environment.key)=\(environment.value) " + wineCmd
wineCmd = "\(environment.key)=\"\(environment.value)\" " + wineCmd
}

return wineCmd
}

public static func generateTerminalEnvironmentCommand(bottle: Bottle) -> String {
var cmd = """
export PATH=\"\(GPTKInstaller.binFolder.path):$PATH\"
export WINE=\"wine64\"
alias wine=\"wine64\"
alias winecfg=\"wine64 winecfg\"
alias msiexec=\"wine64 msiexec\"
alias regedit=\"wine64 regedit\"
alias regsvr32=\"wine64 regsvr32\"
alias wineboot=\"wine64 wineboot\"
alias wineconsole=\"wine64 wineconsole\"
alias winedbg=\"wine64 winedbg\"
alias winefile=\"wine64 winefile\"
alias winepath=\"wine64 winepath\"
"""

let env = constructWineEnvironment(for: bottle, environment: constructWineEnvironment(for: bottle))
for environment in env {
cmd += "\nexport \(environment.key)=\"\(environment.value)\""
}

return cmd
}

/// Run a `wineserver` command with the given arguments and return the output result
private static func runWineserver(_ args: [String], bottle: Bottle) async throws -> String {
var result: [ProcessOutput] = []
Expand Down