forked from CodeEditApp/CodeEditSourceEditor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathContentView.swift
More file actions
123 lines (113 loc) · 4.29 KB
/
ContentView.swift
File metadata and controls
123 lines (113 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//
// ContentView.swift
// CodeEditSourceEditorExample
//
// Created by Khan Winter on 2/24/24.
//
import SwiftUI
import CodeEditSourceEditor
import CodeEditLanguages
import CodeEditTextView
struct ContentView: View {
@Binding var document: CodeEditSourceEditorExampleDocument
let fileURL: URL?
@State private var language: CodeLanguage = .default
@State private var theme: EditorTheme = .standard
@State private var font: NSFont = NSFont.monospacedSystemFont(ofSize: 12, weight: .regular)
@AppStorage("wrapLines") private var wrapLines: Bool = true
@State private var cursorPositions: [CursorPosition] = []
@AppStorage("systemCursor") private var useSystemCursor: Bool = false
@State private var isInLongParse = false
init(document: Binding<CodeEditSourceEditorExampleDocument>, fileURL: URL?) {
self._document = document
self.fileURL = fileURL
}
var body: some View {
VStack(spacing: 0) {
HStack {
Text("Language")
LanguagePicker(language: $language)
.frame(maxWidth: 100)
Toggle("Wrap Lines", isOn: $wrapLines)
if #available(macOS 14, *) {
Toggle("Use System Cursor", isOn: $useSystemCursor)
} else {
Toggle("Use System Cursor", isOn: $useSystemCursor)
.disabled(true)
.help("macOS 14 required")
}
Spacer()
Text(getLabel(cursorPositions))
}
.padding(4)
.zIndex(2)
.background(Color(NSColor.windowBackgroundColor))
Divider()
ZStack {
if isInLongParse {
VStack {
HStack {
Spacer()
Text("Parsing document...")
Spacer()
}
.padding(4)
.background(Color(NSColor.windowBackgroundColor))
Spacer()
}
.zIndex(2)
.transition(.opacity)
}
CodeEditSourceEditor(
$document.text,
language: language,
theme: theme,
font: font,
tabWidth: 4,
lineHeight: 1.2,
wrapLines: wrapLines,
cursorPositions: $cursorPositions,
useSystemCursor: useSystemCursor
)
}
}
.onAppear {
self.language = detectLanguage(fileURL: fileURL) ?? .default
}
.onReceive(NotificationCenter.default.publisher(for: TreeSitterClient.Constants.longParse)) { _ in
withAnimation(.easeIn(duration: 0.1)) {
isInLongParse = true
}
}
.onReceive(NotificationCenter.default.publisher(for: TreeSitterClient.Constants.longParseFinished)) { _ in
withAnimation(.easeIn(duration: 0.1)) {
isInLongParse = false
}
}
}
private func detectLanguage(fileURL: URL?) -> CodeLanguage? {
guard let fileURL else { return nil }
return CodeLanguage.detectLanguageFrom(
url: fileURL,
prefixBuffer: document.text.getFirstLines(5),
suffixBuffer: document.text.getLastLines(5)
)
}
/// Create a label string for cursor positions.
/// - Parameter cursorPositions: The cursor positions to create the label for.
/// - Returns: A string describing the user's location in a document.
func getLabel(_ cursorPositions: [CursorPosition]) -> String {
if cursorPositions.isEmpty {
return ""
}
// More than one selection, display the number of selections.
if cursorPositions.count > 1 {
return "\(cursorPositions.count) selected ranges"
}
// When there's a single cursor, display the line and column.
return "Line: \(cursorPositions[0].line) Col: \(cursorPositions[0].column) Range: \(cursorPositions[0].range)"
}
}
#Preview {
ContentView(document: .constant(CodeEditSourceEditorExampleDocument()), fileURL: nil)
}