aboutsummaryrefslogtreecommitdiff
path: root/Map/Presentation/Base Components
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2025-12-14 20:21:24 +0100
committerRuben Beltran del Rio <jj@r.bdr.sh>2025-12-15 00:10:39 +0100
commit0d5e6636405dbe332c33c0fb82c7ccccb20f96cb (patch)
treea9cda2b711bbfc9277d66310440dd965b16682fc /Map/Presentation/Base Components
parenta5ae7aedc840a38505b3181f4e5ba92e90d94fa1 (diff)
Use wmap-parser-swift and tree-sitter-wmap for parsing and highlighting.
Diffstat (limited to 'Map/Presentation/Base Components')
-rw-r--r--Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift1
-rw-r--r--Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift1
-rw-r--r--Map/Presentation/Base Components/EvolutionPicker/GlassEvolutionPicker.swift1
-rw-r--r--Map/Presentation/Base Components/MapRender/MapAxes.swift2
-rw-r--r--Map/Presentation/Base Components/MapRender/MapBackground.swift11
-rw-r--r--Map/Presentation/Base Components/MapRender/MapEdges.swift1
-rw-r--r--Map/Presentation/Base Components/MapRender/MapGroup.swift3
-rw-r--r--Map/Presentation/Base Components/MapRender/MapGroups.swift2
-rw-r--r--Map/Presentation/Base Components/MapRender/MapMask.swift2
-rw-r--r--Map/Presentation/Base Components/MapRender/MapStages.swift3
-rw-r--r--Map/Presentation/Base Components/MapRender/MapVertices.swift4
-rw-r--r--Map/Presentation/Base Components/MapTextEditor/MapTextEditor.swift89
-rw-r--r--Map/Presentation/Base Components/SearchBar.swift1
13 files changed, 78 insertions, 43 deletions
diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift
index da67054..83d5009 100644
--- a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift
+++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPicker.swift
@@ -18,7 +18,6 @@ struct EvolutionPicker: View {
@State var isShowingMenu = false
@State var isHovered = false
- @FocusState var isFocused: Bool
@Binding var selectedEvolution: StageType
diff --git a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift
index b3eeb97..095c74c 100644
--- a/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift
+++ b/Map/Presentation/Base Components/EvolutionPicker/EvolutionPickerMenuHeader.swift
@@ -8,6 +8,7 @@ struct EvolutionPickerMenuHeader: View {
HStack(alignment: .center, spacing: Dimensions.Spacing.regular) {
Text(key)
.font(.Theme.Caption.emphasized)
+ .lineSpacing(Dimensions.LineHeight.caption - Dimensions.FontSize.caption)
.padding(.vertical, Dimensions.Spacing.cozy)
.textCase(.uppercase)
.padding(.leading, Dimensions.Spacing.regular)
diff --git a/Map/Presentation/Base Components/EvolutionPicker/GlassEvolutionPicker.swift b/Map/Presentation/Base Components/EvolutionPicker/GlassEvolutionPicker.swift
index 3b6f199..72a572a 100644
--- a/Map/Presentation/Base Components/EvolutionPicker/GlassEvolutionPicker.swift
+++ b/Map/Presentation/Base Components/EvolutionPicker/GlassEvolutionPicker.swift
@@ -18,7 +18,6 @@ import SwiftUI
struct GlassEvolutionPicker: View {
@State var isShowingMenu = false
- @FocusState var isFocused: Bool
@Binding var selectedEvolution: StageType
diff --git a/Map/Presentation/Base Components/MapRender/MapAxes.swift b/Map/Presentation/Base Components/MapRender/MapAxes.swift
index 9d0f43f..7c2b74b 100644
--- a/Map/Presentation/Base Components/MapRender/MapAxes.swift
+++ b/Map/Presentation/Base Components/MapRender/MapAxes.swift
@@ -19,7 +19,7 @@ struct MapAxes: View {
let mapSize: CGSize
let lineWidth: CGFloat
let evolution: Stage
- let stages: [CGFloat]
+ let stages: [Double]
let stageHeight = CGFloat(100.0)
let padding = CGFloat(5.0)
diff --git a/Map/Presentation/Base Components/MapRender/MapBackground.swift b/Map/Presentation/Base Components/MapRender/MapBackground.swift
index b33e791..710d549 100644
--- a/Map/Presentation/Base Components/MapRender/MapBackground.swift
+++ b/Map/Presentation/Base Components/MapRender/MapBackground.swift
@@ -14,14 +14,13 @@
// along with this program. If not, see https://map.tranquil.systems.
import Patterns
import SwiftUI
+import WmapParser
struct MapBackground: View {
let mapSize: CGSize
- let lineWidth: CGFloat
- let stages: [CGFloat]
- let opacity = 0.1
-
+ let stages: [Double]
+
var body: some View {
ZStack(alignment: .topLeading) {
PatternView(
@@ -57,6 +56,6 @@ struct MapBackground: View {
#Preview {
MapBackground(
- mapSize: CGSize(width: 200.0, height: 200.0), lineWidth: CGFloat(0.5),
- stages: [25.0, 50.0, 75.0])
+ mapSize: CGSize(width: 200.0, height: 200.0),
+ stages: [])
}
diff --git a/Map/Presentation/Base Components/MapRender/MapEdges.swift b/Map/Presentation/Base Components/MapRender/MapEdges.swift
index 3c6ef82..5819069 100644
--- a/Map/Presentation/Base Components/MapRender/MapEdges.swift
+++ b/Map/Presentation/Base Components/MapRender/MapEdges.swift
@@ -13,6 +13,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see https://map.tranquil.systems.
import SwiftUI
+import WmapParser
struct MapEdges: View {
diff --git a/Map/Presentation/Base Components/MapRender/MapGroup.swift b/Map/Presentation/Base Components/MapRender/MapGroup.swift
index a5877a8..ca5e954 100644
--- a/Map/Presentation/Base Components/MapRender/MapGroup.swift
+++ b/Map/Presentation/Base Components/MapRender/MapGroup.swift
@@ -22,7 +22,6 @@ struct MapGroup: View {
let group: [Vertex]
let color: Color
- let cornerSize = CGSize(width: 2.0, height: 2.0)
var strokeSize: CGFloat { 1.75 * vertexSize.width }
var hull: [CGPoint] {
@@ -92,6 +91,6 @@ struct MapGroup: View {
Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)),
Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square),
Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle),
- Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x),
+ Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .xMark),
], color: .red)
}
diff --git a/Map/Presentation/Base Components/MapRender/MapGroups.swift b/Map/Presentation/Base Components/MapRender/MapGroups.swift
index 1983dcd..149ea65 100644
--- a/Map/Presentation/Base Components/MapRender/MapGroups.swift
+++ b/Map/Presentation/Base Components/MapRender/MapGroups.swift
@@ -40,7 +40,7 @@ struct MapGroups: View {
Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)),
Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square),
Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle),
- Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x),
+ Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .xMark),
]
])
}
diff --git a/Map/Presentation/Base Components/MapRender/MapMask.swift b/Map/Presentation/Base Components/MapRender/MapMask.swift
index b477c0a..c4ba055 100644
--- a/Map/Presentation/Base Components/MapRender/MapMask.swift
+++ b/Map/Presentation/Base Components/MapRender/MapMask.swift
@@ -65,7 +65,7 @@ struct MapMask: View {
Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)),
Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square),
Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle),
- Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x),
+ Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .xMark),
],
labelPositions: [:])
}
diff --git a/Map/Presentation/Base Components/MapRender/MapStages.swift b/Map/Presentation/Base Components/MapRender/MapStages.swift
index 7d7e51e..bcd95a2 100644
--- a/Map/Presentation/Base Components/MapRender/MapStages.swift
+++ b/Map/Presentation/Base Components/MapRender/MapStages.swift
@@ -19,8 +19,7 @@ struct MapStages: View {
let mapSize: CGSize
let lineWidth: CGFloat
- let stages: [CGFloat]
- let opacity = 0.1
+ let stages: [Double]
var body: some View {
ZStack(alignment: .topLeading) {
diff --git a/Map/Presentation/Base Components/MapRender/MapVertices.swift b/Map/Presentation/Base Components/MapRender/MapVertices.swift
index 621c2f9..a3558fa 100644
--- a/Map/Presentation/Base Components/MapRender/MapVertices.swift
+++ b/Map/Presentation/Base Components/MapRender/MapVertices.swift
@@ -132,7 +132,7 @@ struct MapVertices: View {
to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y) + vertexSize.height))
path.closeSubpath()
}
- case .x:
+ case .xMark:
return Path { path in
path.move(to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y)))
path.addLine(
@@ -156,7 +156,7 @@ struct MapVertices: View {
Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)),
Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square),
Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle),
- Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x),
+ Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .xMark),
],
labelPositions: [:])
}
diff --git a/Map/Presentation/Base Components/MapTextEditor/MapTextEditor.swift b/Map/Presentation/Base Components/MapTextEditor/MapTextEditor.swift
index a1b357d..99fa684 100644
--- a/Map/Presentation/Base Components/MapTextEditor/MapTextEditor.swift
+++ b/Map/Presentation/Base Components/MapTextEditor/MapTextEditor.swift
@@ -14,17 +14,17 @@
// along with this program. If not, see https://map.tranquil.systems.
import Cocoa
import SwiftUI
+import WmapParser
+import SwiftTreeSitter
+import SwiftTreeSitterLayer
+import TreeSitterWmap
+
class MapTextEditorController: NSViewController {
@Binding var text: String
- var parsedMap: Wmap.ParsedMap {
- didSet {
- syntaxHighlighter.updateSyntaxElements(from: parsedMap)
- // Don't re-highlight entire document here - let the text change handler do it
- }
- }
+ var parsedMap: WmapParser.Map?
var highlightRanges: [Range<String.Index>] {
didSet {
@@ -41,17 +41,18 @@ class MapTextEditorController: NSViewController {
let onChange: () -> Void
- private let syntaxHighlighter = Wmap.SyntaxHighlighter()
private let changeDebouncer: Debouncer = Debouncer(seconds: 1)
private var trackingArea: NSTrackingArea?
private var hoverView: NSView?
+ private var rootLayer: LanguageLayer?
+
var hoverTimer: Timer?
var isHoveringValidationText = false
var isHoveringHoverView = false
init(
text: Binding<String>,
- parsedMap: Wmap.ParsedMap = Wmap.ParsedMap(entities: [], vertexLabels: Set()),
+ parsedMap: WmapParser.Map? = nil,
highlightRanges: [Range<String.Index>],
selectedRange: Int,
onChange: @escaping () -> Void
@@ -62,9 +63,16 @@ class MapTextEditorController: NSViewController {
self.highlightRanges = highlightRanges
self.selectedRange = selectedRange
super.init(nibName: nil, bundle: nil)
+
+ if let wmapConfiguration = try? LanguageConfiguration(tree_sitter_wmap(), name: "wmap") {
+ let languageConfiguration = LanguageLayer.Configuration(languageProvider: { name in
+ switch name {
+ case "wmap": return wmapConfiguration
+ default: return nil
+ }
+ })
+ self.rootLayer = try? LanguageLayer(languageConfig: wmapConfiguration, configuration: languageConfiguration)
- Task {
- syntaxHighlighter.updateSyntaxElements(from: parsedMap)
}
}
@@ -75,7 +83,7 @@ class MapTextEditorController: NSViewController {
override func loadView() {
let scrollView = NSTextView.scrollableTextView()
let textView = scrollView.documentView as! NSTextView
-
+
scrollView.translatesAutoresizingMaskIntoConstraints = false
textView.backgroundColor = .Theme.UI.background
@@ -87,7 +95,7 @@ class MapTextEditorController: NSViewController {
textView.font = NSFont.Theme.Editor.regular
textView.textColor = NSColor.Theme.Syntax.text
textView.textContainerInset = NSSize(
- width: Dimensions.Spacing.coziest, height: Dimensions.Spacing.coziest)
+ width: Dimensions.Spacing.regular, height: Dimensions.Spacing.regular)
// Configure text wrapping based on user preference
let softWrapLines = UserDefaults.standard.bool(forKey: "softWrapLines")
@@ -114,6 +122,7 @@ class MapTextEditorController: NSViewController {
textView.isVerticallyResizable = true
setupTrackingArea(for: textView)
+ rootLayer?.replaceContent(with: text)
self.view = scrollView
}
@@ -241,10 +250,10 @@ class MapTextEditorController: NSViewController {
var effectiveRange = NSRange()
let attributes = textStorage.attributes(at: characterIndex, effectiveRange: &effectiveRange)
- if let missinVertex = attributes[.init(rawValue: "MissingComponent")] as? String {
+ if let missingVertex = attributes[.init(rawValue: "MissingComponent")] as? String {
isHoveringValidationText = true
hoverTimer?.invalidate()
- showHoverView(for: effectiveRange, with: missinVertex, characterIndex: characterIndex)
+ showHoverView(for: effectiveRange, with: missingVertex, characterIndex: characterIndex)
} else {
isHoveringValidationText = false
scheduleHideHoverView()
@@ -346,17 +355,39 @@ class MapTextEditorController: NSViewController {
}
}
- private func getSyntaxElementAt(characterIndex: Int) -> Wmap.SyntaxElement? {
- let textStorage = currentTextView?.textStorage
- guard let textStorage = textStorage else { return nil }
+ private func applyTreeSitterHighlighting(textStorage: NSTextStorage, range: NSRange) {
+ guard let highlights = try? rootLayer?.highlights(in: range, provider: text.predicateTextProvider)
+ else { return }
+
+ for highlight in highlights {
+ let color = NSColor.Theme.Syntax.colorForSyntax(highlight.name)
+ var attributes: [NSAttributedString.Key: Any] = [
+ .foregroundColor: color
+ ]
- for element in syntaxHighlighter.cachedSyntaxElements {
- let nsRange = NSRange(element.range.stringRange, in: textStorage.string)
- if nsRange.contains(characterIndex) {
- return element
+ // Check for missing components
+ if UserDefaults.standard.bool(forKey: "useSmartEditor"),
+ let parsedMap,
+ highlight.name == "variable.component_label" {
+
+ // Extract the component label text from the range
+ let componentText = (textStorage.string as NSString).substring(with: highlight.range).trimmingCharacters(in: .whitespacesAndNewlines)
+
+ // Check if this component exists in the parsed map
+ let componentExists = parsedMap.components.contains(where: {
+ $0.label.lowercased() == componentText.lowercased()
+ })
+
+ if !componentExists && UserDefaults.standard.bool(forKey: "highlightMissingComponents") {
+ attributes[.underlineStyle] =
+ NSUnderlineStyle.thick.rawValue | NSUnderlineStyle.patternDot.rawValue
+ attributes[.underlineColor] = NSColor.Theme.Syntax.error
+ attributes[.init("MissingComponent")] = componentText
+ }
}
+
+ textStorage.addAttributes(attributes, range: highlight.range)
}
- return nil
}
}
@@ -400,6 +431,13 @@ extension MapTextEditorController: NSTextStorageDelegate {
}
let editedRange = textStorage.editedRange
+ let content = textStorage.string
+
+ // Update tree-sitter layer with new content
+ Task { @MainActor in
+ rootLayer?.replaceContent(with: content)
+ }
+
if editedRange.location != NSNotFound {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
guard let self = self,
@@ -432,21 +470,22 @@ extension MapTextEditorController: NSTextStorageDelegate {
// Set default text color for the range
textStorage.addAttribute(.foregroundColor, value: NSColor.Theme.Syntax.text, range: range)
- syntaxHighlighter.applySyntaxHighlighting(textStorage: textStorage, range: range)
+ // Apply tree-sitter syntax highlighting
+ applyTreeSitterHighlighting(textStorage: textStorage, range: range)
}
}
struct MapTextEditor: NSViewControllerRepresentable {
@Binding var text: String
- var parsedMap: Wmap.ParsedMap
+ var parsedMap: WmapParser.Map?
var highlightRanges: [Range<String.Index>]
var selectedRange: Int
var onChange: () -> Void = {}
init(
text: Binding<String>,
- parsedMap: Wmap.ParsedMap = Wmap.ParsedMap(entities: [], vertexLabels: Set()),
+ parsedMap: WmapParser.Map? = nil,
highlightRanges: [Range<String.Index>] = [], selectedRange: Int = 0,
onChange: @escaping () -> Void = {}
) {
diff --git a/Map/Presentation/Base Components/SearchBar.swift b/Map/Presentation/Base Components/SearchBar.swift
index cf19ddd..706b66f 100644
--- a/Map/Presentation/Base Components/SearchBar.swift
+++ b/Map/Presentation/Base Components/SearchBar.swift
@@ -20,7 +20,6 @@ struct SearchBar: View {
@FocusState var isSearchFocused: Bool
var onNext: () -> Void = {}
var onPrevious: () -> Void = {}
- var onSubmit: () -> Void = {}
var onDismiss: () -> Void = {}
var body: some View {