@ -2,6 +2,7 @@ package acedoc
import (
"fmt"
"math"
"strings"
)
@ -60,7 +61,6 @@ func (d DeltaAction) MarshalJSON() ([]byte, error) {
}
func ( d * DeltaAction ) UnmarshalJSON ( b [ ] byte ) error {
fmt . Println ( string ( b ) )
if string ( b ) == "null" {
return nil
}
@ -81,6 +81,10 @@ type Delta struct {
source * Client
}
func ( d Delta ) String ( ) string {
return fmt . Sprintf ( "%s:%q(%v->%v)" , d . Action , strings . Join ( d . Lines , "\n" ) , d . Start , d . End )
}
func ( d Delta ) Equal ( other Delta ) bool {
if d . Start != other . Start {
return false
@ -108,24 +112,33 @@ func (d Delta) Equal(other Delta) bool {
}
func Remove ( row , col uint , str string ) Delta {
lines := strings . Split ( str , "\n" )
nlines := len ( lines ) - 1
return Delta {
Action : DeltaRemove ,
Lines : lines ,
Start : Position { row , col } ,
End : Position { row + uint ( nlines ) , uint ( len ( lines [ nlines ] ) ) } ,
}
dl := Insert ( row , col , str )
dl . Action = DeltaRemove
return dl
}
func Insert ( row , col uint , str string ) Delta {
lines := strings . Split ( str , "\n" )
nlines := uint ( len ( lines ) - 1 )
var endcol uint
addedLines := uint ( len ( lines ) - 1 )
if len ( lines ) == 0 {
addedLines = 1
} else {
lastLine := lines [ len ( lines ) - 1 ]
endcol += uint ( len ( lastLine ) )
}
if addedLines == 0 {
endcol += col
}
return Delta {
Action : DeltaInsert ,
Lines : lines ,
Start : Position { row , col } ,
End : Position { row + nlines , uint ( len ( lines [ nlines ] ) ) } ,
End : Position { row + addedLines , endcol } ,
}
}
@ -133,15 +146,18 @@ func (d *Document) applyInsert(dl Delta) {
row := dl . Start . Row
col := dl . Start . Column
line := d . lines [ row ]
if uint ( len ( d . lines ) ) == row {
d . lines = append ( d . lines , "" )
}
line := d . line ( row )
if dl . nLines ( ) == 1 {
d . lines [ row ] = line [ : col ] + dl . line ( 0 ) + line [ col : ]
} else {
newlines := [ ] string { }
if row != 0 {
newlines = append ( newlines , d . lines [ : row - 1 ] ... ) // old content
}
newlines = append ( newlines , d . lines [ : row ] ... ) // old content
newlines = append ( newlines , d . lines [ row ] [ : col ] + dl . Lines [ 0 ] )
newlines = append ( newlines , dl . Lines [ 1 : ] ... ) // new content
newlines [ len ( newlines ) - 1 ] += d . lines [ row ] [ col : ]
@ -204,11 +220,11 @@ func (d *Document) Apply(dls ...Delta) error {
func ( d * Document ) validate ( dl Delta ) error {
if ! d . InDocument ( dl . Start ) {
return fmt . Errorf ( "start is not in document" )
return fmt . Errorf ( "start %v is not in document %q " , dl . Start , d . contents ( ) )
}
if dl . Action == DeltaRemove && ! d . InDocument ( dl . End ) {
return fmt . Errorf ( "end is not in document for remove" )
return fmt . Errorf ( "end %v is not in document %q for remove" , dl . End , d . contents ( ) )
}
if dl . nLines ( ) != dl . nRows ( ) {
@ -217,8 +233,8 @@ func (d *Document) validate(dl Delta) error {
lastDlLine := dl . line ( dl . nRows ( ) - 1 )
if uint ( len ( lastDlLine ) ) != dl . cols ( ) {
return fmt . Errorf ( "delta has %d chars on the final line, but positions show range of %d chars" , len ( lastDlLine ) , dl . cols ( ) )
if ! ( len ( lastDlLine ) == 0 && dl . cols ( ) < 0 ) && len ( lastDlLine ) != int ( math . Abs ( float64 ( dl . cols ( ) ) ) ) {
return fmt . Errorf ( "delta %v has %d chars on the final line, but positions (%v -> %v) show range of %d chars" , dl , len ( lastDlLine ) , dl . Start , dl . End , dl . cols ( ) )
}
return nil