Skip to content

🐞 CodeEditTextView Does Not Update When Binding Changes Programmatically #213

@nkleemann

Description

@nkleemann

Description

When trying to programmatically insert text at the cursor position (or anywhere) in a CodeEditTextView, there is an observed issue where the data model (the text binding) updates as expected, but these changes are not reflected in the CodeEditTextView. This occurs when the binding changes are made programmatically, without any key presses.

To help debugging this I created a minimal example. As you can see, when appending content to the code Binding, neither the cursor position nor the code displayed in the View updates as expected.

struct ContentView: View {
    
    // text we want to programmatically append
    @State var codeToAppend = ""
    
    // managed by editor
    @State var code = ""
    @State var cursorPosition = (1, 1)

    var body: some View {
        
        VStack {
            HStack {
                TextField("code to append..", text: $codeToAppend)
                Button {
                    self.code.append(codeToAppend)
                } label: {
                    Text("append")
                }
            }

            CodeEditTextView(
                $code,
                language: .swift,
                theme: Foo.theme,
                font: Foo.font,
                tabWidth: Foo.tabWidth,
                lineHeight: Foo.lineHeight,
                wrapLines: Foo.wrapLines,
                editorOverscroll: Foo.editorOverscroll,
                cursorPosition: $cursorPosition
            )
            
            HStack {
                Text("line: \(cursorPosition.0) col: \(cursorPosition.1)")
                Text("# of chars in editor: \(code.count)")
            }
        }
        .padding()
    }
}

// ignore
struct Foo {
    static let theme = EditorTheme(
        text:           .init(hex: "#F6F7EE"),
        insertionPoint: .init(hex: "#9E9F9D"),
        invisibles:     .init(hex: "#343b59", alpha: 0.6),
        background:     .init(hex: "#000000"), 
        lineHighlight:  .init(hex: "#151515", alpha: 0.3),
        selection:      .init(hex: "#A5CDFF"),
        keywords:       .init(hex: "#F074D5"),
        commands:       .init(hex: "#34548a"),
        types:          .init(hex: "#8f5e15"),
        attributes:     .init(hex: "#9399FF"),
        variables:      .init(hex: "#9399FF"),
        values:         .init(hex: "#9399FF"),
        numbers:        .init(hex: "#67B7A4"),
        strings:        .init(hex: "#67B7A4"),
        characters:     .init(hex: "#0f4b6e"),
        comments:       .init(hex: "#414141")
    )
    static let font = NSFont.monospacedSystemFont(ofSize: 11, weight: .regular)
    static let tabWidth = 4
    static let lineHeight = 1.2
    static let editorOverscroll = 0.3
    static let wrapLines = true
}

To Reproduce

Use my provided, minimal example.

Expected Behavior

Changes to the underlying Bindings (code and cursor position) should be reflected in the View. This will become especially important when developing autocompletion features.

Version Information

CodeEditTextView: [e.g. 0.x.y]
macOS: [e.g. 13.2.1]
Xcode: [e.g. 14.2]

Additional Context

No response

Screenshots

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    🏁 Complete

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions