native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #122 from supabitapp/issue-117-root-cause

Fix smart punctuation substitution in script editors

authored by

khoi and committed by
GitHub
e094c768 d1287fce

+78 -6
+4 -2
supacode/App/ContentView.swift
··· 160 160 } 161 161 162 162 ZStack(alignment: .topLeading) { 163 - TextEditor(text: $script) 164 - .font(.body.monospaced()) 163 + PlainTextEditor( 164 + text: $script, 165 + isMonospaced: true 166 + ) 165 167 .frame(minHeight: 160) 166 168 if script.isEmpty { 167 169 Text("npm run dev")
+2 -4
supacode/Features/Settings/Views/RepositorySettingsView.swift
··· 94 94 } 95 95 Section { 96 96 ZStack(alignment: .topLeading) { 97 - TextEditor( 97 + PlainTextEditor( 98 98 text: settings.setupScript 99 99 ) 100 - .font(.body) 101 100 .frame(minHeight: 120) 102 101 if store.settings.setupScript.isEmpty { 103 102 Text("claude --dangerously-skip-permissions") ··· 116 115 } 117 116 Section { 118 117 ZStack(alignment: .topLeading) { 119 - TextEditor( 118 + PlainTextEditor( 120 119 text: settings.runScript 121 120 ) 122 - .font(.body) 123 121 .frame(minHeight: 120) 124 122 if store.settings.runScript.isEmpty { 125 123 Text("npm run dev")
+72
supacode/Support/PlainTextEditor.swift
··· 1 + import AppKit 2 + import SwiftUI 3 + 4 + struct PlainTextEditor: NSViewRepresentable { 5 + @Binding var text: String 6 + var isMonospaced: Bool = false 7 + 8 + func makeCoordinator() -> Coordinator { 9 + Coordinator(text: $text) 10 + } 11 + 12 + func makeNSView(context: Context) -> NSScrollView { 13 + let textView = NSTextView(frame: .zero) 14 + textView.delegate = context.coordinator 15 + textView.drawsBackground = false 16 + textView.isRichText = false 17 + textView.importsGraphics = false 18 + textView.isAutomaticDashSubstitutionEnabled = false 19 + textView.isAutomaticQuoteSubstitutionEnabled = false 20 + textView.isAutomaticTextReplacementEnabled = false 21 + textView.font = editorFont 22 + textView.textContainerInset = NSSize(width: 4, height: 6) 23 + textView.minSize = NSSize(width: 0, height: 0) 24 + textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude) 25 + textView.isVerticallyResizable = true 26 + textView.isHorizontallyResizable = false 27 + textView.autoresizingMask = [.width] 28 + textView.textContainer?.containerSize = NSSize(width: 0, height: CGFloat.greatestFiniteMagnitude) 29 + textView.textContainer?.widthTracksTextView = true 30 + textView.string = text 31 + 32 + let scrollView = NSScrollView(frame: .zero) 33 + scrollView.drawsBackground = false 34 + scrollView.borderType = .noBorder 35 + scrollView.hasVerticalScroller = true 36 + scrollView.hasHorizontalScroller = false 37 + scrollView.autohidesScrollers = true 38 + scrollView.documentView = textView 39 + return scrollView 40 + } 41 + 42 + func updateNSView(_ nsView: NSScrollView, context: Context) { 43 + guard let textView = nsView.documentView as? NSTextView else { return } 44 + if textView.string != text { 45 + textView.string = text 46 + } 47 + let updatedFont = editorFont 48 + if textView.font != updatedFont { 49 + textView.font = updatedFont 50 + } 51 + } 52 + 53 + private var editorFont: NSFont { 54 + if isMonospaced { 55 + return NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular) 56 + } 57 + return NSFont.preferredFont(forTextStyle: .body) 58 + } 59 + 60 + final class Coordinator: NSObject, NSTextViewDelegate { 61 + @Binding var text: String 62 + 63 + init(text: Binding<String>) { 64 + _text = text 65 + } 66 + 67 + func textDidChange(_ notification: Notification) { 68 + guard let textView = notification.object as? NSTextView else { return } 69 + text = textView.string 70 + } 71 + } 72 + }