From 93d00f428234005b7ff4011827f50c8b0759fa32 Mon Sep 17 00:00:00 2001 From: jess Date: Mon, 6 Apr 2026 13:23:18 -0700 Subject: [PATCH] add FileFormat enum and file tracking to AppState --- src/AppState.swift | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/AppState.swift b/src/AppState.swift index 5086fd8..12ae056 100644 --- a/src/AppState.swift +++ b/src/AppState.swift @@ -1,6 +1,82 @@ import Foundation import Combine +enum FileFormat: String, CaseIterable { + case markdown, csv, json, toml, yaml, xml, svg + case rust, c, cpp, objc + case javascript, typescript, jsx, tsx + case html, css, scss, less + case python, go, ruby, php, lua + case shell, java, kotlin, swift, zig, sql + case makefile, dockerfile + case config, lock, plainText + case unknown + + static func from(extension ext: String) -> FileFormat { + switch ext.lowercased() { + case "md", "markdown", "mdown": return .markdown + case "csv": return .csv + case "json": return .json + case "toml": return .toml + case "yaml", "yml": return .yaml + case "xml": return .xml + case "svg": return .svg + case "rs": return .rust + case "c": return .c + case "cpp", "cc", "cxx": return .cpp + case "h", "hpp", "hxx": return .cpp + case "m": return .objc + case "js": return .javascript + case "jsx": return .jsx + case "ts": return .typescript + case "tsx": return .tsx + case "html", "htm": return .html + case "css": return .css + case "scss": return .scss + case "less": return .less + case "py": return .python + case "go": return .go + case "rb": return .ruby + case "php": return .php + case "lua": return .lua + case "sh", "bash", "zsh", "fish": return .shell + case "java": return .java + case "kt", "kts": return .kotlin + case "swift": return .swift + case "zig": return .zig + case "sql": return .sql + case "mk": return .makefile + case "ini", "cfg", "conf", "env": return .config + case "lock": return .lock + case "txt", "text", "log": return .plainText + default: return .unknown + } + } + + static func from(filename: String) -> FileFormat { + let lower = filename.lowercased() + if lower == "makefile" { return .makefile } + if lower == "dockerfile" { return .dockerfile } + let ext = (filename as NSString).pathExtension + if ext.isEmpty { return .unknown } + return from(extension: ext) + } + + var isCode: Bool { + switch self { + case .rust, .c, .cpp, .objc, .javascript, .typescript, .jsx, .tsx, + .html, .css, .scss, .less, .python, .go, .ruby, .php, .lua, + .shell, .java, .kotlin, .swift, .zig, .sql, .makefile, .dockerfile: + return true + default: + return false + } + } + + var isMarkdown: Bool { self == .markdown } + var isCSV: Bool { self == .csv } +} + class AppState: ObservableObject { @Published var documentText: String = "" { didSet { @@ -16,6 +92,8 @@ class AppState: ObservableObject { @Published var currentNoteID: UUID @Published var selectedNoteIDs: Set = [] @Published var modified: Bool = false + @Published var currentFileURL: URL? = nil + @Published var currentFileFormat: FileFormat = .markdown private let bridge = RustBridge.shared private var autoSaveTimer: DispatchSourceTimer? @@ -120,6 +198,8 @@ class AppState: ObservableObject { documentText = "" evalResults = [:] modified = false + currentFileURL = nil + currentFileFormat = .markdown refreshNoteList() } @@ -162,6 +242,9 @@ class AppState: ObservableObject { func saveNote() { bridge.setText(currentNoteID, text: documentText) + if let url = currentFileURL { + let _ = bridge.saveNote(currentNoteID, path: url.path) + } let _ = bridge.cacheSave(currentNoteID) modified = false refreshNoteList() @@ -169,6 +252,8 @@ class AppState: ObservableObject { func saveNoteToFile(_ url: URL) { let _ = bridge.saveNote(currentNoteID, path: url.path) + currentFileURL = url + currentFileFormat = FileFormat.from(filename: url.lastPathComponent) modified = false } @@ -176,6 +261,8 @@ class AppState: ObservableObject { if let (id, text) = bridge.loadNote(path: url.path) { currentNoteID = id documentText = text + currentFileURL = url + currentFileFormat = FileFormat.from(filename: url.lastPathComponent) modified = false let _ = bridge.cacheSave(id) evaluate()