package acedoc import ( "strings" "sync" ) type Document struct { mtx sync.RWMutex lines []string deltas []Delta clients []*Client logger *Client } type DeltaHandler interface { Handle([]Delta) error } type DeltaHandlerFunc func([]Delta) error func (fn DeltaHandlerFunc) Handle(d []Delta) error { return fn(d) } func NewString(str string) *Document { d := &Document{ lines: strings.Split(str, "\n"), } return d } func (d *Document) nLines() uint { n := uint(len(d.lines)) if n == 0 { n = 1 } return n } func (d Delta) nLines() uint { n := uint(len(d.Lines)) if n == 0 { n = 1 } return n } func (d Document) line(i uint) string { if i >= uint(len(d.lines)) { return "" } return d.lines[i] } func (d Delta) line(i uint) string { if i >= uint(len(d.Lines)) { return "" } return d.Lines[i] } func (d Delta) nRows() uint { r := d.End.Row - d.Start.Row r += 1 if r == 0 { return 1 } return r } func (d Delta) rows() int { r := int(d.End.Row) - int(d.Start.Row) return r } func (d Delta) cols() int { if d.Start.Row == d.End.Row { return int(d.End.Column) - int(d.Start.Column) } else { return int(d.End.Column) } } func (d *Document) Contents() string { d.mtx.RLock() defer d.mtx.RUnlock() return d.contents() } func (d *Document) contents() string { return strings.Join(d.lines, "\n") } type Position struct { Row uint `json:"row"` Column uint `json:"column"` } func (d *Document) InDocument(pos Position) bool { if pos.Row > d.nLines() { return false } line := d.line(pos.Row) if pos.Column > uint(len(line)) { return false } return true }