Last active
May 16, 2018 17:25
-
-
Save ahti/8cb4f5f6986e4e081a4bcf621714620b to your computer and use it in GitHub Desktop.
A script for an Alfred qalc workflow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
/*/../usr/bin/true | |
source="$0" | |
compiled="$0".cache | |
if [[ "$source" -nt "$compiled" ]]; then | |
swiftc "$source" -o "$compiled" || exit | |
fi | |
"$compiled" "$@" | |
exit | |
*/ | |
import Foundation | |
extension String { | |
subscript(value: PartialRangeUpTo<Int>) -> Substring { | |
get { | |
return self[..<index(startIndex, offsetBy: value.upperBound)] | |
} | |
} | |
subscript(value: PartialRangeThrough<Int>) -> Substring { | |
get { | |
return self[...index(startIndex, offsetBy: value.upperBound)] | |
} | |
} | |
subscript(value: PartialRangeFrom<Int>) -> Substring { | |
get { | |
return self[index(startIndex, offsetBy: value.lowerBound)...] | |
} | |
} | |
} | |
public struct StderrOutputStream: TextOutputStream { | |
public mutating func write(_ string: String) { fputs(string, stderr) } | |
} | |
public var STDERR = StderrOutputStream() | |
let ENV = ProcessInfo.processInfo.environment | |
struct Item: Encodable { | |
var valid: Bool | |
var uid: String | |
var title: String | |
var subtitle: String? | |
var arg: String? | |
var text: Text? | |
struct Text: Encodable { | |
var copy: String | |
var largetype: String | |
} | |
} | |
struct Response: Encodable { | |
let items: [Item] | |
} | |
func respond(_ items: [Item]) throws { | |
let d = try JSONEncoder().encode(Response(items: items)) | |
let s = String(decoding: d, as: UTF8.self) | |
print(s) | |
} | |
func respond(_ item: Item) throws { | |
try respond([item]) | |
} | |
func system(stdin: Data? = nil, _ cmd: String...) throws -> String { | |
let p = Process() | |
p.executableURL = URL(fileURLWithPath: cmd[0]) | |
p.arguments = Array(cmd[1...]) | |
p.standardOutput = Pipe() | |
if let d = stdin { | |
let input = Pipe() | |
p.standardInput = input | |
input.fileHandleForWriting.write(d) | |
input.fileHandleForWriting.closeFile() | |
} | |
try p.run() | |
p.waitUntilExit() | |
let d = (p.standardOutput as! Pipe).fileHandleForReading.readDataToEndOfFile() | |
return String(decoding: d, as: UTF8.self) | |
} | |
var q = CommandLine.arguments[1] | |
if q == "" { q = "0" } | |
print(q, to: &STDERR) | |
struct QalcError: LocalizedError { | |
let message: String | |
var errorDescription: String? { return message } | |
} | |
do { | |
let history = ((try? String(contentsOfFile: ENV["alfred_workflow_data"]! + "/history").components(separatedBy: "\n")) ?? []).enumerated() | |
let varsString = history.map { "variable r\($0.offset) \($0.element)" }.joined(separator: "\n") | |
let vars = Data(varsString.utf8) | |
print(varsString, to: &STDERR) | |
let out = try system(stdin: vars, "/usr/local/bin/qalc", "+u8", "-f", "-", "-s", "update_exchange_rates 1days", q) | |
print(out, to: &STDERR) | |
let lines = out.components(separatedBy: "\n") | |
let errorPrefix = "error: " | |
let warningPrefix = "warning: " | |
let result: String | |
let warning: String? | |
if out.starts(with: errorPrefix) { | |
throw QalcError(message: String(lines[0][errorPrefix.count...])) | |
} else if out.starts(with: warningPrefix) { | |
warning = String(lines[0][warningPrefix.count...]) | |
result = lines[1] | |
} else { | |
warning = nil | |
result = lines[0] | |
} | |
let resultValue = result.components(separatedBy: " = ")[1] | |
let resultItem = Item( | |
valid: true, | |
uid: "swift-result", | |
title: result, | |
subtitle: warning, | |
arg: resultValue, | |
text: Item.Text( | |
copy: resultValue, | |
largetype: result | |
) | |
) | |
let historyItems = history.map { | |
Item( | |
valid: true, | |
uid: UUID().uuidString, | |
title: "\($0.element)", | |
subtitle: "r\($0.offset) - history", | |
arg: $0.element, | |
text: Item.Text( | |
copy: resultValue, | |
largetype: resultValue | |
) | |
) | |
} | |
try respond([resultItem] + historyItems) | |
} catch { | |
print("\(error)", to: &STDERR) | |
try! respond( | |
Item( | |
valid: false, | |
uid: "rip", | |
title: "\(error.localizedDescription)", | |
subtitle: "error", | |
arg: nil, | |
text: nil | |
) | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment