mirror of
https://github.com/BigMarc/grammargem.git
synced 2026-10-13 17:01:55 +02:00
- Added LiveMonitor class to scan text areas in the frontmost window for grammar and spelling issues. - Introduced DetectedField struct to represent text areas with issues, including suggestions for corrections. - Implemented functionality to apply corrections and dismiss suggestions. - Added Permissions class to manage Accessibility permissions required for monitoring. - Created SnippetStore for managing text-expansion snippets, including persistence to UserDefaults. - Developed TextCapture class to read and write text from the frontmost application using Accessibility API and clipboard fallback. - Implemented TextFieldScanner to traverse the Accessibility tree and collect editable text elements. - Added TextReplacementCoordinator to orchestrate the text correction process. - Integrated UpdaterManager for handling application updates using Sparkle. - Created comprehensive unit tests for various components, including grammar corrections and entitlement checks.
62 lines
2.3 KiB
Swift
62 lines
2.3 KiB
Swift
import Foundation
|
|
import AppKit
|
|
import Carbon.HIToolbox
|
|
|
|
/// A user-configurable keyboard shortcut: a key code plus Carbon modifier mask,
|
|
/// with a human-readable display string (e.g. "⌘;").
|
|
struct HotkeyCombo: Codable, Equatable {
|
|
var keyCode: UInt32
|
|
var carbonModifiers: UInt32
|
|
var display: String
|
|
|
|
static let defaultFix = HotkeyCombo(
|
|
keyCode: AppConfig.Hotkey.defaultKeyCode,
|
|
carbonModifiers: AppConfig.Hotkey.defaultModifiers,
|
|
display: "⌘;")
|
|
|
|
static let defaultAsk = HotkeyCombo(
|
|
keyCode: AppConfig.Hotkey.askKeyCode,
|
|
carbonModifiers: AppConfig.Hotkey.askModifiers,
|
|
display: "⌘'")
|
|
|
|
/// Build a combo from a recorded key-down event. Requires at least one
|
|
/// modifier so the shortcut is safe to register globally.
|
|
static func from(event: NSEvent) -> HotkeyCombo? {
|
|
let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
|
|
var carbon: UInt32 = 0
|
|
if flags.contains(.command) { carbon |= UInt32(cmdKey) }
|
|
if flags.contains(.shift) { carbon |= UInt32(shiftKey) }
|
|
if flags.contains(.option) { carbon |= UInt32(optionKey) }
|
|
if flags.contains(.control) { carbon |= UInt32(controlKey) }
|
|
guard carbon != 0 else { return nil }
|
|
|
|
let symbol = keySymbol(for: event)
|
|
var display = ""
|
|
if flags.contains(.control) { display += "⌃" }
|
|
if flags.contains(.option) { display += "⌥" }
|
|
if flags.contains(.shift) { display += "⇧" }
|
|
if flags.contains(.command) { display += "⌘" }
|
|
display += symbol
|
|
return HotkeyCombo(keyCode: UInt32(event.keyCode), carbonModifiers: carbon, display: display)
|
|
}
|
|
|
|
private static func keySymbol(for event: NSEvent) -> String {
|
|
switch Int(event.keyCode) {
|
|
case kVK_Space: return "Space"
|
|
case kVK_Return: return "↩"
|
|
case kVK_Tab: return "⇥"
|
|
case kVK_Delete: return "⌫"
|
|
case kVK_Escape: return "⎋"
|
|
case kVK_LeftArrow: return "←"
|
|
case kVK_RightArrow: return "→"
|
|
case kVK_UpArrow: return "↑"
|
|
case kVK_DownArrow: return "↓"
|
|
default:
|
|
if let chars = event.charactersIgnoringModifiers, !chars.isEmpty {
|
|
return chars.uppercased()
|
|
}
|
|
return "key"
|
|
}
|
|
}
|
|
}
|