add FileFormat enum and file tracking to AppState
This commit is contained in:
parent
23cdf0f8ee
commit
93d00f4282
|
|
@ -1,6 +1,82 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
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 {
|
class AppState: ObservableObject {
|
||||||
@Published var documentText: String = "" {
|
@Published var documentText: String = "" {
|
||||||
didSet {
|
didSet {
|
||||||
|
|
@ -16,6 +92,8 @@ class AppState: ObservableObject {
|
||||||
@Published var currentNoteID: UUID
|
@Published var currentNoteID: UUID
|
||||||
@Published var selectedNoteIDs: Set<UUID> = []
|
@Published var selectedNoteIDs: Set<UUID> = []
|
||||||
@Published var modified: Bool = false
|
@Published var modified: Bool = false
|
||||||
|
@Published var currentFileURL: URL? = nil
|
||||||
|
@Published var currentFileFormat: FileFormat = .markdown
|
||||||
|
|
||||||
private let bridge = RustBridge.shared
|
private let bridge = RustBridge.shared
|
||||||
private var autoSaveTimer: DispatchSourceTimer?
|
private var autoSaveTimer: DispatchSourceTimer?
|
||||||
|
|
@ -120,6 +198,8 @@ class AppState: ObservableObject {
|
||||||
documentText = ""
|
documentText = ""
|
||||||
evalResults = [:]
|
evalResults = [:]
|
||||||
modified = false
|
modified = false
|
||||||
|
currentFileURL = nil
|
||||||
|
currentFileFormat = .markdown
|
||||||
refreshNoteList()
|
refreshNoteList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,6 +242,9 @@ class AppState: ObservableObject {
|
||||||
|
|
||||||
func saveNote() {
|
func saveNote() {
|
||||||
bridge.setText(currentNoteID, text: documentText)
|
bridge.setText(currentNoteID, text: documentText)
|
||||||
|
if let url = currentFileURL {
|
||||||
|
let _ = bridge.saveNote(currentNoteID, path: url.path)
|
||||||
|
}
|
||||||
let _ = bridge.cacheSave(currentNoteID)
|
let _ = bridge.cacheSave(currentNoteID)
|
||||||
modified = false
|
modified = false
|
||||||
refreshNoteList()
|
refreshNoteList()
|
||||||
|
|
@ -169,6 +252,8 @@ class AppState: ObservableObject {
|
||||||
|
|
||||||
func saveNoteToFile(_ url: URL) {
|
func saveNoteToFile(_ url: URL) {
|
||||||
let _ = bridge.saveNote(currentNoteID, path: url.path)
|
let _ = bridge.saveNote(currentNoteID, path: url.path)
|
||||||
|
currentFileURL = url
|
||||||
|
currentFileFormat = FileFormat.from(filename: url.lastPathComponent)
|
||||||
modified = false
|
modified = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +261,8 @@ class AppState: ObservableObject {
|
||||||
if let (id, text) = bridge.loadNote(path: url.path) {
|
if let (id, text) = bridge.loadNote(path: url.path) {
|
||||||
currentNoteID = id
|
currentNoteID = id
|
||||||
documentText = text
|
documentText = text
|
||||||
|
currentFileURL = url
|
||||||
|
currentFileFormat = FileFormat.from(filename: url.lastPathComponent)
|
||||||
modified = false
|
modified = false
|
||||||
let _ = bridge.cacheSave(id)
|
let _ = bridge.cacheSave(id)
|
||||||
evaluate()
|
evaluate()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue