mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-11-02 19:28:36 +00:00
* Updated README Added explanation for missing parameters (background, title and image) * Implemented changable icons for AppleScriptTouchBarItem AppleScriptTouchBarItem now allow to specify any number of icons which can be changed from the script. You cannot change icon from touch event. To change icon, you need to return array from your script with 2 values - title and icn name. More info in readme * Fixed error related to ShellButton When you execute Process from swift you cannot relay solely on pipe.fileHandleForReading.readDataToEndOfFile() Sometimes when I close notebook I get exception saying that you cannot access process.terminationStatus variable while process is running. Apparently it seems that this call can be finished when OS X put disks into sleep mode(?) What I did: 1. Added Process.waitUntilExit() call 2. Added timeout (equal to the update interval) Co-authored-by: Fedor Zaitsev <lobster@Fedors-MacBook-Pro.local>
89 lines
3.4 KiB
Swift
89 lines
3.4 KiB
Swift
//
|
|
// ShellScriptTouchBarItem.swift
|
|
// MTMR
|
|
//
|
|
// Created by bobr on 08/08/2019.
|
|
// Copyright © 2019 Anton Palgunov. All rights reserved.
|
|
//
|
|
import Foundation
|
|
|
|
class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
|
|
private let interval: TimeInterval
|
|
private let source: String
|
|
private var forceHideConstraint: NSLayoutConstraint!
|
|
|
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
|
|
self.interval = interval
|
|
self.source = source.string ?? "echo No \"source\""
|
|
super.init(identifier: identifier, title: "⏳")
|
|
|
|
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
|
|
|
DispatchQueue.shellScriptQueue.async {
|
|
self.refreshAndSchedule()
|
|
}
|
|
}
|
|
|
|
required init?(coder _: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func refreshAndSchedule() {
|
|
// Execute script and get result
|
|
let scriptResult = execute(source)
|
|
|
|
// Apply returned text attributes (if they were returned) to our result string
|
|
let helper = AMR_ANSIEscapeHelper.init()
|
|
helper.defaultStringColor = NSColor.white
|
|
helper.font = "1".defaultTouchbarAttributedString.attribute(.font, at: 0, effectiveRange: nil) as? NSFont
|
|
let title = NSMutableAttributedString.init(attributedString: helper.attributedString(withANSIEscapedString: scriptResult) ?? NSAttributedString(string: ""))
|
|
title.addAttributes([.baselineOffset: 1], range: NSRange(location: 0, length: title.length))
|
|
let newBackgoundColor: NSColor? = title.length != 0 ? title.attribute(.backgroundColor, at: 0, effectiveRange: nil) as? NSColor : nil
|
|
|
|
// Update UI
|
|
DispatchQueue.main.async { [weak self, newBackgoundColor] in
|
|
if (newBackgoundColor != self?.backgroundColor) { // performance optimization because of reinstallButton
|
|
self?.backgroundColor = newBackgoundColor
|
|
}
|
|
self?.attributedTitle = title
|
|
self?.forceHideConstraint.isActive = scriptResult == ""
|
|
}
|
|
|
|
// Schedule next update
|
|
DispatchQueue.shellScriptQueue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
|
self?.refreshAndSchedule()
|
|
}
|
|
}
|
|
|
|
func execute(_ command: String) -> String {
|
|
let task = Process()
|
|
task.launchPath = "/bin/bash"
|
|
task.arguments = ["-c", command]
|
|
|
|
let pipe = Pipe()
|
|
task.standardOutput = pipe
|
|
|
|
// kill process if it is over update interval
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + interval) { [weak task] in
|
|
task?.terminate()
|
|
}
|
|
|
|
task.launch()
|
|
|
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
|
var output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? ?? ""
|
|
|
|
//always wait until task end or you can catch "task still running" error while accessing task.terminationStatus variable
|
|
task.waitUntilExit()
|
|
if (output == "" && task.terminationStatus != 0) {
|
|
output = "error"
|
|
}
|
|
|
|
return output.replacingOccurrences(of: "\\n+$", with: "", options: .regularExpression)
|
|
}
|
|
}
|
|
|
|
extension DispatchQueue {
|
|
static let shellScriptQueue = DispatchQueue(label: "mtmr.shellscript")
|
|
}
|