vChewing-macOS/Packages/vChewing_CocoaExtension/Sources/CocoaExtension/CocoaExtension_Misc.swift

171 lines
5.3 KiB
Swift

// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
import SwiftExtension
// MARK: - NSMutableString extension
public extension NSMutableString {
var localized: String { NSLocalizedString(description, comment: "") }
}
// MARK: - NSRect Extension
public extension NSRect {
static var seniorTheBeast: NSRect {
NSRect(x: 0.0, y: 0.0, width: 0.114, height: 0.514)
}
}
// MARK: - Shell Extension
public extension NSApplication {
static func shell(_ command: String) throws -> String {
let task = Process()
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
if #available(macOS 10.13, *) {
task.executableURL = URL(fileURLWithPath: "/bin/zsh")
} else {
task.launchPath = "/bin/zsh"
}
task.standardInput = nil
if #available(macOS 10.13, *) {
try task.run()
} else {
task.launch()
}
var output = ""
do {
let data = try pipe.fileHandleForReading.readToEnd()
if let data = data, let str = String(data: data, encoding: .utf8) {
output.append(str)
}
} catch {
return ""
}
return output
}
}
public extension NSApplication {
// MARK: - System Dark Mode Status Detector.
static var isDarkMode: Bool {
if #unavailable(macOS 10.14) { return false }
if #available(macOS 10.15, *) {
let appearanceDescription = NSApp.effectiveAppearance.debugDescription
.lowercased()
return appearanceDescription.contains("dark")
} else if let appleInterfaceStyle = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") {
return appleInterfaceStyle.lowercased().contains("dark")
}
return false
}
// MARK: - Tell whether this IME is running with Root privileges.
static var isSudoMode: Bool {
NSUserName() == "root"
}
}
// MARK: - Real Home Dir for Sandboxed Apps
public extension FileManager {
static let realHomeDir = URL(
fileURLWithFileSystemRepresentation: getpwuid(getuid()).pointee.pw_dir, isDirectory: true, relativeTo: nil
)
}
// MARK: - Trash a file if it exists.
public extension FileManager {
@discardableResult static func trashTargetIfExists(_ path: String) -> Bool {
do {
if FileManager.default.fileExists(atPath: path) {
//
try FileManager.default.trashItem(
at: URL(fileURLWithPath: path), resultingItemURL: nil
)
} else {
NSLog("Item doesn't exist: \(path)")
}
} catch let error as NSError {
NSLog("Failed from removing this object: \(path) || Error: \(error)")
return false
}
return true
}
}
// MARK: - Memory Footprint Calculator
// Ref: https://developer.apple.com/forums/thread/105088?answerId=357415022#357415022
public extension NSApplication {
/// The memory footprint of the current application in bytes.
static var memoryFootprint: UInt64? {
// The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too
// complex for the Swift C importer, so we have to define them ourselves.
let tskVMInfoCount = mach_msg_type_number_t(
MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)
let tskVMInfoRev1Count = mach_msg_type_number_t(
MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout<integer_t>.size)
var info = task_vm_info_data_t()
var count = tskVMInfoCount
let kr = withUnsafeMutablePointer(to: &info) { infoPtr in
infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in
task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count)
}
}
guard kr == KERN_SUCCESS, count >= tskVMInfoRev1Count else { return nil }
return info.phys_footprint as UInt64
}
}
// MARK: - Check whether current date is the given date.
public extension Date {
/// Check whether current date is the given date.
/// - Parameter dateDigits: `yyyyMMdd`, 8-digit integer. If only `MMdd`, then the year will be the current year.
/// - Returns: The result. Will return false if the given dateDigits is invalid.
static func isTodayTheDate(from dateDigits: Int) -> Bool {
let currentYear = Self.currentYear
var dateDigits = dateDigits
let strDateDigits = dateDigits.description
switch strDateDigits.count {
case 3, 4: dateDigits = currentYear * 10000 + dateDigits
case 8:
if let theHighest = strDateDigits.first, "12".contains(theHighest) { break }
return false
default: return false
}
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd"
var calendar = NSCalendar.current
calendar.timeZone = TimeZone.current
let components = calendar.dateComponents([.day, .month, .year], from: Date())
if let a = calendar.date(from: components), let b = formatter.date(from: dateDigits.description), a == b {
return true
}
return false
}
static var currentYear: Int {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy"
return (Int(formatter.string(from: Date())) ?? 1970)
}
}