Skip to content

Instantly share code, notes, and snippets.

@ahti
Last active May 16, 2018 17:25
Show Gist options
  • Save ahti/8cb4f5f6986e4e081a4bcf621714620b to your computer and use it in GitHub Desktop.
Save ahti/8cb4f5f6986e4e081a4bcf621714620b to your computer and use it in GitHub Desktop.
A script for an Alfred qalc workflow
#!/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