krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Sources/Orgstar/CaptureIntent.swift

778058aafc7ddacee4a613b1da87c60aa0c8e113
orgstar/Sources/Orgstar/CaptureIntent.swift history · blame · raw

50 lines · 2259 bytes

4 symbols in this file
 1import AppIntents
 2import AppKit
 3import OrgApp
 4import OrgCore
 5
 6/// Shortcuts' "Capture to Orgstar": files text with a capture template without the capture
 7/// window. Prompts in the template take their defaults.
 8struct CaptureIntent: AppIntent {
 9    static let title: LocalizedStringResource = "Capture to Orgstar"
10    static let description = IntentDescription("Files text with one of your capture templates.")
11
12    @Parameter(title: "Text")
13    var text: String
14
15    @Parameter(title: "Template Key", description: "A template's key in capture.toml; the first template when empty.")
16    var template: String?
17
18    /// The app's models, once its window is up.
19    @MainActor static var environment: (workspace: WorkspaceModel, session: DocumentSession, clock: ClockModel, commands: AppCommands)?
20
21    struct Failure: Error, CustomLocalizedStringResourceConvertible {
22        let message: String
23        var localizedStringResource: LocalizedStringResource { "\(message)" }
24    }
25
26    @MainActor
27    func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog {
28        // Launched for the intent, the window sets the models up shortly.
29        for _ in 0..<50 where Self.environment == nil { try? await Task.sleep(for: .milliseconds(100)) }
30        guard let (workspace, session, clock, commands) = Self.environment else { throw Failure(message: "Orgstar isn't ready") }
31        let placed = session.capture(
32            text, templateKey: template, templates: CaptureTemplates.load().templates, workspace: workspace, clock: clock,
33            clipboard: NSPasteboard.general.string(forType: .string) ?? "", userName: NSFullUserName()
34        )
35        switch placed {
36        case .failure(let error):
37            throw Failure(message: error.message)
38        case .success(let chosen):
39            let message = "Captured to \(CaptureView.target(chosen))"
40            commands.show(message)
41            return .result(value: message, dialog: "\(message)")
42        }
43    }
44}
45
46struct OrgstarShortcuts: AppShortcutsProvider {
47    static var appShortcuts: [AppShortcut] {
48        AppShortcut(intent: CaptureIntent(), phrases: ["Capture to \(.applicationName)"], shortTitle: "Capture", systemImageName: "tray.and.arrow.down")
49    }
50}