text.go

  1package ygo
  2
  3/*
  4#include "libyrs.h"
  5#include <stdlib.h>
  6*/
  7import "C"
  8import (
  9	"encoding/json"
 10	"fmt"
 11	"unsafe"
 12)
 13
 14// Text represents a collaborative text type.
 15type Text struct {
 16	branch *C.Branch
 17}
 18
 19// GetText retrieves or creates a root-level YText with the given name.
 20func (d *Doc) GetText(name string) (*Text, error) {
 21	if d.ptr == nil {
 22		return nil, ErrNilDocument
 23	}
 24	cName := C.CString(name)
 25	defer C.free(unsafe.Pointer(cName))
 26
 27	branch := C.ytext(d.ptr, cName)
 28	if branch == nil {
 29		return nil, fmt.Errorf("failed to get or create text field %q", name)
 30	}
 31
 32	t := &Text{branch: branch}
 33	return t, nil
 34}
 35
 36// Destroy releases resources (does not delete the text from document).
 37func (t *Text) Destroy() {
 38	// Text is managed by document, no explicit destroy needed
 39}
 40
 41// Len returns the length of the text in UTF code units (based on doc encoding).
 42// Panics if the Text is nil or if txn is nil.
 43func (t *Text) Len(txn *Transaction) uint32 {
 44	if t.branch == nil {
 45		panic("ygo: Text.Len called on nil Text")
 46	}
 47	if txn == nil || txn.ptr == nil {
 48		panic("ygo: Text.Len called with nil transaction")
 49	}
 50	return uint32(C.ytext_len(t.branch, txn.ptr))
 51}
 52
 53// String returns the text content as a Go string.
 54func (t *Text) String(txn *Transaction) (string, error) {
 55	if t.branch == nil {
 56		return "", ErrNilBranch
 57	}
 58	if txn == nil || txn.ptr == nil {
 59		return "", ErrNilTransaction
 60	}
 61	return cStringToGoAndFree(C.ytext_string(t.branch, txn.ptr)), nil
 62}
 63
 64// Insert inserts text at the given index.
 65func (t *Text) Insert(txn *Transaction, index uint32, text string) error {
 66	if t.branch == nil {
 67		return ErrNilBranch
 68	}
 69	if txn == nil || txn.ptr == nil {
 70		return ErrNilTransaction
 71	}
 72	if !txn.IsWriteable() {
 73		return ErrNotWriteable
 74	}
 75	cText := C.CString(text)
 76	defer C.free(unsafe.Pointer(cText))
 77	C.ytext_insert(t.branch, txn.ptr, C.uint32_t(index), cText, nil)
 78	return nil
 79}
 80
 81// InsertWithAttributes inserts text with formatting attributes.
 82func (t *Text) InsertWithAttributes(txn *Transaction, index uint32, text string, attrs Input) error {
 83	if t.branch == nil {
 84		return ErrNilBranch
 85	}
 86	if txn == nil || txn.ptr == nil {
 87		return ErrNilTransaction
 88	}
 89	if !txn.IsWriteable() {
 90		return ErrNotWriteable
 91	}
 92	cText := C.CString(text)
 93	defer C.free(unsafe.Pointer(cText))
 94	C.ytext_insert(t.branch, txn.ptr, C.uint32_t(index), cText, &attrs.cInput)
 95	return nil
 96}
 97
 98// RemoveRange removes a range of text starting at index.
 99func (t *Text) RemoveRange(txn *Transaction, index, length uint32) error {
100	if t.branch == nil {
101		return ErrNilBranch
102	}
103	if txn == nil || txn.ptr == nil {
104		return ErrNilTransaction
105	}
106	if !txn.IsWriteable() {
107		return ErrNotWriteable
108	}
109	C.ytext_remove_range(t.branch, txn.ptr, C.uint32_t(index), C.uint32_t(length))
110	return nil
111}
112
113// Format applies formatting attributes to a text range.
114func (t *Text) Format(txn *Transaction, index, length uint32, attrs Input) error {
115	if t.branch == nil {
116		return ErrNilBranch
117	}
118	if txn == nil || txn.ptr == nil {
119		return ErrNilTransaction
120	}
121	if !txn.IsWriteable() {
122		return ErrNotWriteable
123	}
124	C.ytext_format(t.branch, txn.ptr, C.uint32_t(index), C.uint32_t(length), &attrs.cInput)
125	return nil
126}
127
128// Push appends text to the end.
129func (t *Text) Push(txn *Transaction, text string) error {
130	return t.Insert(txn, t.Len(txn), text)
131}
132
133// Branch returns the underlying branch pointer (for advanced use).
134func (t *Text) Branch() unsafe.Pointer {
135	return unsafe.Pointer(t.branch)
136}
137
138// MarshalJSONWithTxn implements JSON marshaling for Text.
139// Returns the text content as a JSON string.
140func (t *Text) MarshalJSONWithTxn(txn *Transaction) ([]byte, error) {
141	if t.branch == nil {
142		return nil, ErrNilBranch
143	}
144	if txn == nil || txn.ptr == nil {
145		return nil, ErrNilTransaction
146	}
147
148	content, err := t.String(txn)
149	if err != nil {
150		return nil, err
151	}
152
153	return json.Marshal(content)
154}