Well, this has been a fascinating project: I was looking back at my AppleScript Jekyll Assistant and thinking that “this is so much more complicated than it neeeds to be”.

I had used the Swift Argument Parser before and had toyed with writing command line scripts in Swift but was a bit daunted. By the documentation. So ChatGPT came to the rescue and helped me write the following. So AI has definitely been a “productivity enhancer” in this case. I know my way around but am not an expert in the APIs that I rarely use. And getting the regular expressions just right is something that usually would have taken me a lot of time. So ChatGPT helped me with the important and unfamiliar detail and I think you’ll agree we came up with a pretty elegant solution.

#!/usr/bin/env swift

import Foundation
import ArgumentParser

struct CLI: ParsableCommand {
    static let configuration = CommandConfiguration(
        abstract: "A command-line tool that processes a category and description and generates a markdown file."
    )

    @Option(name: [.short, .long], help: "The category of the item.")
    var category: String

    @Option(name: [.short, .long], help: "The description of the item.")
    var description: String

    @Option(name: [.short, .long], help: "Optional: directory to write output markdown file. Overrides and sets persistent path.")
    var outputPath: String?

    func run() throws {
        let fileManager = FileManager.default
        let homeDir = fileManager.homeDirectoryForCurrentUser
        let configURL = homeDir.appendingPathComponent(".mycli_config")

        // Determine target directory for output
        let targetDirectory: String
        if let providedPath = outputPath {
            // Expand ~ and create directory
            let expanded = (providedPath as NSString).expandingTildeInPath
            try fileManager.createDirectory(atPath: expanded, withIntermediateDirectories: true, attributes: nil)
            // Save persistent path
            try expanded.write(to: configURL, atomically: true, encoding: .utf8)
            targetDirectory = expanded
        } else if fileManager.fileExists(atPath: configURL.path) {
            // Load saved path
            let savedPath = try String(contentsOf: configURL, encoding: .utf8)
                .trimmingCharacters(in: .whitespacesAndNewlines)
            targetDirectory = savedPath
        } else {
            throw ValidationError("No output path provided and no persistent path found. Use --output-path to set one.")
        }

        // Print received inputs
        print("Category: \(category)")
        print("Description: \(description)")
        print("Output directory: \(targetDirectory)")

        // Prepare date strings
        let fileDateFormatter = DateFormatter()
        fileDateFormatter.dateFormat = "yyyy-MM-dd"
        let dateString = fileDateFormatter.string(from: Date())

        let timestampFormatter = DateFormatter()
        timestampFormatter.dateFormat = "yyyy-MM-dd HH-mm-ss"
        let timestampString = timestampFormatter.string(from: Date())

        // Sanitize description for filename
        let sanitizedDescription = description
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .replacingOccurrences(of: "\\s+", with: "_", options: .regularExpression)
            .replacingOccurrences(of: "[^A-Za-z0-9_-]", with: "", options: .regularExpression)

        // Build filename and paths
        let baseFilename = "\(dateString)-\(sanitizedDescription)"
        let outputFilename = "\(baseFilename).markdown"
        let fileURL = URL(fileURLWithPath: targetDirectory)
            .appendingPathComponent(outputFilename)

        // Prepare title for front matter (retain spaces)
        let titleString = description.replacingOccurrences(of: "_", with: " ")

        // Build markdown content
        let markdownContent = """
        ---
        title: \(titleString)
        date:  \(timestampString)
        layout: post
        comments: true
        categories: ['\(category)']
        ---
        """

        // Write the markdown file
        try markdownContent.write(to: fileURL, atomically: true, encoding: .utf8)
        print("Created markdown file: \(outputFilename) at \(targetDirectory)")

        // Open the file in Visual Studio Code
        do {
            let openProcess = Process()
            openProcess.executableURL = URL(fileURLWithPath: "/usr/bin/open")
            openProcess.arguments = ["-a", "/Applications/Visual Studio Code.app", fileURL.path]
            try openProcess.run()
        } catch {
            print("Failed to open file in VS Code: \(error)")
        }
    }
}

// Entry point
CLI.main()